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

# Correction automatique des builds CI échoués

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="Correction automatique des builds CI en échec" description="Ajoutez une GitHub Action qui appelle Devin pour corriger les builds CI en échec sur vos PR." prompt="Aidez-moi à configurer une GitHub Action qui déclenche automatiquement Devin pour corriger les builds CI en échec. Suivez le guide à l’adresse https://docs.devin.ai/use-cases/gallery/api-github-actions-ci-fix et faites-moi parcourir chaque étape : stockage de l’API key, ajout du fichier de workflow et définition de son périmètre pour les bons types d’échecs." category="Automatisations" features="API" />

<div className="uc-detail-wrapper">
  <Tip>Vous ne souhaitez pas effectuer cette configuration manuellement ? Collez un lien vers cette page dans une session Devin et demandez-lui de tout configurer pour vous.</Tip>

  <Steps>
    <Step title="Enregistrez votre Devin API key dans GitHub">
      Le workflow appelle l'[API v3](/fr/api-reference/v3/overview) de Devin pour créer des sessions de manière programmatique. Créez un utilisateur de service et enregistrez son jeton comme secret GitHub Actions :

      1. Allez sur [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** et créez un utilisateur de service avec l'autorisation `ManageOrgSessions`
      2. Copiez le jeton d'API affiché après la création — il n'est affiché qu'une seule fois
      3. Dans votre dépôt GitHub, accédez à **Settings > Secrets and variables > Actions**
      4. Ajoutez deux secrets : `DEVIN_API_KEY` (le jeton) et `DEVIN_ORG_ID` (l'ID de votre organisation — obtenez-le en appelant `GET https://api.devin.ai/v3/enterprise/organizations` avec votre jeton)

      Assurez-vous que le dépôt est déjà [configuré dans Devin's Machine](/fr/onboard-devin/environment) afin que Devin puisse le cloner, le construire et y pousser des modifications.
    </Step>

    <Step title="Ajouter le fichier de workflow">
      Créez `.github/workflows/devin-ci-fix.yml`. Ce workflow se déclenche chaque fois que votre workflow CI existant se termine en échec, extrait les noms des jobs en échec et appelle la [Devin API](/fr/api-reference/v3/sessions/post-organizations-sessions) pour démarrer une session de correction :

      ```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.\"
                  }"
      ```

      Remplacez `"CI"` dans le tableau `workflows` par la valeur exacte de `name:` de votre fichier de workflow CI existant (par exemple, `"Tests"`, `"Build & Test"`).

      Utilisez le champ `tags` dans le corps de la requête (par exemple, `"tags": ["ci-fix", "pr-312"]`) pour suivre quels échecs CI ont déjà déclenché des sessions et éviter les doublons.
    </Step>

    <Step title="Que se passe-t-il en cas d'échec de l'intégration continue ?">
      Lorsqu'une exécution CI d'une PR échoue, l'Action extrait les détails de l'échec et les transmet à Devin comme invite de session. Voici un flux de correction automatique typique :

      1. **Lit les logs de la CI** — Devin ouvre l'URL de l'exécution et analyse la sortie d'erreur, les stack traces et les résultats de test des jobs en échec
      2. **Fait le lien entre l'erreur et le code** — Localise le fichier et la ligne concernés sur la branche de la PR (par exemple `UserList.tsx:34`) et lit le code environnant ainsi que le diff récent
      3. **Pousse un correctif** — Fait un commit ciblé directement sur la branche de la PR, ce qui relance automatiquement la CI
      4. **Ajoute un commentaire sur la PR** — Publie un récapitulatif expliquant la cause profonde et ce qui a été modifié

      Exemple de commentaire de PR de la part de 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 Faire le suivi d'un test instable theme={null}
        L'échec de la CI était en fait dû à un test instable — il passe lors de la réexécution. Analysez
        le test dans src/__tests__/UserList.test.tsx et corrigez son instabilité. Vérifiez
        s'il s'agit d'un problème de timing, d'une race condition ou d'un nettoyage manquant entre les exécutions.
        ```
      </PromptBlock>
    </Step>

    <Step title="Limitez-la aux erreurs pertinentes">
      Tous les échecs de CI ne se prêtent pas à une correction automatique : les timeouts d'infrastructure et les problèmes de build Docker ne seront pas résolus par une modification du code. Ajoutez une condition pour que seuls les échecs de jobs pertinents déclenchent 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" \
                ...
      ```

      ### Veiller à ce que les correctifs restent faciles à relire

      Devin pousse un commit de correction, mais la PR nécessite toujours une revue humaine avant la fusion. Considérez les corrections automatiques comme un point de départ pour le développeur, pas comme un remplacement de la revue de code. Si Devin ne parvient pas à résoudre le problème, il ajoute un commentaire sur la PR en expliquant ce qu'il a trouvé afin qu'un ingénieur puisse reprendre à partir de là.
    </Step>
  </Steps>
</div>
