Skip to content

feat(codebuild): harden build execution with retries and source/CA integrity #451

feat(codebuild): harden build execution with retries and source/CA integrity

feat(codebuild): harden build execution with retries and source/CA integrity #451

Workflow file for this run

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