Skip to content

Commit c4fd82b

Browse files
committed
ci: require signed commits and reject AI co-authors (#130)
Add a commit-policy job that verifies every commit in a PR or push range carries a verified signature and rejects AI co-author or generation trailers. Bump CI Go to 1.27.3 to clear GO-2026-6443 (crypto/x509).
1 parent bf69672 commit c4fd82b

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

‎.github/workflows/ci.yml‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
env:
22-
GO_VERSION: "1.27.2"
22+
GO_VERSION: "1.27.3"
2323
GOPRIVATE: "github.com/GrayCodeAI/*"
2424
GONOSUMDB: "github.com/GrayCodeAI/*"
2525
GONOSUMCHECK: "1"
@@ -32,6 +32,20 @@ env:
3232
GOWORK: "off"
3333

3434
jobs:
35+
commit-policy:
36+
name: commit policy
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
40+
- name: Enforce signed commits and no AI co-authors
41+
env:
42+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43+
GITHUB_EVENT_NAME: ${{ github.event_name }}
44+
PR_NUMBER: ${{ github.event.pull_request.number }}
45+
PUSH_BEFORE: ${{ github.event.before }}
46+
PUSH_AFTER: ${{ github.event.after }}
47+
run: bash scripts/check-commit-policy.sh
48+
3549
version:
3650
name: Canonical version metadata
3751
runs-on: ubuntu-latest

‎scripts/check-commit-policy.sh‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env bash
2+
# Enforce the repository commit policy:
3+
# 1. Every commit in the change set has a verified signature.
4+
# 2. No commit credits an AI assistant as a co-author or generator.
5+
#
6+
# Works for pull_request and push events. Requires GH_TOKEN (the workflow's
7+
# GITHUB_TOKEN is enough) and GITHUB_REPOSITORY.
8+
set -euo pipefail
9+
10+
repo="${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required}"
11+
event="${GITHUB_EVENT_NAME:?GITHUB_EVENT_NAME is required}"
12+
13+
ai_author_re='^[[:space:]]*co-authored-by:.*(claude|anthropic|openai|chatgpt|gpt|copilot|cursor|gemini|codex|aider|devin|windsurf|tabnine|cody|replit|amazon[ -]?q|jetbrains[ -]?ai|sourcegraph)'
14+
ai_generated_re='generated (with|by).*(claude|anthropic|openai|chatgpt|gpt|copilot|cursor|gemini|codex|aider|devin|windsurf|tabnine|cody|replit|amazon[ -]?q)'
15+
16+
commit_shas() {
17+
case "$event" in
18+
pull_request | pull_request_target)
19+
gh api --paginate "repos/$repo/pulls/${PR_NUMBER:?PR_NUMBER is required}/commits" --jq '.[].sha'
20+
;;
21+
push)
22+
local before="${PUSH_BEFORE:-}" after="${PUSH_AFTER:?PUSH_AFTER is required}"
23+
if [[ -z "$before" || "$before" =~ ^0+$ ]]; then
24+
# New branch: check the pushed head only; its history predates
25+
# this policy.
26+
printf '%s\n' "$after"
27+
else
28+
gh api "repos/$repo/compare/${before}...${after}" --jq '.commits[].sha'
29+
fi
30+
;;
31+
*)
32+
echo "commit policy: unsupported event '$event'" >&2
33+
exit 2
34+
;;
35+
esac
36+
}
37+
38+
failed=0
39+
checked=0
40+
41+
while IFS= read -r sha; do
42+
[[ -z "$sha" ]] && continue
43+
checked=$((checked + 1))
44+
45+
commit_json=$(gh api "repos/$repo/commits/$sha")
46+
verified=$(jq -r '.commit.verification.verified' <<<"$commit_json")
47+
message=$(jq -r '.commit.message' <<<"$commit_json")
48+
49+
if [[ "$verified" != "true" ]]; then
50+
echo "::error::Commit ${sha:0:12} is not signed with a verified key."
51+
failed=1
52+
fi
53+
54+
if grep -Eiq "$ai_author_re" <<<"$message"; then
55+
echo "::error::Commit ${sha:0:12} credits an AI assistant as co-author."
56+
grep -Ein "$ai_author_re" <<<"$message" | sed 's/^/ /'
57+
failed=1
58+
fi
59+
60+
if grep -Eiq "$ai_generated_re" <<<"$message"; then
61+
echo "::error::Commit ${sha:0:12} contains an AI generation attribution."
62+
grep -Ein "$ai_generated_re" <<<"$message" | sed 's/^/ /'
63+
failed=1
64+
fi
65+
done < <(commit_shas)
66+
67+
if [[ "$checked" -eq 0 ]]; then
68+
echo "commit policy: no commits to check"
69+
exit 0
70+
fi
71+
72+
if [[ "$failed" -ne 0 ]]; then
73+
echo
74+
echo "Commit policy failed."
75+
echo " - Sign commits with a key registered on GitHub (git commit -S)."
76+
echo " - Remove AI co-author / generation trailers from the message."
77+
exit 1
78+
fi
79+
80+
echo "commit policy: $checked commit(s) verified, no AI co-author trailers"

0 commit comments

Comments
 (0)