Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/author-identity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Author Identity Check

on:
pull_request:
branches: [main, master]

jobs:
author-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Verify commit authors use noreply email
run: |
set -eu
base="${{ github.event.pull_request.base.sha }}"
head="${{ github.event.pull_request.head.sha }}"
bad=$(git log --pretty='%h %ae' "${base}..${head}" \
| grep -v 'users\.noreply\.github\.com$' || true)
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex users\.noreply\.github\.com$ matches any domain that merely ends with that suffix (e.g., someone@badusers.noreply.github.com). To avoid false passes, anchor it to the domain boundary, e.g. require @users.noreply.github.com at the end (and optionally do a case-insensitive match).

Suggested change
| grep -v 'users\.noreply\.github\.com$' || true)
| grep -Eiv '@users\.noreply\.github\.com$' || true)

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +21
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bad=$(git log ... | grep ... || true) pipeline can silently succeed even if git log fails (e.g., invalid/missing base/head SHAs), because the pipeline status comes from grep and || true masks non-zero exits. This could let PRs with non-noreply emails pass without being checked. Split the commands so git log errors fail the step (or enable pipefail and only suppress grep's exit code when it’s the expected “no matches”).

Suggested change
bad=$(git log --pretty='%h %ae' "${base}..${head}" \
| grep -v 'users\.noreply\.github\.com$' || true)
authors=$(git log --pretty='%h %ae' "${base}..${head}")
bad=$(printf '%s\n' "$authors" | grep -v 'users\.noreply\.github\.com$' || true)

Copilot uses AI. Check for mistakes.
if [ -n "$bad" ]; then
echo "::error::PR contains commits with non-noreply author email:"
echo "$bad"
echo
echo "Fix locally:"
echo " git config user.email USER@users.noreply.github.com"
echo " git rebase -i \$base # squash/edit to apply new identity"
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remediation hint prints git rebase -i $base, but $base is not defined in a developer’s local shell (it’s only a variable inside this CI step). Consider printing the actual base SHA (expand ${base}) or suggesting a more actionable target like origin/main so the instructions are directly usable.

Suggested change
echo " git rebase -i \$base # squash/edit to apply new identity"
echo " git rebase -i ${base} # squash/edit to apply new identity"

Copilot uses AI. Check for mistakes.
exit 1
fi
echo "All commit author emails OK"
Comment on lines +20 to +31
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only checks the commit author email (%ae). If the goal is preventing email PII in git metadata, consider also checking the committer email (%ce) since it can differ (e.g., amended/cherry-picked commits) and could still leak a non-noreply address.

Suggested change
bad=$(git log --pretty='%h %ae' "${base}..${head}" \
| grep -v 'users\.noreply\.github\.com$' || true)
if [ -n "$bad" ]; then
echo "::error::PR contains commits with non-noreply author email:"
echo "$bad"
echo
echo "Fix locally:"
echo " git config user.email USER@users.noreply.github.com"
echo " git rebase -i \$base # squash/edit to apply new identity"
exit 1
fi
echo "All commit author emails OK"
bad=""
while read -r hash author_email committer_email; do
case "$author_email" in
*users.noreply.github.com) author_ok=1 ;;
*) author_ok=0 ;;
esac
case "$committer_email" in
*users.noreply.github.com) committer_ok=1 ;;
*) committer_ok=0 ;;
esac
if [ "$author_ok" -eq 0 ] || [ "$committer_ok" -eq 0 ]; then
bad="${bad}${hash} author=${author_email} committer=${committer_email}"$'\n'
fi
done <<EOF
$(git log --pretty='%h %ae %ce' "${base}..${head}")
EOF
if [ -n "$bad" ]; then
echo "::error::PR contains commits with non-noreply author or committer email:"
printf '%s' "$bad"
echo
echo "Fix locally:"
echo " git config user.email USER@users.noreply.github.com"
echo " git rebase -i \$base # squash/edit to apply new identity"
exit 1
fi
echo "All commit author and committer emails OK"

Copilot uses AI. Check for mistakes.
Loading