diff --git a/.github/workflows/contributor-guidance.yml b/.github/workflows/contributor-guidance.yml index e9a99bcb6277..4035ea932077 100644 --- a/.github/workflows/contributor-guidance.yml +++ b/.github/workflows/contributor-guidance.yml @@ -1,3 +1,8 @@ +# This action requires the following secrets to be set on the repository: +# GH_USER_TOKEN: GitHub user token, used because FIRST_TIMER and +# FIRST_TIME_CONTRIBUTOR associations are only returned for +# privileged API calls + name: Contributor guidance on: @@ -9,8 +14,7 @@ permissions: {} jobs: contributor: name: Resolve contributor status - # Use the event only to exclude trusted associations, mannequins, and bots. - # Resolve every potentially external contributor with a privileged API request. + # Avoid allocating a runner unless a welcome or scan is a plausible outcome. if: >- github.run_attempt == 1 && github.repository == 'nodejs/node' && @@ -22,52 +26,40 @@ jobs: runs-on: ubuntu-slim outputs: is_first_time: ${{ steps.resolve.outputs.is_first_time }} + # The event association may not expose private organization membership, + # so gate the guidance job on the privileged API result. should_scan: ${{ steps.resolve.outputs.should_scan }} steps: - name: Check author association id: resolve env: + EVENT_ASSOCIATION: ${{ github.event.pull_request.author_association }} GH_TOKEN: ${{ secrets.GH_USER_TOKEN }} NUMBER: ${{ github.event.pull_request.number }} run: | - started_at=$SECONDS - # TODO: Remove the retries once privileged API requests are confirmed - # to return the association immediately. - for delay in 0 15 30 60; do - sleep "$delay" - association=$(gh api "/repos/$GITHUB_REPOSITORY/pulls/$NUMBER" \ - --jq '.author_association') - elapsed=$((SECONDS - started_at)) - echo "Author association after ${elapsed}s: $association" - - case "$association" in - FIRST_TIMER|FIRST_TIME_CONTRIBUTOR) - echo 'is_first_time=true' >> "$GITHUB_OUTPUT" - echo 'should_scan=true' >> "$GITHUB_OUTPUT" - exit 0 - ;; - CONTRIBUTOR) - echo 'is_first_time=false' >> "$GITHUB_OUTPUT" - echo 'should_scan=true' >> "$GITHUB_OUTPUT" - exit 0 - ;; - NONE) - ;; - COLLABORATOR|MANNEQUIN|MEMBER|OWNER) - echo 'is_first_time=false' >> "$GITHUB_OUTPUT" - echo 'should_scan=false' >> "$GITHUB_OUTPUT" - exit 0 - ;; - *) - echo "Unexpected author association: $association" >&2 - exit 1 - ;; - esac - done + api_association=$(gh api "/repos/$GITHUB_REPOSITORY/pulls/$NUMBER" \ + --jq '.author_association') + echo "API author association: $api_association" + echo "Event author association: $EVENT_ASSOCIATION" - # NONE is unresolved, not trusted. Scan without posting the welcome. - echo 'is_first_time=false' >> "$GITHUB_OUTPUT" - echo 'should_scan=true' >> "$GITHUB_OUTPUT" + case "$api_association" in + FIRST_TIMER|FIRST_TIME_CONTRIBUTOR) + echo 'is_first_time=true' >> "$GITHUB_OUTPUT" + echo 'should_scan=true' >> "$GITHUB_OUTPUT" + ;; + CONTRIBUTOR|NONE) + echo 'is_first_time=false' >> "$GITHUB_OUTPUT" + echo 'should_scan=true' >> "$GITHUB_OUTPUT" + ;; + COLLABORATOR|MANNEQUIN|MEMBER|OWNER) + echo 'is_first_time=false' >> "$GITHUB_OUTPUT" + echo 'should_scan=false' >> "$GITHUB_OUTPUT" + ;; + *) + echo "Unexpected author association: $api_association" >&2 + exit 1 + ;; + esac guidance: name: Apply contributor guidance @@ -90,8 +82,12 @@ jobs: scan-issues: false auto-close: false honeypot: false + # The privileged association check skips trusted authors before this job, + # so `trusted-author-associations` would be redundant here. + # trusted-author-associations: collaborator,member,owner - name: Comment with contributor guidance + if: env.IS_FIRST_TIME == 'true' || env.ADD_CAUTION == 'true' env: ADD_CAUTION: >- ${{ @@ -137,10 +133,8 @@ jobs: body="$WELCOME_MESSAGE"$'\n\n'"$CAUTION_MESSAGE" elif [[ "$IS_FIRST_TIME" == "true" ]]; then body="$WELCOME_MESSAGE" - elif [[ "$ADD_CAUTION" == "true" ]]; then - body="$CAUTION_MESSAGE" else - exit 0 + body="$CAUTION_MESSAGE" fi printf '%s\n' "$body" |