> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Correggere automaticamente le build CI non riuscite

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Correzione automatica dei build CI non riusciti" description="Aggiungi una GitHub Action che chiama Devin per correggere i build CI non riusciti nelle tue PR." prompt="Aiutami a configurare una GitHub Action che attivi automaticamente Devin per correggere i build CI non riusciti. Segui la guida su https://docs.devin.ai/use-cases/gallery/api-github-actions-ci-fix e accompagnami in ogni passaggio: memorizzare l'API key, aggiungere il file di workflow e configurarlo in modo che agisca solo sugli errori rilevanti." category="Automazioni" features="API" />

<div className="uc-detail-wrapper">
  <Tip>Non vuoi configurare tutto manualmente? Incolla un collegamento a questa pagina in una sessione di Devin e chiedigli di configurare tutto per te.</Tip>

  <Steps>
    <Step title="Salva la tua chiave API di Devin in GitHub">
      Il workflow chiama le [API v3 di Devin](/it/api-reference/v3/overview) per creare sessioni in modo programmatico. Crea un utente di servizio e salva il suo token come segreto di GitHub Actions:

      1. Vai su [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** e crea un utente di servizio con il permesso `ManageOrgSessions`
      2. Copia il token API mostrato dopo la creazione — viene visualizzato una sola volta
      3. Nel tuo repository GitHub, vai su **Settings > Secrets and variables > Actions**
      4. Aggiungi due segreti: `DEVIN_API_KEY` (il token) e `DEVIN_ORG_ID` (l'ID della tua organizzazione — ottienilo chiamando `GET https://api.devin.ai/v3/enterprise/organizations` con il tuo token)

      Assicurati che il repository sia già [configurato sulla Machine di Devin](/it/onboard-devin/environment) così che Devin possa clonarlo, compilarlo e fare push.
    </Step>

    <Step title="Aggiungi il file del workflow">
      Crea `.github/workflows/devin-ci-fix.yml`. Questo workflow si attiva ogni volta che il tuo workflow CI esistente termina con un errore, estrae i nomi dei job falliti e chiama le [API di Devin](/it/api-reference/v3/sessions/post-organizations-sessions) per avviare una sessione di correzione:

      ```yaml theme={null}
      name: Auto-fix CI with Devin

      on:
        workflow_run:
          workflows: ["CI"]
          types: [completed]

      jobs:
        trigger-devin-fix:
          if: >
            github.event.workflow_run.conclusion == 'failure' &&
            github.event.workflow_run.pull_requests[0]
          runs-on: ubuntu-latest
          steps:
            - name: Get failure details
              id: failure
              uses: actions/github-script@v7
              with:
                script: |
                  const run = context.payload.workflow_run;
                  const pr = run.pull_requests[0];
                  const jobs = await github.rest.actions.listJobsForWorkflowRun({
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    run_id: run.id
                  });
                  const failed = jobs.data.jobs
                    .filter(j => j.conclusion === 'failure')
                    .map(j => j.name);
                  core.setOutput('pr_number', pr.number);
                  core.setOutput('branch', pr.head.ref);
                  core.setOutput('failed_jobs', failed.join(', '));
                  core.setOutput('run_url', run.html_url);

            - name: Trigger Devin session
              run: |
                curl -s -X POST "https://api.devin.ai/v3/organizations/${{ secrets.DEVIN_ORG_ID }}/sessions" \
                  -H "Authorization: Bearer ${{ secrets.DEVIN_API_KEY }}" \
                  -H "Content-Type: application/json" \
                  -d "{
                    \"prompt\": \"CI failed on PR #${{ steps.failure.outputs.pr_number }} in ${{ github.repository }}. Failed jobs: ${{ steps.failure.outputs.failed_jobs }}. Run: ${{ steps.failure.outputs.run_url }}. Branch: ${{ steps.failure.outputs.branch }}. Read the CI logs, identify the root cause, and push a fix to the branch.\"
                  }"
      ```

      Sostituisci `"CI"` nell'array `workflows` con il `name:` esatto del tuo file di workflow CI esistente (es. `"Tests"`, `"Build & Test"`).

      Usa il campo `tags` nel corpo della richiesta (es. `"tags": ["ci-fix", "pr-312"]`) per tenere traccia di quali errori CI hanno già avviato sessioni ed evitare duplicati.
    </Step>

    <Step title="Cosa succede quando la CI fallisce">
      Quando la CI di una PR fallisce, l'Action estrae i dettagli dell'errore e li passa a Devin come prompt di sessione. Ecco un tipico flusso di correzione automatica:

      1. **Legge i log della CI** — Devin apre l'URL dell'esecuzione e analizza l'output degli errori, gli stack trace e i risultati dei test dai job falliti
      2. **Risale all'errore nel codice** — Individua il file e la riga rilevanti nel branch della PR (es. `UserList.tsx:34`) e legge il codice circostante e il diff recente
      3. **Fa push di una correzione** — Esegue il commit di una modifica mirata direttamente nel branch della PR, che ri-attiva automaticamente la CI
      4. **Commenta sulla PR** — Pubblica un riepilogo che spiega la causa principale e cosa è stato modificato

      Esempio di commento sulla PR da parte di Devin:

      ```
      CI failure in test-unit — fixed

      Root cause: `UserList.tsx:34` calls `.map()` on `props.users`, which is
      undefined when the API returns an empty response body instead of `[]`.

      Fix: Added a fallback — `const users = props.users ?? [];`
      Added a test case for the empty-response scenario.
      All 312 tests passing.
      ```

      <PromptBlock>
        ```txt Analizza un test instabile theme={null}
        L'errore in CI era in realtà dovuto a un test instabile: va a buon fine al nuovo tentativo. Analizza
        il test in src/__tests__/UserList.test.tsx e correggi l'instabilità. Verifica
        se è un problema di timing, una race condition o una mancata pulizia tra un'esecuzione e l'altra.
        ```
      </PromptBlock>
    </Step>

    <Step title="Limita l'ambito agli errori corretti">
      Non tutti gli errori in CI traggono beneficio da una correzione automatica: i timeout dell'infrastruttura e i problemi di build Docker non verranno risolti da una modifica al codice. Aggiungi una condizione in modo che solo gli errori dei job rilevanti attivino Devin:

      ```yaml theme={null}
            - name: Trigger Devin session
              if: >
                contains(steps.failure.outputs.failed_jobs, 'test') ||
                contains(steps.failure.outputs.failed_jobs, 'lint') ||
                contains(steps.failure.outputs.failed_jobs, 'typecheck')
              run: |
                curl -s -X POST "https://api.devin.ai/v3/organizations/${{ secrets.DEVIN_ORG_ID }}/sessions" \
                ...
      ```

      ### Mantieni le correzioni facili da rivedere

      Devin esegue un commit di correzione, ma la PR richiede comunque una revisione umana prima del merge. Considera le correzioni automatiche come un punto di partenza per lo sviluppatore, non come un sostituto della revisione del codice. Se Devin non riesce a risolvere il problema, aggiunge un commento alla PR spiegando cosa ha trovato, così un ingegnere può riprendere il lavoro da lì.
    </Step>
  </Steps>
</div>
