| name: Contributor Attribution Check |
|
|
| on: |
| pull_request: |
| branches: [main] |
| paths: |
| |
| - '*.py' |
| - '**/*.py' |
| - '.github/workflows/contributor-check.yml' |
|
|
| permissions: |
| contents: read |
|
|
| jobs: |
| check-attribution: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 |
| with: |
| fetch-depth: 0 |
|
|
| - name: Check for unmapped contributor emails |
| run: | |
| # Get the merge base between this PR and main |
| MERGE_BASE=$(git merge-base origin/main HEAD) |
| |
| |
| NEW_EMAILS=$(git log ${MERGE_BASE}..HEAD --format='%ae' --no-merges | sort -u) |
|
|
| if [ -z "$NEW_EMAILS" ]; then |
| echo "No new commits to check." |
| exit 0 |
| fi |
|
|
| |
| MISSING="" |
| while IFS= read -r email; do |
| |
| case "$email" in |
| *teknium*|*noreply@github.com*|*dependabot*|*github-actions*|*anthropic.com*|*cursor.com*) |
| continue ;; |
| esac |
|
|
| |
| if echo "$email" | grep -qP '\+.*@users\.noreply\.github\.com'; then |
| continue |
| fi |
|
|
| if ! grep -qF "\"${email}\"" scripts/release.py 2>/dev/null; then |
| AUTHOR=$(git log --author="$email" --format='%an' -1) |
| MISSING="${MISSING}\n ${email} (${AUTHOR})" |
| fi |
| done <<< "$NEW_EMAILS" |
|
|
| if [ -n "$MISSING" ]; then |
| echo "" |
| echo "⚠️ New contributor email(s) not in AUTHOR_MAP:" |
| echo -e "$MISSING" |
| echo "" |
| echo "Please add mappings to scripts/release.py AUTHOR_MAP:" |
| echo -e "$MISSING" | while read -r line; do |
| email=$(echo "$line" | sed 's/^ *//' | cut -d' ' -f1) |
| [ -z "$email" ] && continue |
| echo " \"${email}\": \"<github-username>\"," |
| done |
| echo "" |
| echo "To find the GitHub username for an email:" |
| echo " gh api 'search/users?q=EMAIL+in:email' --jq '.items[0].login'" |
| exit 1 |
| else |
| echo "✅ All contributor emails are mapped in AUTHOR_MAP." |
| fi |
|
|