Require Linked Issue #47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # PR intake gate — see CONTRIBUTING.md ("How pull requests get in") for the | |
| # policy and .github/scripts/pr_intake_gate.js for the rules as applied. | |
| # | |
| # In short: a PR from someone without triage rights stays open only if it links | |
| # an open issue here that is assigned to them (or labeled `help wanted`); | |
| # otherwise it is labeled `missing-issue-link`, gets one comment, and is closed, | |
| # and it reopens automatically once the author is assigned. Bots and drafts are | |
| # skipped. A triage+ user reopening the PR, removing the label, or adding | |
| # `bypass-issue-check` overrides. | |
| # | |
| # Operating it: | |
| # - Live by default. To pause it without a revert, set the repository | |
| # variable PR_GATE_ENFORCE to "false": runs then only log their verdicts. | |
| # - PRs below the number in the job `if:` predate the gate and are ignored | |
| # unless evaluated by hand: `gh workflow run require-linked-issue.yml -f pr_number=N`. | |
| # | |
| # Security: pull_request_target runs with a write token in the base repo's | |
| # context, and GitHub takes both this file and the checkout from the default | |
| # branch whatever the PR targets (so PRs against v1.x are covered too). The | |
| # job checks out only that, for the script, and never fetches, builds, or runs | |
| # anything from the pull request. | |
| # | |
| # Adapted from PrefectHQ/fastmcp's require-issue-link.yml (Apache-2.0), itself | |
| # from langchain-ai/langchain (MIT). | |
| name: Require Linked Issue | |
| on: | |
| pull_request_target: # zizmor: ignore[dangerous-triggers] checks out the default branch only and never runs PR code — see header | |
| types: [opened, edited, reopened, ready_for_review, labeled, unlabeled] | |
| issues: | |
| types: [assigned] | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: PR number to evaluate | |
| required: true | |
| type: number | |
| permissions: {} | |
| jobs: | |
| gate: | |
| name: Evaluate | |
| # Routing only; the rules are in the script. PR events run at or above the | |
| # grandfathering floor, or for PRs the gate has already labeled; label | |
| # events only for the two labels the gate cares about. | |
| if: >- | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'issues' && !github.event.issue.pull_request && github.event.issue.state == 'open') || | |
| ( | |
| github.event_name == 'pull_request_target' && | |
| ( | |
| github.event.pull_request.number >= 3200 || | |
| contains(github.event.pull_request.labels.*.name, 'missing-issue-link') || | |
| github.event.action == 'unlabeled' | |
| ) && | |
| (github.event.action != 'unlabeled' || github.event.label.name == 'missing-issue-link') && | |
| (github.event.action != 'labeled' || github.event.label.name == 'bypass-issue-check') | |
| ) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| concurrency: | |
| group: require-linked-issue-${{ github.event.pull_request.number || inputs.pr_number || format('issue-{0}-{1}', github.event.issue.number, github.event.assignee.login) }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read # check out the gate script from the default branch | |
| issues: write # read linked issues; label and comment on the PR | |
| pull-requests: write # close and reopen the PR | |
| env: | |
| ENFORCE: ${{ vars.PR_GATE_ENFORCE != 'false' && 'true' || 'false' }} # kill switch: set the variable to "false" to go log-only | |
| PR_NUMBER_INPUT: ${{ inputs.pr_number }} | |
| steps: | |
| - name: Check out the gate script (default branch) | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| sparse-checkout: .github/scripts | |
| - name: Evaluate | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const run = require('./.github/scripts/pr_intake_gate.js'); | |
| await run({ github, context, core }); |