Skip to content
Merged
Show file tree
Hide file tree
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
36 changes: 36 additions & 0 deletions .github/external-contributors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2026 NVIDIA Corporation. All rights reserved.
#
# Reviewed external contributors.
#
# The verify-authors check requires an @nvidia.com or github-noreply
# email on every commit. External (non-NVIDIA) contributions are
# accepted only after a maintainer-run IP review of the contribution.
# Once a contribution passes review, a maintainer records the
# contributor here, and the authors check accepts their email for the
# listed pull requests only.
#
# This file is always read from the tip of the target (base) branch by
# CI, so a pull request cannot allowlist itself. After merging a new
# entry, re-run the authors check on the contributor's PR to pick it up.
#
# This per-entry flow is a deliberate v1 while external contributions
# are rare. If volume grows, revisit with a lower-toil mechanism (e.g.,
# a maintainer-applied label) without weakening the review requirement.
#
# Entry fields:
# email commit author/committer email to accept
# github contributor's GitHub login
# prs pull request numbers this entry applies to (required —
# entries are scoped per contribution, never blanket)
# reviewed_by maintainer who ran the contribution review
# review_date date the review was completed (YYYY-MM-DD)
# notes one-line description of the contribution

external_contributors:
- email: wenyuchiou12@gmail.com
github: WenyuChiou
prs: [76]
reviewed_by: mosheabr
review_date: "2026-07-13"
notes: One-line CONTRIBUTING.md anchor fix (dead README link). Review passed on all criteria.
57 changes: 55 additions & 2 deletions .github/workflows/verify-authors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
#
# The automated/sync-skills branch is exempt — same reason as DCO:
# it's the bot mirror, not a contributor.
#
# Reviewed external contributions are accepted via
# .github/external-contributors.yml: a maintainer runs the contribution
# review, records the contributor's email scoped to specific PR
# numbers, and this check then accepts that email for those PRs only.
# The allowlist is read from the tip of the BASE branch, never the PR
# head, so a pull request cannot allowlist itself — and a re-run picks
# up entries merged after the PR was opened.

name: Verify Authors

Expand All @@ -36,8 +44,10 @@ jobs:
- name: Verify all commit author emails are NVIDIA-affiliated
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail

Expand All @@ -54,12 +64,53 @@ jobs:
# NVIDIA-org GitHub user)
allowed='@(nvidia\.com|users\.noreply\.github\.com)$'

# The allowlist logic depends on the YAML parser. Fail loudly
# if it is unavailable — otherwise reviewed externals would be
# silently rejected with no clue why.
python3 -c 'import yaml'

# Reviewed-external allowlist, read from the TIP of the base
# branch so a PR cannot allowlist itself, and so a re-run
# picks up entries merged after the PR was opened. Produces
# "email" lines for entries whose prs list contains this PR's
# number. An unparsable allowlist fails the job loudly.
allowlist_ref="origin/$BASE_REF"
if git cat-file -e "$allowlist_ref:.github/external-contributors.yml" 2>/dev/null; then
reviewed_externals=$(git show "$allowlist_ref:.github/external-contributors.yml" \
| python3 -c '
import os, sys, yaml
try:
doc = yaml.safe_load(sys.stdin) or {}
except yaml.YAMLError as exc:
print(f"::error::.github/external-contributors.yml on the base branch is unparsable: {exc}", file=sys.stderr)
sys.exit(1)
pr = int(os.environ["PR_NUMBER"])
for entry in doc.get("external_contributors") or []:
email = str(entry.get("email", "")).strip().lower()
prs = entry.get("prs") or []
if email and isinstance(prs, list) and pr in prs:
print(email)
')
else
reviewed_externals=""
fi

is_reviewed_external() {
local email_lc
email_lc=$(echo "$1" | tr '[:upper:]' '[:lower:]')
[ -n "$reviewed_externals" ] && echo "$reviewed_externals" | grep -qxF "$email_lc"
}

violations=()
while read -r sha; do
author_email=$(git show --format='%ae' -s "$sha")
committer_email=$(git show --format='%ce' -s "$sha")
for email in "$author_email" "$committer_email"; do
if ! echo "$email" | grep -qE "$allowed"; then
if is_reviewed_external "$email"; then
echo "Accepting reviewed external contributor email $email for PR #$PR_NUMBER (see .github/external-contributors.yml)."
continue
fi
subject=$(git show --format='%s' -s "$sha")
violations+=("${sha:0:7} $email $subject")
fi
Expand All @@ -86,8 +137,10 @@ jobs:
echo " origin/main && git push --force-with-lease"
echo ""
echo "If you are not an NVIDIA employee, please contact a CODEOWNER."
echo "External contributions to catalog content require explicit OSRB"
echo "review before merge and cannot be self-served."
echo "External contributions are accepted after a maintainer-run"
echo "review; once cleared, a maintainer records your email in"
echo ".github/external-contributors.yml scoped to your PR and this"
echo "check will accept it. This cannot be self-served."
exit 1
fi

Expand Down
Loading