Skip to content

Auto Copilot Autofix (High & Medium Only) #10

Auto Copilot Autofix (High & Medium Only)

Auto Copilot Autofix (High & Medium Only) #10

name: Auto Copilot Autofix (High & Medium Only)
on:
workflow_dispatch:
workflow_run:
workflows: ["CodeQL Advanced"]
types: [completed]
jobs:
auto-fix:
runs-on: ubuntu-latest
permissions:
security-events: read
contents: write
pull-requests: write
steps:
- name: Trigger Autofix for High & Medium alerts
env:
GH_TOKEN: ${{ secrets.AUTOFIX_TOKEN }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
run: |
DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch')
echo "Default branch: $DEFAULT_BRANCH"
# 获取所有 open alert,用 jq 过滤 security_severity_level 为 high 或 medium 的
ALERTS=$(gh api \
"/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \
--jq '[.[] | select(.rule.security_severity_level == "high" or .rule.security_severity_level == "medium") | {number: .number, level: .rule.security_severity_level}]')
COUNT=$(echo $ALERTS | jq 'length')
echo "Found $COUNT alerts with security_severity_level high or medium"
echo "$ALERTS" | jq -r '.[] | " Alert #\(.number) [\(.level)]"'
if [ "$COUNT" -eq 0 ]; then
echo "No alerts to process, exiting."
exit 0
fi
for ROW in $(echo $ALERTS | jq -r '.[] | @base64'); do
_jq() { echo "$ROW" | base64 -d | jq -r "$1"; }
NUMBER=$(_jq '.number')
SEC_LEVEL=$(_jq '.level')
echo "--- Alert #$NUMBER [$SEC_LEVEL] ---"
EXISTING=$(gh api \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \
--jq '.status' 2>/dev/null || echo "none")
if [ "$EXISTING" = "success" ]; then
echo "✅ Fix already exists, committing directly..."
else
echo "⏳ Generating fix..."
gh api -X POST \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix || {
echo "⚠️ Failed to trigger autofix for #$NUMBER, skipping"
continue
}
for i in 1 2 3; do
sleep 30
EXISTING=$(gh api \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \
--jq '.status' 2>/dev/null || echo "none")
echo " Attempt $i: status = $EXISTING"
[ "$EXISTING" = "success" ] && break
done
fi
if [ "$EXISTING" = "success" ]; then
BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}"
SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \
--jq '.object.sha')
# 创建分支
gh api -X POST /repos/$OWNER/$REPO/git/refs \
-f ref="refs/heads/$BRANCH" \
-f sha="$SHA" 2>/dev/null && \
echo "🌿 Created branch: $BRANCH" || \
echo "🌿 Branch already exists: $BRANCH"
# 提交 fix
gh api -X POST \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \
-f target_ref="$BRANCH" || {
echo "❌ Failed to commit fix for alert #$NUMBER"
continue
}
echo "✅ Committed fix to branch: $BRANCH"
# 获取 alert 详情
ALERT_INFO=$(gh api \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER)
ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description')
ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800)
ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")')
ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"')
ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"')
ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url')
CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")')
# 获取 Autofix AI 修复说明
AUTOFIX_DESC=$(gh api \
/repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \
--jq '.description // "暂无 AI 修复说明"')
# 创建 Draft PR
gh pr create \
--repo "$OWNER/$REPO" \
--base "$DEFAULT_BRANCH" \
--head "$BRANCH" \
--draft \
--title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \
--body "## 🤖 Copilot Autofix 自动修复报告
---
### 📋 基本信息
| 字段 | 内容 |
|------|------|
| **Alert ID** | [#$NUMBER]($ALERT_URL) |
| **安全级别** | $SEC_LEVEL |
| **规则名称** | $ALERT_TITLE |
| **问题文件** | \`$ALERT_FILE\` 第 $ALERT_LINE 行 |
| **CWE 分类** | $CWE_TAGS |
| **规则标签** | $ALERT_TAGS |
---
### 🔍 问题说明
$ALERT_HELP
---
### 🤖 AI 修复思路
$AUTOFIX_DESC
---
### ✅ Review 检查清单
- [ ] 理解了漏洞的成因和影响范围
- [ ] 确认 AI 修复逻辑正确,没有遗漏边界情况
- [ ] 确认修复没有改变原有业务逻辑
- [ ] 确认没有引入新的安全问题
- [ ] CI / 单元测试全部通过
- [ ] 如有必要,已补充对应的测试用例
---
> 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \
echo "🎉 PR created for alert #$NUMBER" || \
echo "⚠️ PR already exists for alert #$NUMBER"
else
echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping"
fi
done