diff --git a/.github/workflows/require_issue_link.yml b/.github/workflows/require_issue_link.yml index 0d524cada4d..c878d74faa4 100644 --- a/.github/workflows/require_issue_link.yml +++ b/.github/workflows/require_issue_link.yml @@ -7,6 +7,8 @@ # - Also re-checks on PR edits/reopens for PRs that already have the label. # - Validates the PR author is an assignee on at least one linked issue. # - Adds a "missing-issue-link" label on failure; removes it on pass. +# - Automatically reopens PRs that were closed by this workflow once the +# check passes (e.g. author edits the body to add a valid issue link). # - Posts a comment explaining the requirement on failure. # - Deduplicates comments via an HTML marker so re-runs don't spam. # @@ -92,7 +94,7 @@ jobs: owner, repo, issue_number: prNumber, labels: ['missing-issue-link'], }); - - name: Remove missing-issue-link label + - name: Remove missing-issue-link label and reopen PR if: steps.check-link.outputs.has-link == 'true' && steps.check-link.outputs.is-assigned == 'true' uses: actions/github-script@v8 with: @@ -107,6 +109,18 @@ jobs: if (error.status !== 404) throw error; } + // Reopen PR only if it was previously closed by this workflow + const labels = context.payload.pull_request.labels.map(l => l.name); + if (context.payload.pull_request.state === 'closed' && labels.includes('missing-issue-link')) { + await github.rest.pulls.update({ + owner, + repo, + pull_number: prNumber, + state: 'open', + }); + console.log(`Reopened PR #${prNumber}`); + } + - name: Post comment, close PR, and fail if: steps.check-link.outputs.has-link != 'true' || steps.check-link.outputs.is-assigned != 'true' uses: actions/github-script@v8 @@ -127,8 +141,7 @@ jobs: 'All external contributions must reference an approved issue or discussion. Please:', '1. Find or [open an issue](https://github.com/' + owner + '/' + repo + '/issues/new/choose) describing the change', '2. Wait for a maintainer to approve and assign you', - '3. Add `Fixes #`, `Closes #`, or `Resolves #` to your PR description', - '4. Ask a maintainer to reopen this PR', + '3. Add `Fixes #`, `Closes #`, or `Resolves #` to your PR description and the PR will be reopened automatically', ]; } else { lines = [ @@ -137,7 +150,7 @@ jobs: '', 'External contributors must be assigned to an issue before opening a PR for it. Please:', '1. Comment on the linked issue to request assignment from a maintainer', - '2. Once assigned, ask a maintainer to reopen this PR', + '2. Once assigned, edit your PR description and the PR will be reopened automatically', ]; } diff --git a/.github/workflows/tag-external-contributions.yml b/.github/workflows/tag-external-contributions.yml index 0cb941f6fa2..577ac67d6a4 100644 --- a/.github/workflows/tag-external-contributions.yml +++ b/.github/workflows/tag-external-contributions.yml @@ -16,8 +16,7 @@ # Without it, the workflow will fail. # # Contributor tier thresholds: -# - trusted-contributor: >= 4 merged PRs -# - experienced-contributor: >= 10 merged PRs +# - trusted-contributor: >= 5 merged PRs name: Tag External Contributions @@ -184,8 +183,7 @@ jobs: const author = item.user.login; const issueNumber = item.number; - const TRUSTED_THRESHOLD = 4; - const EXPERIENCED_THRESHOLD = 10; + const TRUSTED_THRESHOLD = 5; const mergedQuery = `repo:${owner}/${repo} is:pr is:merged author:"${author}"`; let mergedCount = 0; @@ -201,12 +199,7 @@ jobs: return; } - let label = null; - if (mergedCount >= EXPERIENCED_THRESHOLD) { - label = 'experienced-contributor'; - } else if (mergedCount >= TRUSTED_THRESHOLD) { - label = 'trusted-contributor'; - } + const label = mergedCount >= TRUSTED_THRESHOLD ? 'trusted-contributor' : null; if (label) { await github.rest.issues.addLabels({ @@ -244,12 +237,11 @@ jobs: const maxItems = parseInt('${{ inputs.max_items }}') || 100; const backfillType = '${{ inputs.backfill_type }}'; - const TRUSTED_THRESHOLD = 4; - const EXPERIENCED_THRESHOLD = 10; + const TRUSTED_THRESHOLD = 5; const LABEL_COLOR = 'b76e79'; const sizeLabels = ['size: XS', 'size: S', 'size: M', 'size: L', 'size: XL']; - const tierLabels = ['trusted-contributor', 'experienced-contributor']; + const tierLabels = ['trusted-contributor']; // Ensure tier and size labels exist for (const name of [...tierLabels, ...sizeLabels]) { @@ -303,9 +295,7 @@ jobs: } function getTierLabel(mergedCount) { - if (mergedCount >= EXPERIENCED_THRESHOLD) return 'experienced-contributor'; - if (mergedCount >= TRUSTED_THRESHOLD) return 'trusted-contributor'; - return null; + return mergedCount >= TRUSTED_THRESHOLD ? 'trusted-contributor' : null; } function getSizeLabel(totalChangedLines) {