Skip to main content

自动修复失败的 CI 构建

添加一个调用 Devin 的 GitHub Action,用于修复你 PR 中失败的 CI。
AuthorCognition
Category自动化
FeaturesAPI
1

将 Devin API key 存储到 GitHub 中

该工作流会调用 Devin 的 v3 API,以编程方式创建会话。先创建一个服务用户,并将其 token 存储为 GitHub Actions 机密:
  1. 前往 app.devin.ai > Settings > Service Users,创建一个具有 ManageOrgSessions 权限的服务用户
  2. 复制创建后显示的 API token —— 它只会显示一次
  3. 在你的 GitHub 仓库中,导航到 Settings > Secrets and variables > Actions
  4. 新增两个机密:DEVIN_API_KEY(该 token)和 DEVIN_ORG_ID(你的组织 ID —— 通过使用该 token 调用 GET https://api.devin.ai/v3/enterprise/organizations 获取)
请确保该代码仓库已在 Devin 的 Machine 上完成配置,以便 Devin 可以克隆、构建并向其推送代码。
2

添加工作流程文件

创建 .github/workflows/devin-ci-fix.yml。该工作流会在你现有的 CI 工作流执行失败时触发,提取失败的作业名称,并调用 Devin API 来启动一次修复会话:
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.\"
            }"
workflows 数组中的 "CI" 替换为你现有 CI 工作流文件中的精确 name: 值(例如 "Tests""Build & Test")。在请求体中使用 tags 字段(例如 "tags": ["ci-fix", "pr-312"])来跟踪哪些 CI 失败已经触发过会话,以避免重复触发。
3

当 CI 失败时会发生什么

当某个 PR 的 CI 运行失败时,Action 会提取失败详情,并将其作为会话提示传递给 Devin。下面是一个典型的自动修复流程:
  1. 读取 CI 日志 —— Devin 打开本次运行的 URL,并从失败的作业中解析错误输出、堆栈跟踪和测试结果
  2. 将错误追溯到代码 —— 在 PR 分支上定位相关文件与行号(例如:UserList.tsx:34),并阅读其周围代码和最近的 diff
  3. 推送修复 —— 直接向 PR 分支提交有针对性的变更,从而自动重新触发 CI
  4. 在 PR 上评论 —— 发布一条评论,总结根本原因以及修改内容
以下是 Devin 在 PR 上的一条示例评论:
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.
4

将范围限定到正确的故障上

并非所有 CI 失败都适合自动修复——基础设施超时和 Docker 构建问题并不能单纯通过修改代码解决。添加一个条件,使只有相关的作业失败才会触发 Devin:
      - 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" \
          ...

保持修复内容易于审查

Devin 会推送一个修复提交,但在合并之前,这个 PR 仍然需要人工审查。将自动修复视为开发者的起点,而不是代码审查的替代。如果 Devin 无法解决该失败,它会在 PR 上发表评论,说明它发现了什么,方便工程师在此基础上接手处理。