Skip to content

Commit d6e73cb

Browse files
Add CI check to detect terms in PR content (#134)
* Add CI check to detect banned terms in PR content (#133) Big Brother is watching your pull requests. This adds a CI workflow that scans PR content for forbidden terminology, because thoughtcrime in commit messages shall not go unpunished. Checks branch names, titles, descriptions, commit messages, comments, review comments, labels, changed file paths, and diff content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Rename CI job from 'Check for banned terms' to 'Check for terms' Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fail CI check when PR diff cannot be fetched Previously `|| true` suppressed gh pr diff failures, causing the diff check to silently pass on large PRs. Now a diff fetch failure is treated as a violation so banned terms cannot slip through unchecked. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix diff check grep using wrong regex mode The `grep -v '^\+\+\+'` used BRE mode where `\+` is a quantifier, not a literal plus. This caused it to filter out ALL added lines instead of just `+++` diff headers, making the diff content check silently pass every time. Switch to `-Ev` for consistent ERE mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fddae60 commit d6e73cb

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: PR Content Check
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, edited, labeled]
6+
issue_comment:
7+
types: [created, edited]
8+
pull_request_review_comment:
9+
types: [created, edited]
10+
pull_request_review:
11+
types: [submitted, edited]
12+
13+
permissions:
14+
contents: read
15+
pull-requests: read
16+
17+
jobs:
18+
check-banned-terms:
19+
name: Check for terms
20+
# issue_comment fires for both issues and PRs; only run for PRs
21+
if: github.event_name != 'issue_comment' || github.event.issue.pull_request
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Get PR number
25+
id: pr
26+
run: |
27+
if [ "${{ github.event_name }}" = "issue_comment" ]; then
28+
echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
29+
else
30+
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
31+
fi
32+
33+
- name: Check for banned terms
34+
env:
35+
GH_TOKEN: ${{ github.token }}
36+
PR_NUMBER: ${{ steps.pr.outputs.number }}
37+
REPO: ${{ github.repository }}
38+
run: |
39+
set -euo pipefail
40+
41+
VIOLATIONS=""
42+
43+
add_violation() {
44+
VIOLATIONS="${VIOLATIONS}- ${1}\n"
45+
}
46+
47+
# 1. Branch name
48+
echo "::group::Checking branch name"
49+
BRANCH=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json headRefName -q '.headRefName')
50+
if echo "$BRANCH" | grep -qi 'seo'; then
51+
add_violation "Branch name contains 'SEO': \`$BRANCH\`"
52+
echo "::error::Branch name '$BRANCH' contains banned term"
53+
else
54+
echo "OK"
55+
fi
56+
echo "::endgroup::"
57+
58+
# 2. PR title
59+
echo "::group::Checking PR title"
60+
TITLE=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json title -q '.title')
61+
if echo "$TITLE" | grep -qi 'seo'; then
62+
add_violation "PR title contains 'SEO': \`$TITLE\`"
63+
echo "::error::PR title contains banned term"
64+
else
65+
echo "OK"
66+
fi
67+
echo "::endgroup::"
68+
69+
# 3. PR description
70+
echo "::group::Checking PR description"
71+
gh pr view "$PR_NUMBER" --repo "$REPO" --json body -q '.body // ""' > /tmp/pr_body.txt
72+
if grep -qi 'seo' /tmp/pr_body.txt; then
73+
add_violation "PR description contains 'SEO'"
74+
echo "::error::PR description contains banned term"
75+
else
76+
echo "OK"
77+
fi
78+
echo "::endgroup::"
79+
80+
# 4. Commit messages
81+
echo "::group::Checking commit messages"
82+
gh api "repos/${REPO}/pulls/${PR_NUMBER}/commits" --paginate \
83+
-q '.[].commit.message' > /tmp/commits.txt
84+
if grep -qi 'seo' /tmp/commits.txt; then
85+
MATCH=$(grep -i 'seo' /tmp/commits.txt | head -1)
86+
add_violation "Commit message contains 'SEO': \`$MATCH\`"
87+
echo "::error::Commit message contains banned term"
88+
else
89+
echo "OK"
90+
fi
91+
echo "::endgroup::"
92+
93+
# 5. PR comments
94+
echo "::group::Checking PR comments"
95+
gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" --paginate \
96+
-q '.[].body // ""' > /tmp/comments.txt
97+
if grep -qi 'seo' /tmp/comments.txt; then
98+
add_violation "PR comment contains 'SEO'"
99+
echo "::error::PR comment contains banned term"
100+
else
101+
echo "OK"
102+
fi
103+
echo "::endgroup::"
104+
105+
# 6. Review comments (inline code review)
106+
echo "::group::Checking review comments"
107+
gh api "repos/${REPO}/pulls/${PR_NUMBER}/comments" --paginate \
108+
-q '.[].body // ""' > /tmp/review_comments.txt
109+
if grep -qi 'seo' /tmp/review_comments.txt; then
110+
add_violation "Inline review comment contains 'SEO'"
111+
echo "::error::Inline review comment contains banned term"
112+
else
113+
echo "OK"
114+
fi
115+
echo "::endgroup::"
116+
117+
# 7. Review bodies
118+
echo "::group::Checking review bodies"
119+
gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" --paginate \
120+
-q '.[].body // ""' > /tmp/reviews.txt
121+
if grep -qi 'seo' /tmp/reviews.txt; then
122+
add_violation "PR review body contains 'SEO'"
123+
echo "::error::PR review body contains banned term"
124+
else
125+
echo "OK"
126+
fi
127+
echo "::endgroup::"
128+
129+
# 8. PR labels
130+
echo "::group::Checking PR labels"
131+
LABELS=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json labels -q '.labels[].name' | tr '\n' ', ')
132+
if echo "$LABELS" | grep -qi 'seo'; then
133+
add_violation "PR label contains 'SEO': \`$LABELS\`"
134+
echo "::error::PR label contains banned term"
135+
else
136+
echo "OK"
137+
fi
138+
echo "::endgroup::"
139+
140+
# 9. Changed file paths
141+
echo "::group::Checking changed file paths"
142+
gh pr view "$PR_NUMBER" --repo "$REPO" --json files -q '.files[].path' > /tmp/changed_files.txt
143+
if grep -qi 'seo' /tmp/changed_files.txt; then
144+
MATCH=$(grep -i 'seo' /tmp/changed_files.txt | head -3 | tr '\n' ', ')
145+
add_violation "Changed file path contains 'SEO': \`$MATCH\`"
146+
echo "::error::Changed file path contains banned term"
147+
else
148+
echo "OK"
149+
fi
150+
echo "::endgroup::"
151+
152+
# 10. Diff content (added lines only)
153+
echo "::group::Checking diff content (added lines)"
154+
if ! gh pr diff "$PR_NUMBER" --repo "$REPO" > /tmp/pr_diff.txt; then
155+
add_violation "Failed to fetch PR diff (may be too large to check)"
156+
echo "::error::Failed to fetch PR diff"
157+
elif grep -E '^\+' /tmp/pr_diff.txt | grep -Ev '^\+\+\+' | grep -qi 'seo'; then
158+
add_violation "Added lines in diff contain 'SEO'"
159+
echo "::error::Added code contains banned term"
160+
else
161+
echo "OK"
162+
fi
163+
echo "::endgroup::"
164+
165+
# Final verdict
166+
if [ -n "$VIOLATIONS" ]; then
167+
echo ""
168+
echo "::error::Banned term 'SEO' found in PR content"
169+
echo ""
170+
echo "========================================="
171+
echo "FAILED: Banned term 'SEO' detected"
172+
echo "========================================="
173+
echo -e "$VIOLATIONS"
174+
exit 1
175+
fi
176+
177+
echo ""
178+
echo "All checks passed - no banned terms found."

0 commit comments

Comments
 (0)