Merge pull request #12707 from cli/kw/use-shared-pr-workflows

Migrate PR triage workflows to shared workflows
This commit is contained in:
Kynan Ware 2026-02-17 10:36:42 -07:00 committed by GitHub
commit 4da3fc5713
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 59 additions and 226 deletions

View file

@ -1,46 +0,0 @@
name: PR Help Wanted Check
on:
pull_request_target:
types: [opened]
workflow_dispatch:
inputs:
pr_number:
description: "Pull Request number to check"
required: true
type: string
permissions:
contents: none
issues: read
pull-requests: write
jobs:
check-help-wanted:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set PR variables for workflow_dispatch event
id: pr-vars-dispatch
if: github.event_name == 'workflow_dispatch'
env:
PR_NUMBER: ${{ github.event.inputs.pr_number }}
run: |
# We only need to construct the PR URL from the dispatch event input.
echo "pr_url=https://github.com/cli/cli/pull/${PR_NUMBER}" >> $GITHUB_OUTPUT
- name: Check for issues without help-wanted label
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# These variables are optionally used in the check-help-wanted.sh
# script for additional checks; but they are not strictly necessary
# for the script to run. This is why we are okay with them being
# empty when the event is workflow_dispatch.
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_AUTHOR_TYPE: ${{ github.event.pull_request.user.type }}
PR_AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
PR_URL: ${{ github.event.pull_request.html_url || steps.pr-vars-dispatch.outputs.pr_url }}
run: |
# Run the script to check for issues without help-wanted label
bash .github/workflows/scripts/check-help-wanted.sh "${PR_URL}"

View file

@ -1,75 +0,0 @@
name: PR Automation
on:
pull_request_target:
types: [ready_for_review, opened, reopened]
permissions:
contents: none
issues: write
pull-requests: write
jobs:
pr-auto:
runs-on: ubuntu-latest
environment: cli-automation
steps:
- name: lint pr
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.AUTOMATION_TOKEN }}
PRBODY: ${{ github.event.pull_request.body }}
PRNUM: ${{ github.event.pull_request.number }}
PRHEAD: ${{ github.event.pull_request.head.label }}
PRAUTHOR: ${{ github.event.pull_request.user.login }}
PR_AUTHOR_TYPE: ${{ github.event.pull_request.user.type }}
if: "!github.event.pull_request.draft"
run: |
commentPR () {
gh pr comment $PRNUM -b "${1}"
}
closePR () {
gh pr close $PRNUM
}
colID () {
gh api graphql -f query='query($owner:String!, $repo:String!) {
repository(owner:$owner, name:$repo) {
project(number:1) {
columns(first:10) { nodes {id,name} }
}
}
}' -f owner="${GH_REPO%/*}" -f repo="${GH_REPO#*/}" \
-q ".data.repository.project.columns.nodes[] | select(.name | startswith(\"$1\")) | .id"
}
if [ "$PR_AUTHOR_TYPE" = "Bot" ] || gh api orgs/cli/public_members/$PRAUTHOR --silent 2>/dev/null
then
if [ "$PR_AUTHOR_TYPE" != "Bot" ]
then
gh pr edit $PRNUM --add-assignee $PRAUTHOR
fi
exit 0
fi
gh pr edit $PRNUM --add-label "external"
if [ "$PRHEAD" = "cli:trunk" ]
then
closePR
exit 0
fi
if [ $(wc -c <<<"$PRBODY") -lt 10 ]
then
commentPR "Thanks for the pull request! We're a small team and it's helpful to have context around community submissions in order to review them appropriately. Our automation has closed this pull request since it does not have an adequate description. Please edit the body of this pull request to describe what this does, then reopen it."
closePR
exit 0
fi
if ! grep -Eq '(#|issues/)[0-9]+' <<<"$PRBODY"
then
commentPR "Hi! Thanks for the pull request. Please ensure that this change is linked to an issue by mentioning an issue number in the description of the pull request. If this pull request would close the issue, please put the word 'Fixes' before the issue number somewhere in the pull request body. If this is a tiny change like fixing a typo, feel free to ignore this message."
fi
exit 0

View file

@ -1,105 +0,0 @@
#!/bin/bash
set -e
PR_URL="$1"
if [ -z "$PR_URL" ]; then
echo "Usage: $0 <PR_URL>"
echo ""
echo "Check if the PR references any non-help-wanted issues and, if so, comment"
echo "on it explaining why the team might close/dismiss it."
exit 1
fi
# Skip if PR is from a bot or org member
if [ "$PR_AUTHOR_TYPE" = "Bot" ] || [ "$PR_AUTHOR_ASSOCIATION" = "MEMBER" ] || [ "$PR_AUTHOR_ASSOCIATION" = "OWNER" ]; then
echo "Skipping check for PR $PR_URL as it is from a bot ($PR_AUTHOR_TYPE) or an org member ($PR_AUTHOR_ASSOCIATION: MEMBER/OWNER)"
exit 0
fi
# Skip if PR is a draft
if [ "$(gh pr view "${PR_URL}" --json isDraft --jq '.isDraft')" != "false" ]; then
echo "Skipping check for PR $PR_URL as it is a draft"
exit 0
fi
# Extract PR number from URL for logging
PR_NUM="$(basename "$PR_URL")"
# Extract cli/cli closing issues references from PR
CLOSING_ISSUES="$(gh pr view "$PR_URL" --json closingIssuesReferences --jq '.closingIssuesReferences[] | select(.repository.name == "cli" and .repository.owner.login == "cli") | .number')"
if [ -z "$CLOSING_ISSUES" ]; then
echo "No closing issues found for PR #$PR_NUM"
exit 0
fi
# Check each closing issue for 'help-wanted' label
ISSUES_WITHOUT_HELP_WANTED=()
for issue_num in $CLOSING_ISSUES; do
echo "Checking issue #$issue_num for 'help wanted' label..."
# Get issue labels
LABELS=$(gh issue view "$issue_num" --json labels --jq '.labels[].name')
# Skip if the issue has the gh-attestion or gh-codespace label
# This is because the codeowners for these commands may not be public
# cli org members, and so unless we authenticate with a PAT, we can't
# know who is an external contributor or not.
# So we skip these issues to avoid falsely writing a comment
# on each PR opened by these codeowners.
if echo "$LABELS" | grep -q -e "gh-attestation" -e "gh-codespace"; then
echo "Issue #$issue_num is skipped due to labels"
continue
fi
# Check if 'help wanted' label exists
if ! echo "$LABELS" | grep -qE '^help wanted$'; then
ISSUES_WITHOUT_HELP_WANTED+=("$issue_num")
echo "Issue #$issue_num does not have 'help wanted' label"
else
echo "Issue #$issue_num has 'help wanted' label"
fi
done
# If we found issues without 'help wanted' label, post a comment
if [ ${#ISSUES_WITHOUT_HELP_WANTED[@]} -gt 0 ]; then
echo "Found ${#ISSUES_WITHOUT_HELP_WANTED[@]} issues without 'help wanted' label"
# Build issue list for comment
ISSUE_LIST=""
for issue_num in "${ISSUES_WITHOUT_HELP_WANTED[@]}"; do
ISSUE_LIST="$ISSUE_LIST- #$issue_num"$'\n'
done
# Create comment message
gh pr comment "$PR_URL" --body-file - <<EOF
Thank you for your pull request! 🎉
This PR appears to fix the following issues that are not labeled with https://github.com/cli/cli/labels/help%20wanted:
$ISSUE_LIST
As outlined in our [Contributing Guidelines](https://github.com/cli/cli/blob/trunk/.github/CONTRIBUTING.md), we expect that PRs are only created for issues that have been labeled \`help wanted\`.
While we appreciate your initiative, please note that:
- **PRs for non-\`help wanted\` issues may not be reviewed immediately** as they might not align with our current priorities
- **The issue might already be assigned** to a team member or planned for a specific release
- **We may need to close this PR**. For example, if it conflicts with ongoing work or architectural decisions
**What happens next:**
- Our team will review this PR and the associated issues
- We may add the \`help wanted\` label to the issues, if appropriate, and review this pull request
- In some cases, we may need to close the PR. For example, if it doesn't fit our current roadmap
Thank you for your understanding and contribution to the project! 🙏
*This comment was automatically generated by cliAutomation.*
EOF
echo "Posted comment on PR #$PR_NUM"
else
echo "All closing issues have 'help wanted' label - no action needed"
fi

View file

@ -0,0 +1,59 @@
name: PR Triaging
on:
pull_request_target:
types: [opened, reopened, edited, labeled, ready_for_review]
schedule:
- cron: '0 4 * * *' # Daily at 4 AM UTC — close unmet-requirements PRs
jobs:
label-external:
if: >-
github.event_name == 'pull_request_target' &&
(github.event.action == 'opened' || github.event.action == 'reopened')
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-label-external-pr.yml@main
permissions:
issues: write
pull-requests: write
repository-projects: read
close-from-default-branch:
if: >-
github.event_name == 'pull_request_target' &&
github.event.action == 'opened'
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-close-from-default-branch.yml@main
with:
default_branch: trunk
permissions:
pull-requests: write
check-requirements:
if: >-
github.event_name == 'pull_request_target' &&
(github.event.action == 'opened' || github.event.action == 'reopened' || github.event.action == 'edited')
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-pr-requirements.yml@main
permissions:
issues: read
pull-requests: write
close-unmet-requirements:
if: github.event_name == 'schedule'
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-pr-requirements.yml@main
permissions:
issues: read
pull-requests: write
close-no-help-wanted:
if: >-
github.event_name == 'pull_request_target' &&
github.event.action == 'labeled'
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-close-no-help-wanted.yml@main
permissions:
pull-requests: write
ready-for-review:
if: >-
github.event_name == 'pull_request_target' &&
github.event.action == 'labeled'
uses: desktop/gh-cli-and-desktop-shared-workflows/.github/workflows/triage-ready-for-review.yml@main
permissions:
pull-requests: write