feat(codebuild): harden build execution with retries and source/CA integrity #451
Workflow file for this run
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: AI Attribution | |
| on: | |
| pull_request: | |
| types: [opened, edited, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint-trailers: | |
| name: Commits omit AI attribution trailers | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check commit trailers | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # CONTRIBUTING.md and AGENTS.md both state: | |
| # | |
| # "Do not include Co-Authored-By trailers for AI tools in commit | |
| # messages. Attribution should be limited to human contributors." | |
| # | |
| # This job enforces that. It does NOT try to recognise an AI by its | |
| # name. Names are not a usable signal in either direction: Claude and | |
| # Devin are ordinary human given names, so matching on them rejects | |
| # real contributors, while any list of product names is stale the | |
| # moment a new agent ships. | |
| # | |
| # Instead a co-author is rejected only on evidence that the identity | |
| # is not a person: | |
| # | |
| # 1. Its GitHub privacy address resolves to an account of type Bot. | |
| # GitHub is the authority here, and agents commit through GitHub | |
| # Apps, so this keeps working for tools that do not exist yet. | |
| # 2. Its address is a noreply@ mailbox on some other domain - a | |
| # fabricated, uncontactable address. No person's git identity is | |
| # noreply@. | |
| # | |
| # A false positive costs far more than a false negative here: a | |
| # missed trailer is untidy attribution, but a blocked contributor is | |
| # a person turned away by a linter. So anything this cannot resolve | |
| # is allowed through, and a GitHub API failure never fails the build. | |
| # | |
| # Merge commits are skipped via --no-merges, matching the | |
| # Conventional Commits job. | |
| # Bot accounts that may legitimately co-author. Keep this short. | |
| ALLOWED_BOTS='dependabot[bot]' | |
| # Trailer keys and generator markers that are AI-only by construction. | |
| # These are literal strings no person writes, not identity matching. | |
| AI_ONLY_TRAILER='^(claude-session|codex-session|chatgpt-session):' | |
| AI_MARKER='(Generated with \[Claude Code\]|🤖 Generated with)' | |
| CACHE=$(mktemp) | |
| FAILED=0 | |
| # Prints "bot <login>" if the address belongs to a bot account, | |
| # "noreply" for a fabricated noreply mailbox, nothing otherwise. | |
| classify() { | |
| local email="$1" local_part login id cached type | |
| local_part=${email%@*} | |
| case "$email" in | |
| *@users.noreply.github.com) | |
| case "$local_part" in | |
| *+*) id=${local_part%%+*}; login=${local_part#*+} ;; | |
| *) id=""; login=$local_part ;; | |
| esac | |
| # A [bot] suffix is GitHub's own convention; no lookup needed. | |
| case "$login" in | |
| *'[bot]'*) printf 'bot %s' "$login"; return ;; | |
| esac | |
| cached=$(grep -m1 "^${id}|${login} " "$CACHE" 2>/dev/null || true) | |
| if [ -n "$cached" ]; then | |
| type=${cached##* } | |
| else | |
| if [ -n "$id" ]; then | |
| type=$(gh api "user/$id" --jq .type 2>/dev/null || echo "") | |
| else | |
| type=$(gh api "users/$login" --jq .type 2>/dev/null || echo "") | |
| fi | |
| # Unresolvable (deleted account, API trouble) is not evidence. | |
| [ -z "$type" ] && type="Unknown" | |
| printf '%s|%s %s\n' "$id" "$login" "$type" >> "$CACHE" | |
| fi | |
| if [ "$type" = "Bot" ]; then | |
| printf 'bot %s' "$login" | |
| fi | |
| ;; | |
| *) | |
| # noreply@example.com, but not GitHub's own privacy domain. | |
| case "$local_part" in | |
| noreply|no-reply) printf 'noreply' ;; | |
| esac | |
| ;; | |
| esac | |
| # Never let a "this is a person" verdict look like a failure: | |
| # the job runs under set -e and this is called in a $( ). | |
| return 0 | |
| } | |
| for sha in $(git log --no-merges --format=%H "$BASE_SHA".."$HEAD_SHA"); do | |
| subject=$(git show -s --format=%s "$sha") | |
| offending="" | |
| while IFS= read -r line; do | |
| lower=$(printf '%s' "$line" | tr '[:upper:]' '[:lower:]') | |
| case "$lower" in | |
| co-authored-by:*) | |
| email=$(printf '%s' "$lower" | sed -n 's/.*<\(.*\)>.*/\1/p') | |
| [ -z "$email" ] && continue | |
| verdict=$(classify "$email") | |
| case "$verdict" in | |
| bot\ *) | |
| login=${verdict#bot } | |
| # -F because a login like dependabot[bot] is not a pattern. | |
| if ! printf '%s\n' "$ALLOWED_BOTS" | grep -Fxq "$login"; then | |
| offending="${offending}${line} <- ${login} is a bot account"$'\n' | |
| fi | |
| ;; | |
| noreply) | |
| offending="${offending}${line} <- noreply address, not a contactable person"$'\n' | |
| ;; | |
| esac | |
| ;; | |
| *) | |
| offending="${offending}${line}"$'\n' | |
| ;; | |
| esac | |
| done < <(git show -s --format=%B "$sha" | grep -iE "^co-authored-by:|$AI_ONLY_TRAILER|$AI_MARKER" || true) | |
| if [ -n "$offending" ]; then | |
| echo "::error::Commit carries AI attribution: $sha $subject" | |
| echo "" | |
| echo " Commit: $sha" | |
| echo " $subject" | |
| echo "" | |
| echo " Offending line(s):" | |
| printf '%s' "$offending" | sed 's/^/ /' | |
| echo "" | |
| FAILED=1 | |
| else | |
| echo "ok: $sha $subject" | |
| fi | |
| done | |
| if [ "$FAILED" -ne 0 ]; then | |
| echo "" | |
| echo " CONTRIBUTING.md: \"Do not include Co-Authored-By trailers for AI tools in" | |
| echo " commit messages. Attribution should be limited to human contributors.\"" | |
| echo "" | |
| echo " Co-authoring a person is fine and is never rejected — this only fires when" | |
| echo " the address belongs to a bot account or is a noreply mailbox." | |
| echo "" | |
| echo " To fix a single commit:" | |
| echo " git commit --amend # delete the trailer lines, save" | |
| echo " git push --force-with-lease" | |
| echo "" | |
| echo " To fix several:" | |
| echo " git rebase --root -x 'git commit --amend --no-edit'" | |
| echo "" | |
| echo " Configure your agent not to add them in the first place — for Claude Code," | |
| echo " set includeCoAuthoredBy: false in .claude/settings.json." | |
| fi | |
| exit $FAILED |