fix(MOC-59): antigravity 传输指纹层对齐官方客户端(抓包实证) (#310) #421
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: no-ai-coauthor | |
| # 阻塞含 AI Co-Authored-By trailer 或 AI author email 的 commit 进入 main。 | |
| # 配合 branch protection 把本 workflow 加进 required status checks 后, | |
| # 任何含 AI 署名的 PR 都无法 squash merge。 | |
| on: | |
| pull_request: | |
| # 不限制 base 分支(跟 ci.yml 一致):stacked PR(base=feature 分支)在底 PR 合并后 | |
| # 自动 retarget 到 main 时,若加 `branches:[main]` 过滤会漏跑 —— retarget 不是触发 | |
| # 事件类型,且 retarget 瞬间 base 未稳定到 main 会被过滤掉,导致该 required check 缺失 | |
| # → PR BLOCKED,只能手动 close+reopen 补跑(MOC-64)。job 内按 PR_BASE_SHA..PR_HEAD_SHA | |
| # 扫 commit,对任意 base 都正确,去掉 base 过滤无副作用。 | |
| # `ready_for_review` 让 draft → ready 触发;`synchronize` 在 draft 仍 fire, | |
| # 下面 job-level `if` 把 draft job skip(skip = pass,不卡 required check)。 | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| no-ai-coauthor: | |
| # draft PR 期间 skip;push/dispatch/non-draft PR 正常跑。 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.draft == false | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine commit range | |
| id: range | |
| env: | |
| PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PUSH_BEFORE: ${{ github.event.before }} | |
| PUSH_AFTER: ${{ github.sha }} | |
| run: | | |
| set -eu | |
| if [ -n "${PR_HEAD_SHA:-}" ]; then | |
| BASE="$PR_BASE_SHA" | |
| HEAD="$PR_HEAD_SHA" | |
| else | |
| BASE="$PUSH_BEFORE" | |
| HEAD="$PUSH_AFTER" | |
| fi | |
| if [ -z "$BASE" ] || [ "$BASE" = "0000000000000000000000000000000000000000" ]; then | |
| echo "range=$HEAD~1..$HEAD" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "range=$BASE..$HEAD" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Scan commits for AI co-author / email | |
| env: | |
| RANGE: ${{ steps.range.outputs.range }} | |
| run: | | |
| set -eu | |
| echo "Scanning commits in range: $RANGE" | |
| COMMITS=$(git log --format='%H' "$RANGE") | |
| if [ -z "$COMMITS" ]; then | |
| echo "No commits to scan." | |
| exit 0 | |
| fi | |
| COUNT=$(echo "$COMMITS" | wc -l | tr -d ' ') | |
| echo "Commit count: $COUNT" | |
| # AI co-author trailer pattern(全大小写;覆盖 anthropic / claude / cursor / | |
| # copilot 子串) | |
| TRAILER_RE='Co-[Aa]uthored-[Bb]y:.*<[^>]*(@anthropic\.com|cursor|[Cc]opilot|cursoragent|claude)' | |
| # AI author email pattern | |
| EMAIL_RE='@anthropic\.com|cursoragent@cursor|copilot-swe-agent|[Cc]ursor@users\.noreply|[Cc]opilot@users\.noreply' | |
| FAILED=0 | |
| for sha in $COMMITS; do | |
| short=$(git log -1 --format='%h' "$sha") | |
| msg=$(git log -1 --format='%B' "$sha") | |
| ae=$(git log -1 --format='%ae' "$sha") | |
| ce=$(git log -1 --format='%ce' "$sha") | |
| if echo "$msg" | grep -iE "$TRAILER_RE" > /dev/null; then | |
| echo "::error::commit $short: AI Co-Authored-By trailer detected" | |
| echo "$msg" | grep -iE "$TRAILER_RE" || true | |
| FAILED=1 | |
| fi | |
| if echo "$ae" | grep -iE "$EMAIL_RE" > /dev/null; then | |
| echo "::error::commit $short: AI author email — $ae" | |
| FAILED=1 | |
| fi | |
| if echo "$ce" | grep -iE "$EMAIL_RE" > /dev/null; then | |
| echo "::error::commit $short: AI committer email — $ce" | |
| FAILED=1 | |
| fi | |
| done | |
| if [ "$FAILED" -ne 0 ]; then | |
| echo "::error::Found AI co-author trailer or AI email in $RANGE." | |
| echo "::error::Rewrite commit message (git commit --amend / rebase -i) to remove," | |
| echo "::error::or force-push with corrected history." | |
| exit 1 | |
| fi | |
| echo "✅ No AI co-author trailers or emails in $COUNT commits." |