diff --git a/.github/workflows/pr_enforce_labels.yml b/.github/workflows/pr_enforce_labels.yml deleted file mode 100644 index 829ab1f20..000000000 --- a/.github/workflows/pr_enforce_labels.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Check PR Labels - -on: - pull_request: - types: [opened, synchronize, edited, labeled, unlabeled] - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -permissions: - pull-requests: read - contents: read - -jobs: - check-label: - # Skip bot PRs — they already have labels from the workflows/bots that create them - if: >- - github.event.pull_request.user.login != 'renovate[bot]' && - github.event.pull_request.user.login != 'github-actions[bot]' && - github.event.pull_request.user.login != 'dependabot[bot]' && - github.event.pull_request.head.ref != 'scheduled-updates' && - github.event.pull_request.head.ref != 'l10n_main' - runs-on: ubuntu-24.04-arm - steps: - - name: Check for PR labels - uses: actions/github-script@v9 - with: - script: | - // Extract labels from the payload directly to avoid extra API calls - const latestLabels = context.payload.pull_request.labels.map(label => label.name); - const requiredLabels = ['bugfix', 'enhancement', 'automation', 'dependencies', 'repo', 'release', 'refactor', 'desktop', 'chore', 'ci', 'build', 'testing', 'documentation']; - console.log('Labels from payload:', latestLabels); - const hasRequiredLabel = latestLabels.some(label => requiredLabels.includes(label)); - if (!hasRequiredLabel) { - core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`); - } diff --git a/.github/workflows/pull-request-target.yml b/.github/workflows/pull-request-target.yml index 543242f20..080027eb3 100644 --- a/.github/workflows/pull-request-target.yml +++ b/.github/workflows/pull-request-target.yml @@ -1,7 +1,7 @@ name: "Pull Request Labeler" on: pull_request_target: - types: [opened, synchronize] + types: [opened, synchronize, reopened, labeled, unlabeled] # Do not execute arbitrary code on this workflow. # See warnings at https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target @@ -106,3 +106,23 @@ jobs: } else { core.info('No labels matched for this PR.'); } + + // Enforce that the PR ends up with a required label. Done here (not in a + // separate pull_request workflow) so the check sees labels this job just + // applied: label events fired by GITHUB_TOKEN don't re-trigger workflows, + // so a separate checker would read an empty label set at `opened` and stay + // red forever. Bot PRs are labeled by their own flows and are skipped. + const author = context.payload.pull_request.user.login; + const headRef = context.payload.pull_request.head.ref; + const skipAuthors = ['renovate[bot]', 'github-actions[bot]', 'dependabot[bot]']; + const skipRefs = ['scheduled-updates', 'l10n_main']; + if (!skipAuthors.includes(author) && !skipRefs.includes(headRef)) { + const requiredLabels = ['bugfix', 'enhancement', 'automation', 'dependencies', 'repo', 'release', 'refactor', 'desktop', 'chore', 'ci', 'build', 'testing', 'documentation']; + const effectiveLabels = new Set([ + ...context.payload.pull_request.labels.map(l => l.name), + ...labels, + ]); + if (!requiredLabels.some(l => effectiveLabels.has(l))) { + core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`); + } + }