From 514342fe41836cddd79227e9e5000a1febb61172 Mon Sep 17 00:00:00 2001 From: samzong Date: Thu, 14 May 2026 16:45:00 +0800 Subject: [PATCH] fix(workflow): clear review eyes reaction on completion Signed-off-by: samzong --- .github/workflows/sweep.yml | 61 +++++++++++++++++++++++++++++-------- test/clawsweeper.test.ts | 14 +++++++++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/.github/workflows/sweep.yml b/.github/workflows/sweep.yml index 7739951f03..3c79fb74d2 100644 --- a/.github/workflows/sweep.yml +++ b/.github/workflows/sweep.yml @@ -473,19 +473,54 @@ jobs: run: | set -euo pipefail test -n "$GH_TOKEN" - err="$(mktemp)" - if gh api -X POST \ - -H "Accept: application/vnd.github+json" \ - "repos/$TARGET_REPO/issues/$ITEM_NUMBER/reactions" \ - -f content="+1" 2>"$err" >/dev/null; then - echo "Added +1 reaction to $TARGET_REPO#$ITEM_NUMBER." - elif grep -qi "HTTP 422\\|already exists" "$err"; then - echo "+1 reaction already exists on $TARGET_REPO#$ITEM_NUMBER." - else - cat "$err" >&2 - exit 1 - fi - rm -f "$err" + add_completion_reaction() { + local err + err="$(mktemp)" + if gh api -X POST \ + -H "Accept: application/vnd.github+json" \ + "repos/$TARGET_REPO/issues/$ITEM_NUMBER/reactions" \ + -f content="+1" 2>"$err" >/dev/null; then + echo "Added +1 reaction to $TARGET_REPO#$ITEM_NUMBER." + elif grep -qi "HTTP 422\\|already exists" "$err"; then + echo "+1 reaction already exists on $TARGET_REPO#$ITEM_NUMBER." + else + cat "$err" >&2 + rm -f "$err" + exit 1 + fi + rm -f "$err" + } + remove_own_eyes_reactions() { + local ids + local err + err="$(mktemp)" + if ! ids="$(gh api -X GET \ + -H "Accept: application/vnd.github+json" \ + "repos/$TARGET_REPO/issues/$ITEM_NUMBER/reactions" \ + -f content="eyes" \ + -F per_page=100 \ + --paginate \ + --jq '.[] | select(.content == "eyes") | select((.user.login // "") as $login | ["clawsweeper","clawsweeper[bot]","openclaw-clawsweeper[bot]"] | index($login)) | .id' 2>"$err")"; then + cat "$err" >&2 + rm -f "$err" + return 0 + fi + rm -f "$err" + while IFS= read -r reaction_id; do + [ -n "$reaction_id" ] || continue + err="$(mktemp)" + if gh api -X DELETE \ + -H "Accept: application/vnd.github+json" \ + "repos/$TARGET_REPO/issues/$ITEM_NUMBER/reactions/$reaction_id" 2>"$err" >/dev/null; then + echo "Removed eyes reaction $reaction_id from $TARGET_REPO#$ITEM_NUMBER." + else + cat "$err" >&2 + fi + rm -f "$err" + done <<< "$ids" + } + add_completion_reaction + remove_own_eyes_reactions plan: name: Plan review candidates diff --git a/test/clawsweeper.test.ts b/test/clawsweeper.test.ts index 0d665804bc..70e7434cde 100644 --- a/test/clawsweeper.test.ts +++ b/test/clawsweeper.test.ts @@ -3212,6 +3212,20 @@ test("review workflow gives Codex a read-only inspection token", () => { assert.match(workflow, /CLAWSWEEPER_PROOF_INSPECTION_TOKEN/); }); +test("event review completion removes ClawSweeper eyes reaction", () => { + const workflow = readFileSync(".github/workflows/sweep.yml", "utf8"); + const block = workflow.slice( + workflow.indexOf("- name: React to target item completion"), + workflow.indexOf("\n\n plan:"), + ); + + assert.match(block, /-f content="\+1"/); + assert.match(block, /-f content="eyes"/); + assert.match(block, /repos\/\$TARGET_REPO\/issues\/\$ITEM_NUMBER\/reactions\/\$reaction_id/); + assert.match(block, /"openclaw-clawsweeper\[bot\]"/); + assert.doesNotMatch(block, /issues\/comments\/\$ITEM_NUMBER\/reactions/); +}); + test("manual exact-item review dispatches avoid broad review concurrency", () => { const workflow = readFileSync(".github/workflows/sweep.yml", "utf8");