Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions .github/workflows/review-claims.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
pull_request_review:
types: [submitted]
schedule:
- cron: "23 */6 * * *"
- cron: "23 * * * *"
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -138,8 +138,16 @@ jobs:
}
for (const name of present) {
if (latestLabeler[name] === reviewer) {
await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name });
core.info(`Removed ${name}: claimer ${reviewer} submitted their review.`);
try {
await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name });
core.info(`Removed ${name}: claimer ${reviewer} submitted their review.`);
} catch (e) {
if (e.status === 403) {
core.warning(`Token is read-only in this PR context; the hourly sweep will release ${name} instead.`);
} else {
throw e;
}
}
} else {
core.info(`Kept ${name}: claimed by ${latestLabeler[name] ?? 'unknown'}, review came from ${reviewer}.`);
}
Expand Down Expand Up @@ -192,12 +200,18 @@ jobs:
let removedAny = false;
for (const name of present) {
const info = latest[name];
if (!info || now - info.at < MAX_AGE_MS) continue;
if (!info) continue;
const reviewedSince = reviews.some((r) =>
r.user && r.user.login === info.actor &&
Date.parse(r.submitted_at) > info.at &&
(r.state === 'APPROVED' || r.state === 'CHANGES_REQUESTED'));
if (reviewedSince) continue;
if (reviewedSince) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When a claimer reapplies a label while the sweep is between its reads and deletion, reviewedSince still describes the previous claim and removes the new claim. Revalidate or serialize the current claim generation before deleting the label.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/review-claims.yml, line 208:

<comment>When a claimer reapplies a label while the sweep is between its reads and deletion, `reviewedSince` still describes the previous claim and removes the new claim. Revalidate or serialize the current claim generation before deleting the label.</comment>

<file context>
@@ -192,12 +200,18 @@ jobs:
                   Date.parse(r.submitted_at) > info.at &&
                   (r.state === 'APPROVED' || r.state === 'CHANGES_REQUESTED'));
-                if (reviewedSince) continue;
+                if (reviewedSince) {
+                  await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name })
+                    .catch((e) => core.info(`PR #${pr.number}: ${name} release skipped: ${e.message}`));
</file context>

await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name })
.catch((e) => core.info(`PR #${pr.number}: ${name} release skipped: ${e.message}`));
core.info(`PR #${pr.number}: released ${name} — claimer ${info.actor} already reviewed (backstop for restricted-token contexts).`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When removeLabel fails, the catch swallows the error and the next line reports the claim as released even though it remains active. Log success only after a successful removal.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/review-claims.yml, line 211:

<comment>When `removeLabel` fails, the catch swallows the error and the next line reports the claim as released even though it remains active. Log success only after a successful removal.</comment>

<file context>
@@ -192,12 +200,18 @@ jobs:
+                if (reviewedSince) {
+                  await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name })
+                    .catch((e) => core.info(`PR #${pr.number}: ${name} release skipped: ${e.message}`));
+                  core.info(`PR #${pr.number}: released ${name} — claimer ${info.actor} already reviewed (backstop for restricted-token contexts).`);
+                  continue;
+                }
</file context>

continue;
}
if (now - info.at < MAX_AGE_MS) continue;
await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name })
.catch((e) => core.info(`PR #${pr.number}: ${name} removal skipped: ${e.message}`));
removedAny = true;
Expand Down