From 59931734d058e1c3a71fefe6f13db6ce2945d0e2 Mon Sep 17 00:00:00 2001 From: Kaushik Lingarkar Date: Wed, 29 Oct 2025 09:54:12 -0700 Subject: [PATCH 1/2] Rename '--json' option to '--commit-json' This change updates the email checker to use '--commit-json' instead of '--json' when passing commit metadata. The rename improves clarity and avoids ambiguity as new options like '--properties-json' will be introduced in future updates. Key updates: - Modified 'check_email_pr.sh' to call 'check_email.sh' with '--commit-json'. - Updated 'check_email.sh' to replace all references to 'JSON' with 'COMMIT_JSON'. - Adjusted usage instructions and helper functions to reflect the new option name. This refactor prepares the codebase for upcoming enhancements that will read custom repository properties and pass them along to the email checker. Signed-off-by: Kaushik Lingarkar --- check_email_pr.sh | 3 ++- src/check_email.sh | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/check_email_pr.sh b/check_email_pr.sh index 67c9c57..64b62ea 100755 --- a/check_email_pr.sh +++ b/check_email_pr.sh @@ -58,7 +58,8 @@ done RESULT=0 while read -r pr_commit ; do debug "Running check on: $pr_commit" - "$MYDIR"/src/check_email.sh --json "$pr_commit" "${TEST_MODE[@]}" || RESULT=1 + "$MYDIR"/src/check_email.sh \ + --commit-json "$pr_commit" "${TEST_MODE[@]}" || RESULT=1 done < <(get_pr_commits | split_commits_and_add_metadata) exit $RESULT diff --git a/src/check_email.sh b/src/check_email.sh index b08af40..7ccd03b 100755 --- a/src/check_email.sh +++ b/src/check_email.sh @@ -10,14 +10,14 @@ debug() { [ "$VERBOSE" = "true" ] && echo "::debug::$1" >&2 ; } # message error() { echo "::error::$1" >&2 ; HAS_ERRORS=1 ; } # message warning() { echo "::warning::$1" >&2 ; } # message -json_val_by_key() { # key > value - echo "$JSON" | jq -r "$1 // empty" +json_val_by_key() { # json key > value + echo "$1" | jq -r "$2 // empty" } has_email_characters() { echo "$1" | grep -q "[@<>]" ; } # name in_allowlist() { # email - echo "$JSON" | jq -e --arg email "$1" \ + echo "$COMMIT_JSON" | jq -e --arg email "$1" \ '.extra_allowed_emails? | contains([$email])' > /dev/null } @@ -33,7 +33,7 @@ is_current_or_past_qc_email() { # email_address } is_upstream_commit() { - local commit_msg=$(json_val_by_key ".commit.message") + local commit_msg=$(json_val_by_key "$COMMIT_JSON" ".commit.message") contains_upstream_commit_footers "$commit_msg" || \ contains_cherry_picked_from_text "$commit_msg" } @@ -144,9 +144,9 @@ usage() { # error_message [error_code] local prog=$(basename -- "$0") cat < [--verbose] + usage: $prog --commit-json [--verbose] - The input provided to --json should contain this structure (additional + The input provided to --commit-json should contain this structure (additional properties will be ignored): { "commit": { @@ -180,7 +180,7 @@ VERBOSE=false while [ $# -gt 0 ] ; do case "$1" in --test-function) shift ; "$@" ; exit ;; - --json) shift ; JSON=$1 ;; + --commit-json) shift ; COMMIT_JSON=$1 ;; --verbose) VERBOSE=true ;; *) usage ;; esac @@ -188,21 +188,21 @@ while [ $# -gt 0 ] ; do done # Proprietary or Open Source -if ! REPO_EMAIL_TYPE=$(json_val_by_key ".license_type") || \ +if ! REPO_EMAIL_TYPE=$(json_val_by_key "$COMMIT_JSON" ".license_type") || \ [ -z "$REPO_EMAIL_TYPE" ] ; then error "Cannot determine project license type. Must provide 'license_type' \ as either 'PROPRIETARY' or 'OPEN_SOURCE'." exit fi -COMMITTER_DATE=$(json_val_by_key ".commit.committer.date") -COMMITTER_EMAIL=$(json_val_by_key ".commit.committer.email") -COMMITTER_NAME=$(json_val_by_key ".commit.committer.name") +COMMITTER_DATE=$(json_val_by_key "$COMMIT_JSON" ".commit.committer.date") +COMMITTER_EMAIL=$(json_val_by_key "$COMMIT_JSON" ".commit.committer.email") +COMMITTER_NAME=$(json_val_by_key "$COMMIT_JSON" ".commit.committer.name") debug "Committer is: $COMMITTER_NAME <$COMMITTER_EMAIL> , date: $COMMITTER_DATE" -AUTHOR_DATE=$(json_val_by_key ".commit.author.date") -AUTHOR_EMAIL=$(json_val_by_key ".commit.author.email") -AUTHOR_NAME=$(json_val_by_key ".commit.author.name") +AUTHOR_DATE=$(json_val_by_key "$COMMIT_JSON" ".commit.author.date") +AUTHOR_EMAIL=$(json_val_by_key "$COMMIT_JSON" ".commit.author.email") +AUTHOR_NAME=$(json_val_by_key "$COMMIT_JSON" ".commit.author.name") debug "Author is: $AUTHOR_NAME <$AUTHOR_EMAIL> , date: $AUTHOR_DATE" # Check for malformed names From 4ffebe837387f0000ba6ff8c3d50cc90a0ed888b Mon Sep 17 00:00:00 2001 From: Kaushik Lingarkar Date: Wed, 29 Oct 2025 12:56:54 -0700 Subject: [PATCH 2/2] Gate quicinc emails via repo custom properties Allow '@quicinc.com' addresses based on repository custom properties so projects can explicitly opt in for specific roles (author or committer). Supported custom properties: - allow-quicinc-authors - allow-quicinc-committers Some repositories need to accept '@quicinc.com' emails, while others must continue blocking them. Using GitHub custom properties provides a repo-level toggle per role, eliminating hard-coded exceptions and making policy changes configurable. By default, '@quicinc.com' addresses are blocked unless the repository sets the appropriate property to 'true'. Signed-off-by: Kaushik Lingarkar --- README.md | 4 +++- check_email_pr.sh | 24 +++++++++++++++++++- src/check_email.sh | 45 ++++++++++++++++++++++++++++++++----- test/custom_properties.json | 6 +++++ 4 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 test/custom_properties.json diff --git a/README.md b/README.md index 2d1704a..1257808 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,9 @@ jobs: - Committer (in all cases) or Author (when commit is not an upstream cherry-pick) - Block `@.*qualcomm.com` except `@qti.qualcomm.com` and `@oss.qualcomm.com` - - Block `@quicinc.com` + - Block `@quicinc.com` unless the custom repository property + `allow-quicinc-authors` (for authors) or `allow-quicinc-committers` (for committers) + is set to true - Block `quic_@quicinc.com` (starting Jan 2026) - Block `@codeaurora.org` - Author (when commit is an [upstream cherry-pick](#upstream-cherry_pick)) diff --git a/check_email_pr.sh b/check_email_pr.sh index 64b62ea..684b63a 100755 --- a/check_email_pr.sh +++ b/check_email_pr.sh @@ -31,6 +31,25 @@ get_pr_commits() { "$endpoint" } +# https://docs.github.com/en/rest/repos/custom-properties?apiVersion=2022-11-28#get-all-custom-property-values-for-a-repository +get_custom_properties() { + if [ -n "$TEST_MODE" ] ; then + debug "Using custom_properties test data" + cat "$MYDIR"/test/custom_properties.json + return + fi + local endpoint="$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/properties/values" + debug "Getting custom properties from $endpoint" + local debug_opts=() + [ -n "$RUNNER_DEBUG" ] && debug_opts=("--verbose" "--progress-meter" "--show-error") + curl -L --no-progress-meter --fail-with-body \ + "${debug_opts[@]}" \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$endpoint" +} + split_commits_and_add_metadata() { jq -c '.[] |= . + {"extra_allowed_emails": [], "license_type": "OPEN_SOURCE"} | .[]' } @@ -56,10 +75,13 @@ while [ $# -gt 0 ] ; do done RESULT=0 +custom_properties=$(get_custom_properties) while read -r pr_commit ; do debug "Running check on: $pr_commit" "$MYDIR"/src/check_email.sh \ - --commit-json "$pr_commit" "${TEST_MODE[@]}" || RESULT=1 + --commit-json "$pr_commit" \ + --custom-properties-json "$custom_properties" \ + "${TEST_MODE[@]}" || RESULT=1 done < <(get_pr_commits | split_commits_and_add_metadata) exit $RESULT diff --git a/src/check_email.sh b/src/check_email.sh index 7ccd03b..3c725a7 100755 --- a/src/check_email.sh +++ b/src/check_email.sh @@ -57,6 +57,17 @@ is_committer_date_after() { # cutoff_date [ "$(convert_to_epoch_sec_if_needed "$COMMITTER_DATE")" -gt "$cutoff_date" ] } +is_quicinc_allowed() { # role + local property + case "$1" in + Committer) property="allow-quicinc-committers" ;; + Author) property="allow-quicinc-authors" ;; + *) return 2 ;; # Not a valid role, programming error + esac + echo "$CUSTOM_PROPERTIES_JSON" | jq -e --arg property "$property" \ + 'any(.[]; .property_name == $property and .value == "true")' > /dev/null +} + convert_to_epoch_sec_if_needed() { # date-string (possibly already epoch_seconds) local first_git_commit=1112911993 if [ "$1" -gt "$first_git_commit" ] 2> /dev/null ; then @@ -90,26 +101,28 @@ isOssValid() { # email_address role local addr=$1 role=$2 ; shift 2 case "$role" in Committer) - isOssValidCommitter "$addr" + isOssValidEmailAddr "$addr" "$role" return ;; Author) - isOssValidCommitter "$addr" || \ + isOssValidEmailAddr "$addr" "$role" || \ (is_upstream_commit "$COMMIT" && isValidUpstreamAuthor "$addr") return ;; *) return 2 ;; # Not a valid role, programming error esac } -isOssValidCommitter() { # email_address +isOssValidEmailAddr() { # email_address role local addr=$1 ; shift 1 + local role=$1 ; shift 1 # Block @.*qualcomm.com if is_any_qualcomm_com "$addr" ; then # except @qti.qualcomm.com and @oss.qualcomm.com is_qti "$addr" || is_oss "$addr" return fi - # Block @quicinc.com - if is_quicinc "$addr" && ! is_quic_username "$addr" ; then + # Block @quicinc.com unless the corresponding custom repo properties + # are set to true + if is_quicinc "$addr" && ! is_quic_username "$addr" && ! is_quicinc_allowed "$role" ; then return 1 fi # Block quic_@quicinc.com (starting Jan 1 2026) @@ -144,7 +157,8 @@ usage() { # error_message [error_code] local prog=$(basename -- "$0") cat < [--verbose] + usage: $prog --commit-json \ + [--custom-properties-json ] [--verbose] The input provided to --commit-json should contain this structure (additional properties will be ignored): @@ -168,6 +182,23 @@ usage() { # error_message [error_code] The "date" values should be either epoch seconds or a format like ISO 8061 parseable by the \`date\` command. + + The input provided to --custom-properties-json should contain this structure: +[ + { + "property_name": "Require-commit-email-check", + "value": "true" + }, + { + "property_name": "allow-quicinc-authors", + "value": "true" + }, + { + "property_name": "allow-quicinc-committers", + "value": "true" + } +] + EOF [ $# -gt 0 ] && error "$@" @@ -177,10 +208,12 @@ EOF HAS_ERRORS=0 VERBOSE=false +CUSTOM_PROPERTIES_JSON="[]" while [ $# -gt 0 ] ; do case "$1" in --test-function) shift ; "$@" ; exit ;; --commit-json) shift ; COMMIT_JSON=$1 ;; + --custom-properties-json) shift ; CUSTOM_PROPERTIES_JSON=$1 ;; --verbose) VERBOSE=true ;; *) usage ;; esac diff --git a/test/custom_properties.json b/test/custom_properties.json new file mode 100644 index 0000000..0ed88d1 --- /dev/null +++ b/test/custom_properties.json @@ -0,0 +1,6 @@ +[ + { + "property_name": "Require-commit-email-check", + "value": "true" + } +] \ No newline at end of file