diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index 38aa4c4083..1ff05a874d 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -63,6 +63,7 @@ jobs: pull-requests: write outputs: + skip: ${{ steps.context.outputs.skip }} pr_number: ${{ steps.context.outputs.pr_number }} comment_id: ${{ steps.context.outputs.comment_id }} head_sha: ${{ steps.context.outputs.head_sha }} @@ -132,6 +133,21 @@ jobs: github.paginate(github.rest.pulls.listReviewComments, { owner, repo, pull_number: prNumber, per_page: 100 }), ]); + /* A README.md that still carries the AI review notice has not been + * looked at by its author yet, so there is nothing to review. */ + const readme = await github.rest.repos.getContent({ + owner, + repo, + path: "README.md", + ref: pr.data.head.sha, + }); + if (Buffer.from(readme.data.content, "base64").toString() + .includes("Remove this line to confirm you've reviewed this PR before submitting.")) { + console.log("README.md still carries the review notice, skipping."); + core.setOutput("skip", "true"); + return; + } + /* Find or create tracking comment. */ const existing = issueComments.find((c) => c.user?.login === "github-actions[bot]" && c.body?.includes(MARKER)); @@ -201,6 +217,7 @@ jobs: review: runs-on: ubuntu-latest needs: setup + if: needs.setup.outputs.skip != 'true' timeout-minutes: 55 permissions: @@ -496,7 +513,7 @@ jobs: needs: [setup, review] # Run unless setup never started, so a setup that dies after creating the # tracking comment cannot strand the transient banner on the pull request. - if: always() && needs.setup.result != 'skipped' + if: always() && needs.setup.result != 'skipped' && needs.setup.outputs.skip != 'true' permissions: pull-requests: write diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index ab0c205e02..f3d7edf4f3 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -64,7 +64,28 @@ jobs: "good-to-merge/waiting-for-reporter-feedback 👍", ]); - if (Array.from(labels).filter(l => good_to_merge.has(l)).length == 0) { + /* 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"); }