apoorvrajdev commited on
Commit
8e0a706
·
1 Parent(s): a0f0210

ci: add workflow blocking AI attribution in commit messages

Browse files
.github/workflows/no-ai-attribution.yml ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: no-ai-attribution
2
+
3
+ on:
4
+ push:
5
+ branches: ["**"]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ scan-commits:
13
+ name: Scan commit messages for AI attribution
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0
20
+
21
+ - name: Determine commit range
22
+ id: range
23
+ run: |
24
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
25
+ base="${{ github.event.pull_request.base.sha }}"
26
+ head="${{ github.event.pull_request.head.sha }}"
27
+ echo "range=${base}..${head}" >>"$GITHUB_OUTPUT"
28
+ elif [ -n "${{ github.event.before }}" ] && [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then
29
+ echo "range=${{ github.event.before }}..${{ github.sha }}" >>"$GITHUB_OUTPUT"
30
+ else
31
+ echo "range=${{ github.sha }}~1..${{ github.sha }}" >>"$GITHUB_OUTPUT"
32
+ fi
33
+
34
+ - name: Scan commit messages
35
+ env:
36
+ RANGE: ${{ steps.range.outputs.range }}
37
+ run: |
38
+ set -eu
39
+
40
+ # Patterns indicating AI co-authorship / Anthropic-tooling metadata.
41
+ # Bare "Claude" / "Anthropic" are intentionally NOT blocked so that
42
+ # legitimate product/roadmap references (e.g. "Anthropic Claude
43
+ # vision API integration") remain commitable.
44
+ patterns='
45
+ co-authored-by:
46
+ noreply@anthropic\.com
47
+ @anthropic\.com
48
+ generated[[:space:]]+with[[:space:]]+\[?claude
49
+ claude[[:space:]]+code
50
+ \[claude[[:space:]]+code\]
51
+ 🤖[[:space:]]*generated
52
+ 🤖.*claude
53
+ '
54
+
55
+ echo "Scanning range: ${RANGE}"
56
+ commits=$(git log --pretty=format:%H "${RANGE}" || true)
57
+ if [ -z "${commits}" ]; then
58
+ echo "No new commits in range — nothing to scan."
59
+ exit 0
60
+ fi
61
+
62
+ fail=0
63
+ for sha in ${commits}; do
64
+ msg=$(git log -1 --pretty=%B "${sha}")
65
+ for pat in ${patterns}; do
66
+ if printf '%s' "${msg}" | grep -qiE "${pat}"; then
67
+ echo "::error::Commit ${sha} matches forbidden pattern: ${pat}"
68
+ echo "----- offending commit message -----"
69
+ printf '%s\n' "${msg}"
70
+ echo "------------------------------------"
71
+ fail=1
72
+ break
73
+ fi
74
+ done
75
+ done
76
+
77
+ if [ "${fail}" -ne 0 ]; then
78
+ echo
79
+ echo "AI attribution detected in one or more commit messages."
80
+ echo "This repository is intentionally solo-authored."
81
+ exit 1
82
+ fi
83
+ echo "✓ No AI attribution detected."
84
+
85
+ - name: Scan author/committer identity
86
+ env:
87
+ RANGE: ${{ steps.range.outputs.range }}
88
+ run: |
89
+ set -eu
90
+ # Reject any commit authored or committed by an *@anthropic.com
91
+ # identity. Plain author-name matching ("Claude") is too broad —
92
+ # email is the reliable signal.
93
+ bad=$(git log --pretty=format:'%H %ae %ce' "${RANGE}" \
94
+ | grep -iE '@anthropic\.com' || true)
95
+ if [ -n "${bad}" ]; then
96
+ echo "::error::Commits with Anthropic-tooling identity detected:"
97
+ printf '%s\n' "${bad}"
98
+ exit 1
99
+ fi
100
+ echo "✓ No Anthropic-domain author/committer identities found."