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

# 自动解决 SonarQube 问题

> 通过 GitHub Actions 让 Devin 自动解决 SonarQube 问题

Devin 的 API 是一款功能强大的工具，旨在自动解决由 SonarQube 等代码扫描工具检测到的代码问题。尽管本文档聚焦于 SonarQube，但其底层策略同样适用于其他代码扫描工具，包括 Veracode、Orca 等。

如果你希望了解这一流程的实际运行方式，可以查看我们的示例仓库，并在 Cognition 的博客文章中阅读详细说明。

在生产环境中，流程大致如下所示：

<div id="automated-issue-resolution-with-devins-api">
  # 使用 Devin API 的自动化问题解决
</div>

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

<div id="1-process-overview">
  ### 1. 流程概览
</div>

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，并将其提交以供人工审核。

<div id="2-steps-to-accomplish-this">
  ### 2. 完成此操作的步骤
</div>

要将 Devin 的 API 集成到你的 CI/CD 流水线中，你需要完成以下配置：

1. **为 CI 和 API 支持配置 SonarQube**：
   * 确保 SonarQube 已配置为支持持续集成 (CI) 和 API 集成。如果你不希望专门为 API 访问配置 SonarQube，可以通过 cookie 进行身份验证。[在此了解有关该设置的更多信息](#)。

2. **配置 GitHub 环境以保存所需的机密信息**：
   * 设置 GitHub 环境，以安全存储与 Devin 的 API 和其他集成工具交互所需的机密信息，例如身份验证令牌和配置密钥。

完成这些步骤后，你的流水线将准备好使用 Devin 的 API 自动解决问题，加快处理速度并减少人工干预。

3. **测试集成**

完成设置后，你可以通过手动触发 GitHub Action 来测试集成。这将允许你验证该 Action 是否能正确调用 Devin API 并解决已识别的问题。

4. **查看 Devin Sessions 页面**

在 GitHub Action 被触发且 Devin 处理完问题后，你可以在 Devin Sessions 页面查看状态和结果。此页面提供已解决问题和建议更改的详细信息。

深入指南

如果你的 SonarQube 项目已经正确配置，请直接跳过以下内容。否则，下面的说明将讲解如何确保 GitHub 可以访问 SonarQube 的 API。

从 SonarQube 获取的必要值
要配置集成，你需要从你的

SonarQube 实例中获取以下三个值：
你将需要来自 SonarQube 的三个值：

<div id="1-create-sonar_token">
  ### 1. 创建 **SONAR\_TOKEN**：
</div>

1. 点击 SonarQube 右上角的账户图标。
2. 在下拉菜单中选择 **Security**。
3. 在 **Tokens** 部分中，点击 **Generate Tokens**。
4. 为令牌命名并点击 **Generate**。

* 复制生成的令牌，以便在 GitHub Actions 中使用。

<Frame>
  <img src="https://mintcdn.com/cognitionai/a0js040y87FuBerW/images/SonarQubeImages/Onboarding-Token-SonarQube.png?fit=max&auto=format&n=a0js040y87FuBerW&q=85&s=a97d5bbc59358891fbf70d57216db756" alt="SonarQube" width="2988" height="1610" data-path="images/SonarQubeImages/Onboarding-Token-SonarQube.png" />
</Frame>

<div id="2-create-sonar_project">
  ### 2. 创建 **SONAR\_PROJECT**
</div>

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

<Frame>
  <img src="https://mintcdn.com/cognitionai/a0js040y87FuBerW/images/SonarQubeImages/Onboarding-Project-SonarQube.png?fit=max&auto=format&n=a0js040y87FuBerW&q=85&s=bfab801236d9e500ca7adbd643106aeb" alt="SonarQube" width="2990" height="1702" data-path="images/SonarQubeImages/Onboarding-Project-SonarQube.png" />
</Frame>

<div id="3-create-sonar_org">
  ### 3. 创建 **SONAR\_ORG**
</div>

参考上面的步骤，在 SonarQube 中找到你的组织详情。

获取所有所需的值后，你就可以开始配置 GitHub Action 了。

<Note>
  这里假设你有一个本地的 SonarCloud 属性文件 `sonar-project.properties`，其中指定：

  ```
  sonar.projectKey={PROJECT_KEY}
  sonar.sources=FILE_PATH（通常为 "."）
  ```
</Note>

该 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 "action@github.com"
    - 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\_TOKEN** 和 **DEVINS\_API**。

<Frame>
  <img src="https://mintcdn.com/cognitionai/a0js040y87FuBerW/images/SonarQubeImages/Onboarding-Repository-Secret.png?fit=max&auto=format&n=a0js040y87FuBerW&q=85&s=9d26c6c07f8cd38a9a6aba45149e171a" alt="SonarQube" width="1562" height="664" data-path="images/SonarQubeImages/Onboarding-Repository-Secret.png" />
</Frame>

配置完成后，可以监控正在执行的 GitHub Action。如果运行成功，将显示如下：

<Frame>
  <img src="https://mintcdn.com/cognitionai/a0js040y87FuBerW/images/SonarQubeImages/Sonarqube-Github-Action.png?fit=max&auto=format&n=a0js040y87FuBerW&q=85&s=3a0afdc9c816af42e25c6083e3f1d6a5" alt="SonarQube" width="3412" height="1468" data-path="images/SonarQubeImages/Sonarqube-Github-Action.png" />
</Frame>

你可以在 **Session Manager** 中查看 Devin 会话。

<Frame>
  <img src="https://mintcdn.com/cognitionai/a0js040y87FuBerW/images/SonarQubeImages/Devin-API-SonarQube.png?fit=max&auto=format&n=a0js040y87FuBerW&q=85&s=c7c9eedf1ba0e78d0ce5000b4eecb2e6" alt="SonarQube" width="1648" height="1688" data-path="images/SonarQubeImages/Devin-API-SonarQube.png" />
</Frame>

完成后，Devin 会自动创建拉取请求 (PR) 。对于 GitLab 用户，请参阅链接的[指南](/zh/enterprise/use-cases/sonarqube/gitlab)。
