AI agents prepend a notice to README.md that the author removes once they have reviewed the changes. Until that happens nobody else should look at the PR: convert it to a draft, don't add the please-review label, and don't start a Claude review. The labeler and the review workflow check README.md at the PR head for the notice. Marking the PR ready for review after removing the notice triggers the normal labeling again.
158 lines
6.1 KiB
YAML
158 lines
6.1 KiB
YAML
---
|
|
# 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: |
|
|
response = await github.rest.issues.listLabelsOnIssue({
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
});
|
|
|
|
original = new Set(response.data.map(l => l.name));
|
|
labels = new Set(original);
|
|
|
|
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(labels).filter(l => good_to_merge.has(l)).length == 0) {
|
|
labels.add("please-review");
|
|
}
|
|
|
|
for (const label of ["reviewed/needs-rework 🔨",
|
|
"ci-fails/needs-rework 🔥",
|
|
"ci-failure-appears-unrelated",
|
|
"needs-rebase"]) {
|
|
labels.delete(label);
|
|
}
|
|
|
|
if (labels.size != original.size || Array.from(labels).some(l => !original.has(l))) {
|
|
await github.rest.issues.setLabels({
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
labels: Array.from(labels),
|
|
});
|
|
}
|
|
|
|
- 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,
|
|
});
|
|
|
|
original = new Set(response.data.map(l => l.name));
|
|
labels = new Set(original);
|
|
|
|
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 🏃♂️"]) {
|
|
labels.delete(label);
|
|
}
|
|
|
|
if (labels.size != original.size || Array.from(labels).some(l => !original.has(l))) {
|
|
await github.rest.issues.setLabels({
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
labels: Array.from(labels),
|
|
});
|
|
}
|