--- # vi: ts=2 sw=2 et: # SPDX-License-Identifier: LGPL-2.1-or-later # name: "Pull Request Labeler" on: pull_request_target: types: [opened, synchronize, reopened, ready_for_review, closed] paths-ignore: - '.github/labeler.yml' - '.github/workflows/labeler.yml' # Allow testing changes made to the labeler configuration pull_request: paths: - '.github/labeler.yml' - '.github/workflows/labeler.yml' issue_comment: types: [created] permissions: contents: read jobs: triage: if: github.repository == 'systemd/systemd' runs-on: ubuntu-24.04 permissions: pull-requests: write steps: - name: Repository checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 if: github.event_name == 'pull_request' with: persist-credentials: false - name: Label PR based on policy in labeler.yml uses: actions/labeler@c5dadc2a45784a4b6adfcd20fea3465da3a5f904 if: startsWith(github.event_name, 'pull_request') && github.base_ref == 'main' && github.event.action != 'closed' with: repo-token: "${{ secrets.GITHUB_TOKEN }}" configuration-path: .github/labeler.yml sync-labels: false - name: Set or remove labels based on systemd development workflow uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 if: startsWith(github.event_name, 'pull_request') && github.event.action != 'closed' && !github.event.pull_request.draft with: script: | /* Never read the full label set and write it back: other workflows * label the same pull request concurrently and setLabels() would * clobber whatever they added in the meantime. Only ever add or * remove the individual labels this step owns. */ const removeLabel = async (name) => { try { await github.rest.issues.removeLabel({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, name: name, }); } catch (error) { /* Somebody else removed it first. */ if (error.status !== 404) { throw error; } } }; response = await github.rest.issues.listLabelsOnIssue({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); labels = new Set(response.data.map(l => l.name)); good_to_merge = new Set([ "good-to-merge/waiting-for-ci 👍", "good-to-merge/after-next-release", "good-to-merge/with-minor-suggestions", "good-to-merge/waiting-for-reporter-feedback 👍", ]); /* A README.md that still carries the AI review notice has not been * looked at by its author yet, so nobody else should review it. */ const readme = await github.rest.repos.getContent({ owner: context.repo.owner, repo: context.repo.repo, path: "README.md", ref: context.payload.pull_request.head.sha, }); const unreviewed = Buffer.from(readme.data.content, "base64").toString() .includes("Remove this line to confirm you've reviewed this PR before submitting."); if (unreviewed) { /* Only GraphQL can do this. The author marks the PR ready again once * the notice is gone, which triggers the labeling below. */ await github.graphql(` mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { isDraft } } } `, { id: context.payload.pull_request.node_id }); } else if (!Array.from(good_to_merge).some(l => labels.has(l)) && !labels.has("please-review")) { await github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: ["please-review"], }); } for (const label of ["reviewed/needs-rework 🔨", "ci-fails/needs-rework 🔥", "ci-failure-appears-unrelated", "needs-rebase"]) { if (labels.has(label)) { await removeLabel(label); } } - name: Add please-review label on command in issue comment uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 if: github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/please-review') with: script: | await github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: ["please-review"] }) - name: Remove specific labels when PR is closed or merged uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 if: startsWith(github.event_name, 'pull_request') && github.event.action == 'closed' with: script: | response = await github.rest.issues.listLabelsOnIssue({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); labels = new Set(response.data.map(l => l.name)); for (const label of ["please-review", "reviewed/needs-rework 🔨", "ci-fails/needs-rework 🔥", "needs-rebase", "good-to-merge/waiting-for-ci 👍", "good-to-merge/after-next-release", "good-to-merge/with-minor-suggestions", "good-to-merge/waiting-for-reporter-feedback 👍", "needs-discussion 🤔", "needs-reporter-feedback ❓", "dont-merge 💣", "squash-on-merge", "quick-review 🏃‍♂️"]) { if (!labels.has(label)) { continue; } try { await github.rest.issues.removeLabel({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, name: label, }); } catch (error) { /* Somebody else removed it first. */ if (error.status !== 404) { throw error; } } }