Skip to content

feat(seidroid-review): acknowledge the trigger with a reaction - #72

Merged
bdchatham merged 1 commit into
feat/seidroid-reviewfrom
feat/acknowledge-the-trigger
Sep 5, 2026
Merged

feat(seidroid-review): acknowledge the trigger with a reaction#72
bdchatham merged 1 commit into
feat/seidroid-reviewfrom
feat/acknowledge-the-trigger

Conversation

@bdchatham

Copy link
Copy Markdown
Contributor

What

Reacts 👀 to the triggering comment as the first step of the review job.

Why

A review takes minutes to produce its first visible output — the Go
toolchain, the driver install, and the session start all run before anything
appears on the pull request. Until then nothing on the PR distinguishes "the
trigger was seen" from "the trigger was dropped", and the person who asked
has to open the Actions tab to find out which.

This is not hypothetical. During a credential outage, runs completed
success and posted nothing, and the only way to tell a working review from
a broken one was to read the workflow log. An acknowledgement would have
separated the two immediately.

It is the first step deliberately. An acknowledgement that arrives after the
verdict is not one.

Scope

  • Comment path only. An automatic pull_request review has no comment to
    react to, so the guard leaves comment_id empty and the step is skipped.
  • continue-on-error. An acknowledgement is a courtesy. Failing the
    review because a reaction did not post would trade the whole job for the
    signal that the job started. A failure emits a ::warning:: instead.
  • Idempotent. Reactions are unique per (user, content), so re-running a
    review on the same comment returns the existing reaction rather than adding
    a second one. A retry needs no cleanup.

The permission

The job gains issues: write. A reaction on a pull request comment goes to
the /repos/{repo}/issues/comments/{id}/reactions endpoint, which
pull-requests: write does not cover — the likely reason this was never
wired up.

Verification

actionlint is clean on the new step; the four findings it reports are
pre-existing, at lines 326/1001/1177.

Behaviour needs a live trigger to confirm, since it depends on the token's
effective permissions in the calling repository. The consumer-side pin bump
is sei-load#97.

🤖 Generated with Claude Code

A review takes minutes to reach its first visible output: the Go toolchain,
the driver install, and the session start all run before anything appears on
the pull request. Until then nothing distinguishes "the trigger was seen"
from "the trigger was dropped", and the person who asked has no way to tell
which without opening the Actions tab.

React to the triggering comment as the first step of the review job, so the
acknowledgement precedes the work rather than trailing it.

Comment path only: an automatic pull_request review has no comment to react
to, so the guard leaves comment_id empty and the step is skipped. It is also
continue-on-error -- an acknowledgement is a courtesy, and failing the review
because a reaction did not post would trade the job for the signal that the
job started.

A reaction on a pull-request comment goes to the ISSUE comments endpoint,
which `pull-requests: write` does not cover, so the job also takes
`issues: write`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Workflow-only change: broader token scope for a best-effort first step that cannot fail the review job.

Overview
Comment-triggered reviews now post a 👀 reaction on the triggering comment as the first step of the review job, so requesters get immediate PR feedback instead of waiting through Go setup, driver install, and session start (or digging in Actions when a run succeeds but posts nothing).

The step runs only when the guard supplies a comment_id (manual @seidroid review; automatic pull_request runs skip it). It uses continue-on-error and logs a workflow warning if the reaction fails, so a courtesy ack cannot fail the review. Reactions are idempotent per user/content on retries.

The job adds issues: write because PR comment reactions hit the issues comments reactions API, which pull-requests: write does not authorize.

Reviewed by Cursor Bugbot for commit a951ebb. Bugbot is set up for automated code reviews on this repo. Configure here.

@bdchatham
bdchatham merged commit 2f11d75 into feat/seidroid-review Sep 5, 2026
5 checks passed
@bdchatham
bdchatham deleted the feat/acknowledge-the-trigger branch September 5, 2026 15:32

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A small, well-scoped addition that reacts 👀 to the triggering comment as the first step of the review job; the shell is injection-safe (all GitHub values routed through env), the guard correctly skips the automatic pull_request path, and the idempotency claim holds. Two rollout/diagnostic concerns worth addressing before merge, none of which break the same-repo happy path.

Findings: 0 blocking | 4 non-blocking | 3 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The header block at the top of the file documents every other caller-facing requirement (pins, secrets, trigger wiring) but says nothing about the job's GITHUB_TOKEN scopes. Since this change makes a caller-side permission newly load-bearing, a line in that block — or in .github/seidroid/README.md — stating that the calling job must grant issues: write would save the next consumer a failed run.
  • 3 suggestion(s)/nit(s) flagged inline on specific lines.

checks: write # publish the review check run
# React to the triggering comment. A reaction on a PR comment goes to the
# ISSUE comments endpoint, which pull-requests: write does not cover.
issues: write # acknowledge the trigger with a reaction

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[suggestion] This is a reusable workflow, so the caller's token is the ceiling: a called job may only downgrade the caller's permissions, never elevate them. Where the calling job enumerates its permissions: (as every workflow in this repo does) without issues: write — or where the org restricts the default GITHUB_TOKEN — GitHub rejects the request rather than intersecting it, failing the whole review job before any step runs (The workflow is requesting 'issues: write', but is only allowed 'issues: none'). The step's continue-on-error cannot protect against that, because the failure is workflow validation, not the step.

The effect is the inverse of the change's purpose: a caller that bumps the pin without also adding the permission loses the entire review, not just the acknowledgement. Worth confirming sei-load#97 adds issues: write to the caller job and lands with the bump, and worth stating the new caller requirement in this file's header alongside the other caller-facing wiring.

# the same comment returns the existing reaction rather than adding a
# second one, so a retry needs no cleanup.
if gh api -X POST "repos/$REPO/issues/comments/$TRIGGER_ID/reactions" \
-f content=eyes >/dev/null 2>&1; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[suggestion] 2>/dev/null discards the API error at exactly the moment it is worth having. This change exists so a human can tell "seen" from "dropped" without opening the Actions tab; when the reaction itself fails, the warning says only that it failed, and the log no longer distinguishes a 403 (the caller did not grant issues: write) from a 404 (wrong comment id) from a rate limit — so the diagnosis moves back into the workflow log the change set out to avoid, minus the one line that would have explained it.

Capturing stderr and folding it into the warning keeps that, e.g.:

if err=$(gh api -X POST "repos/$REPO/issues/comments/$TRIGGER_ID/reactions" \
    -f content=eyes 2>&1 >/dev/null); then
  echo "acknowledged comment $TRIGGER_ID"
else
  echo "::warning::could not react to comment $TRIGGER_ID; the review continues: $(printf '%s' "$err" | tr '\n' ' ')"
fi

The tr matters: an annotation is single-line, so a multi-line gh error would otherwise truncate at the first newline.

if: ${{ needs.guard.outputs.comment_id != '' }}
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[nit] The reaction lands as github-actions[bot] rather than as seidroid, because the identity mint runs later in the job. In a repository that also runs ai-review.yml under that same default identity, the 👀 does not say which automation saw the trigger — a weaker signal than the sticky verdict that follows it.

Not a straightforward fix, and reasonable to leave as is: the App token is scoped to review_repo_name || github.event.repository.name, so on a cross-repository trigger it is scoped to the reviewed repo and could not react to a comment living here. github.token is the only credential that always covers the comment being reacted to. If it seems worth aligning the attribution for the same-repo path, that would mean moving the mint above this step and falling back to github.token; otherwise the current choice is the correct one and the tradeoff is worth a line in the step's comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant