> ## 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.

# Corrección automática de compilaciones de CI fallidas

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="Corrección automática de ejecuciones de CI con errores" description="Agrega una GitHub Action que llame a Devin para corregir ejecuciones de CI que fallen en tus PR." prompt="Ayúdame a configurar una GitHub Action que active automáticamente a Devin para corregir ejecuciones de CI fallidas. Sigue la guía en https://docs.devin.ai/use-cases/gallery/api-github-actions-ci-fix y guíame paso a paso: almacenar la API key, agregar el archivo de workflow y configurarlo para que solo actúe sobre los fallos correctos." category="Automatizaciones" features="API" />

<div className="uc-detail-wrapper">
  <Tip>¿Prefieres no configurarlo manualmente? Pega un enlace a esta página en una sesión de Devin y pídele que lo configure todo por ti.</Tip>

  <Steps>
    <Step title="Guarda tu API key de Devin en GitHub">
      El flujo de trabajo llama a la [API v3](/es/api-reference/v3/overview) de Devin para crear sesiones de forma programática. Crea un usuario de servicio y almacena su token como un secreto de GitHub Actions:

      1. Ve a [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) > **Settings** > **Service Users** y crea un usuario de servicio con el permiso `ManageOrgSessions`
      2. Copia el token de la API que se muestra después de crearlo — solo se muestra una vez
      3. En tu repositorio de GitHub, ve a **Settings > Secrets and variables > Actions**
      4. Añade dos secretos: `DEVIN_API_KEY` (el token) y `DEVIN_ORG_ID` (el ID de tu organización — obténlo llamando a `GET https://api.devin.ai/v3/enterprise/organizations` con tu token)

      Asegúrate de que el repositorio ya esté [configurado en la máquina de Devin](/es/onboard-devin/environment) para que Devin pueda clonarlo, compilarlo y hacer push en él.
    </Step>

    <Step title="Añade el archivo de flujo de trabajo">
      Crea `.github/workflows/devin-ci-fix.yml`. Este flujo de trabajo se ejecuta cada vez que el flujo de trabajo de CI existente finaliza con un error, extrae los nombres de los jobs que fallaron y llama a la [Devin API](/es/api-reference/v3/sessions/post-organizations-sessions) para iniciar una sesión de corrección:

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

      Reemplaza `"CI"` en el array `workflows` por el valor exacto de `name:` de tu archivo de flujo de trabajo de CI existente (por ejemplo, `"Tests"`, `"Build & Test"`).

      Usa el campo `tags` en el cuerpo de la solicitud (por ejemplo, `"tags": ["ci-fix", "pr-312"]`) para llevar un registro de qué errores de CI ya han activado sesiones y evitar duplicados.
    </Step>

    <Step title="Qué ocurre cuando falla la CI">
      Cuando falla la ejecución de CI de un PR, la Action extrae los detalles del error y se los pasa a Devin como mensaje de sesión. Este es un flujo típico de corrección automática:

      1. **Lee los registros de CI** — Devin abre la URL de la ejecución y analiza la salida de errores, las trazas de pila y los resultados de pruebas de los jobs que fallaron
      2. **Rastrea el error hasta el código** — Localiza el archivo y la línea relevantes en la rama del PR (por ejemplo, `UserList.tsx:34`) y lee el código que lo rodea y el diff reciente
      3. **Publica una corrección** — Realiza un commit con un cambio específico directamente en la rama del PR, lo que vuelve a ejecutar la CI automáticamente
      4. **Comenta en el PR** — Publica un resumen que explica la causa raíz y qué se cambió

      Ejemplo de comentario de PR 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 Dar seguimiento a una prueba inestable theme={null}
        La falla de CI en realidad fue una prueba inestable: pasa al reintentarla. Investiga
        la prueba en src/__tests__/UserList.test.tsx y corrige la inestabilidad. Verifica
        si es un problema de temporización, una condición de carrera o una falta de limpieza entre ejecuciones.
        ```
      </PromptBlock>
    </Step>

    <Step title="Acotar a los fallos pertinentes">
      No todos los fallos de CI pueden solucionarse automáticamente: los timeouts en la infraestructura y los problemas de compilación de Docker no se resolverán con un cambio de código. Agrega una condición para que solo los fallos de trabajos relevantes activen a 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" \
                ...
      ```

      ### Mantén las correcciones fáciles de revisar

      Devin envía un commit de corrección, pero el PR aún requiere revisión humana antes de fusionarlo. Trata las correcciones automáticas como un punto de partida para el desarrollador, no como un reemplazo de la revisión de código. Si Devin no puede resolver el fallo, deja un comentario en el PR explicando lo que encontró para que un ingeniero pueda continuar a partir de ahí.
    </Step>
  </Steps>
</div>
