contributor-check.yml
1 name: Contributor Attribution Check 2 3 on: 4 pull_request: 5 branches: [main] 6 paths: 7 # Only run when code files change (not docs-only PRs) 8 - '*.py' 9 - '**/*.py' 10 - '.github/workflows/contributor-check.yml' 11 12 permissions: 13 contents: read 14 15 jobs: 16 check-attribution: 17 runs-on: ubuntu-latest 18 steps: 19 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 20 with: 21 fetch-depth: 0 # Full history needed for git log 22 23 - name: Check for unmapped contributor emails 24 run: | 25 # Get the merge base between this PR and main 26 MERGE_BASE=$(git merge-base origin/main HEAD) 27 28 # Find any new author emails in this PR's commits 29 NEW_EMAILS=$(git log ${MERGE_BASE}..HEAD --format='%ae' --no-merges | sort -u) 30 31 if [ -z "$NEW_EMAILS" ]; then 32 echo "No new commits to check." 33 exit 0 34 fi 35 36 # Check each email against AUTHOR_MAP in release.py 37 MISSING="" 38 while IFS= read -r email; do 39 # Skip teknium and bot emails 40 case "$email" in 41 *teknium*|*noreply@github.com*|*dependabot*|*github-actions*|*anthropic.com*|*cursor.com*) 42 continue ;; 43 esac 44 45 # Check if email is in AUTHOR_MAP (either as a key or matches noreply pattern) 46 if echo "$email" | grep -qP '\+.*@users\.noreply\.github\.com'; then 47 continue # GitHub noreply emails auto-resolve 48 fi 49 50 if ! grep -qF "\"${email}\"" scripts/release.py 2>/dev/null; then 51 AUTHOR=$(git log --author="$email" --format='%an' -1) 52 MISSING="${MISSING}\n ${email} (${AUTHOR})" 53 fi 54 done <<< "$NEW_EMAILS" 55 56 if [ -n "$MISSING" ]; then 57 echo "" 58 echo "⚠️ New contributor email(s) not in AUTHOR_MAP:" 59 echo -e "$MISSING" 60 echo "" 61 echo "Please add mappings to scripts/release.py AUTHOR_MAP:" 62 echo -e "$MISSING" | while read -r line; do 63 email=$(echo "$line" | sed 's/^ *//' | cut -d' ' -f1) 64 [ -z "$email" ] && continue 65 echo " \"${email}\": \"<github-username>\"," 66 done 67 echo "" 68 echo "To find the GitHub username for an email:" 69 echo " gh api 'search/users?q=EMAIL+in:email' --jq '.items[0].login'" 70 exit 1 71 else 72 echo "✅ All contributor emails are mapped in AUTHOR_MAP." 73 fi