From c46b716754090d480377b076428818898f13f47b Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Thu, 22 Oct 2026 15:38:37 +0530 Subject: [PATCH] ci: require signed commits and reject AI co-authors 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). --- .github/workflows/ci.yml | 16 ++++++- scripts/check-commit-policy.sh | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 scripts/check-commit-policy.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8779e581..1cc80bdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ concurrency: cancel-in-progress: true env: - GO_VERSION: "1.27.2" + GO_VERSION: "1.27.3" GOPRIVATE: "github.com/GrayCodeAI/*" GONOSUMDB: "github.com/GrayCodeAI/*" GONOSUMCHECK: "1" @@ -32,6 +32,20 @@ env: GOWORK: "off" jobs: + commit-policy: + name: commit policy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Enforce signed commits and no AI co-authors + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PUSH_BEFORE: ${{ github.event.before }} + PUSH_AFTER: ${{ github.event.after }} + run: bash scripts/check-commit-policy.sh + version: name: Canonical version metadata runs-on: ubuntu-latest diff --git a/scripts/check-commit-policy.sh b/scripts/check-commit-policy.sh new file mode 100644 index 00000000..04b66167 --- /dev/null +++ b/scripts/check-commit-policy.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Enforce the repository commit policy: +# 1. Every commit in the change set has a verified signature. +# 2. No commit credits an AI assistant as a co-author or generator. +# +# Works for pull_request and push events. Requires GH_TOKEN (the workflow's +# GITHUB_TOKEN is enough) and GITHUB_REPOSITORY. +set -euo pipefail + +repo="${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required}" +event="${GITHUB_EVENT_NAME:?GITHUB_EVENT_NAME is required}" + +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)' +ai_generated_re='generated (with|by).*(claude|anthropic|openai|chatgpt|gpt|copilot|cursor|gemini|codex|aider|devin|windsurf|tabnine|cody|replit|amazon[ -]?q)' + +commit_shas() { + case "$event" in + pull_request | pull_request_target) + gh api --paginate "repos/$repo/pulls/${PR_NUMBER:?PR_NUMBER is required}/commits" --jq '.[].sha' + ;; + push) + local before="${PUSH_BEFORE:-}" after="${PUSH_AFTER:?PUSH_AFTER is required}" + if [[ -z "$before" || "$before" =~ ^0+$ ]]; then + # New branch: check the pushed head only; its history predates + # this policy. + printf '%s\n' "$after" + else + gh api "repos/$repo/compare/${before}...${after}" --jq '.commits[].sha' + fi + ;; + *) + echo "commit policy: unsupported event '$event'" >&2 + exit 2 + ;; + esac +} + +failed=0 +checked=0 + +while IFS= read -r sha; do + [[ -z "$sha" ]] && continue + checked=$((checked + 1)) + + commit_json=$(gh api "repos/$repo/commits/$sha") + verified=$(jq -r '.commit.verification.verified' <<<"$commit_json") + message=$(jq -r '.commit.message' <<<"$commit_json") + + if [[ "$verified" != "true" ]]; then + echo "::error::Commit ${sha:0:12} is not signed with a verified key." + failed=1 + fi + + if grep -Eiq "$ai_author_re" <<<"$message"; then + echo "::error::Commit ${sha:0:12} credits an AI assistant as co-author." + grep -Ein "$ai_author_re" <<<"$message" | sed 's/^/ /' + failed=1 + fi + + if grep -Eiq "$ai_generated_re" <<<"$message"; then + echo "::error::Commit ${sha:0:12} contains an AI generation attribution." + grep -Ein "$ai_generated_re" <<<"$message" | sed 's/^/ /' + failed=1 + fi +done < <(commit_shas) + +if [[ "$checked" -eq 0 ]]; then + echo "commit policy: no commits to check" + exit 0 +fi + +if [[ "$failed" -ne 0 ]]; then + echo + echo "Commit policy failed." + echo " - Sign commits with a key registered on GitHub (git commit -S)." + echo " - Remove AI co-author / generation trailers from the message." + exit 1 +fi + +echo "commit policy: $checked commit(s) verified, no AI co-author trailers"