Skip to main content
Devin 的 API 是一款功能强大的工具,旨在自动解决由 SonarQube 等代码扫描工具检测到的代码问题。尽管本文档聚焦于 SonarQube,但其底层策略同样适用于其他代码扫描工具,包括 Veracode、Orca 等。 如果你希望了解这一流程的实际运行方式,可以查看我们的示例仓库,并在 Cognition 的博客文章中阅读详细说明。 在生产环境中,流程大致如下所示:

使用 Devin API 的自动化问题解决

在生产环境中,使用 Devin API 自动解决代码问题的流程简洁高效。下面是该流程所涉及主要步骤的高层概览:

1. 流程概览

  1. 创建 Pull Request:向代码仓库提交一个包含更改的 Pull Request(PR),这些更改中可能包含由代码扫描工具检测出的问题。
  2. 触发 GitHub Action:PR 创建后会自动触发一个 GitHub Action 工作流。
  3. GitHub Action 调用 Devin API:GitHub Action 向 Devin API 发送请求,将检测出的问题传递给 Devin 以进行自动修复。
  4. 初始化 Devin 会话:Devin 会话被启动,接收问题的上下文,并基于提供的数据尝试解决该问题。
  5. Devin 提交用于人工审核的 PR:问题解决后,Devin 生成一个包含建议修改的 PR,并将其提交以供人工审核。

2. 完成此操作的步骤

要将 Devin 的 API 集成到你的 CI/CD 流水线中,你需要完成以下配置:
  1. 为 CI 和 API 支持配置 SonarQube
    • 确保 SonarQube 已配置为支持持续集成(CI)和 API 集成。如果你不希望专门为 API 访问配置 SonarQube,可以通过 cookie 进行身份验证。在此了解有关该设置的更多信息
  2. 配置 GitHub 环境以保存所需的机密信息
    • 设置 GitHub 环境,以安全存储与 Devin 的 API 和其他集成工具交互所需的机密信息,例如身份验证令牌和配置密钥。
完成这些步骤后,你的流水线将准备好使用 Devin 的 API 自动解决问题,加快处理速度并减少人工干预。
  1. 测试集成
完成设置后,你可以通过手动触发 GitHub Action 来测试集成。这将允许你验证该 Action 是否能正确调用 Devin API 并解决已识别的问题。
  1. 查看 Devin Sessions 页面
在 GitHub Action 被触发且 Devin 处理完问题后,你可以在 Devin Sessions 页面查看状态和结果。此页面提供已解决问题和建议更改的详细信息。 深入指南 如果你的 SonarQube 项目已经正确配置,请直接跳过以下内容。否则,下面的说明将讲解如何确保 GitHub 可以访问 SonarQube 的 API。 从 SonarQube 获取的必要值 要配置集成,你需要从你的 SonarQube 实例中获取以下三个值: 你将需要来自 SonarQube 的三个值:

1. 创建 SONAR_TOKEN

  1. 点击 SonarQube 右上角的账户图标。
  2. 在下拉菜单中选择 Security
  3. Tokens 部分中,点击 Generate Tokens
  4. 为令牌命名并点击 Generate
  • 复制生成的令牌,以便在 GitHub Actions 中使用。
SonarQube

2. 创建 SONAR_PROJECT

  1. 在 SonarQube 中选择项目。
  2. 点击左下角的 Information
  3. 向下滚动,找到 project key(项目键)。
SonarQube

3. 创建 SONAR_ORG

参考上面的步骤,在 SonarQube 中找到你的组织详情。 获取所有所需的值后,你就可以开始配置 GitHub Action 了。
这里假设你有一个本地的 SonarCloud 属性文件 sonar-project.properties,其中指定:
sonar.projectKey={PROJECT_KEY}
sonar.sources=FILE_PATH(通常为 ".")
该 GitHub Action 的源代码如下
name: SonarCloud 扫描与 Devin 问题修复
on:
  workflow_dispatch:
  push:
    branches:
      - '**'
  pull_request:
    branches:
      - '**'

jobs:
  analyze:
    name: 分析与修复
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: SonarCloud 扫描
      uses: SonarSource/sonarqube-scan-action@v4
      env:
        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
        SONAR_ORG: ${{ secrets.SONAR_ORG }}
      with:
        args: >
          -Dsonar.organization=${{ env.SONAR_ORG }}
          -Dsonar.sources=.
    - name: 设置 Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.x'

    - name: 安装依赖项
      run: pip install aiohttp

    - name: 配置 Git
      run: |
        git config --global user.name "GitHub Action"
        git config --global user.email "[email protected]"
    - name: 运行 Devin 问题修复
      env:
        DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        SONAR_ORG: ${{ secrets.SONAR_ORG }}
        SONAR_PROJECT_KEY: {SONAR_PROJECT_KEY}
      run: python .github/scripts/devin_remediation.py
提醒一下:devin_remediation.py
import asyncio
import aiohttp
import os
from datetime import datetime

# 环境变量
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
SONAR_TOKEN = os.getenv("SONAR_TOKEN")
DEVIN_API_KEY = os.getenv("DEVIN_API_KEY")
SONAR_ORG = os.getenv("SONAR_ORG")
SONAR_PROJECT_KEY = os.getenv("SONAR_PROJECT_KEY")
DEVIN_API_BASE = "https://api.devin.ai/v1"

async def get_sonarcloud_issues():
    """从 SonarCloud 获取未解决的漏洞。"""
    url = "https://sonarcloud.io/api/issues/search"
    headers = {"Authorization": f"Bearer {SONAR_TOKEN}"}
    params = {
        "organization": SONAR_ORG,
        "projectKeys": SONAR_PROJECT_KEY,
        "types": "VULNERABILITY",
        "statuses": "OPEN"
    }

    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers=headers, params=params) as response:
            if response.status != 200:
                print(f"获取 SonarCloud 问题时出错:{await response.text()}")
                return []
            result = await response.json()
            print(f"发现 {len(result.get('issues', []))} 个问题")
            return result.get('issues', [])

async def delegate_task_to_devin(issue):
    """将修复、提交和推送的完整任务委托给 Devin AI。"""
    async with aiohttp.ClientSession() as session:
        headers = {"Authorization": f"Bearer {DEVIN_API_KEY}"}
        prompt = f"""
        修复 {GITHUB_REPOSITORY} 中的以下漏洞:{issue['message']},位于文件 {issue['component']}。
        1. 创建名为 'devin/{issue['key']}-fix-vulnerability' 的新分支。
        2. 实施修复。
        3. 编写详细的提交消息说明更改内容:
            - 问题键:{issue['key']}
            - 组件:{issue['component']}
            - 由 Devin AI 于 {datetime.now().isoformat()} 修复
            - 包含 'Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>'。
        4. 将分支推送到远程仓库。
        5. 创建包含修复说明的拉取请求。
        """

        data = {"prompt": prompt, "idempotent": True}

        async with session.post(f"{DEVIN_API_BASE}/sessions", json=data, headers=headers) as response:
            if response.status != 200:
                print(f"委托任务给 Devin 时出错:{await response.text()}")
                return None
            result = await response.json()
            print(f"已创建 Devin 会话:{result}")
            return result

async def monitor_devin_session(session_id):
    """监控 Devin 的进度直至任务完成。"""
    async with aiohttp.ClientSession() as session:
        headers = {"Authorization": f"Bearer {DEVIN_API_KEY}"}

        while True:
            async with session.get(f"{DEVIN_API_BASE}/sessions/{session_id}", headers=headers) as response:
                if response.status != 200:
                    print(f"监控 Devin 会话时出错:{await response.text()}")
                    return None

                result = await response.json()
                status = result.get("status_enum")

                if status in ["completed", "stopped"]:
                    print(f"Devin 已完成任务:{result}")
                    return result
                elif status == "blocked":
                    print("Devin 遇到问题,请手动检查。")
                    return None

                await asyncio.sleep(5)

async def main():
    try:
        issues = await get_sonarcloud_issues()

        for issue in issues:
            print(f"正在处理问题:{issue['key']}")

            # 将任务委托给 Devin AI
            session_data = await delegate_task_to_devin(issue)

            if session_data:
                session_id = session_data["session_id"]

                # 监控 Devin 的进度
                await monitor_devin_session(session_id)

    except Exception as e:
        print(f"发生错误:{str(e)}")
        raise

if __name__ == "__main__":
    asyncio.run(main())
为确保 GitHub Action 正确设置环境变量,请将这些变量添加到 GitHub Repository Secrets 中。 前往正确的设置页面可能有些麻烦。依次进入 Security,然后编辑 Secrets。在 Repository Secrets 下添加 SONAR_TOKENDEVINS_API
SonarQube
配置完成后,可以监控正在执行的 GitHub Action。如果运行成功,将显示如下:
SonarQube
你可以在 Session Manager 中查看 Devin 会话。
SonarQube
完成后,Devin 会自动创建 pull request。对于 GitLab 用户,请参考相关指南