Skip to content

fix(actions): Lopu repairs failed PR checks - #432

Merged
lopugit merged 3 commits into
github-actionsfrom
lopu/workflow-check-fix-33045346055
Aug 27, 2026
Merged

fix(actions): Lopu repairs failed PR checks#432
lopugit merged 3 commits into
github-actionsfrom
lopu/workflow-check-fix-33045346055

Conversation

@lopugit

@lopugit lopugit commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Lopu controller check repair

Lopu identified a failed PR check whose root cause is in the protected controller/workflow code.

Lopu control-plane fix: the review selector must fail closed on an unrouted event

Found while reviewing PR #428 (codex/lopu-default-listener-parity), which
activates a workflow_run trigger on the default-branch Lopu PR manager
listener.

Diagnosis

.github/workflows/resolve-pr-conflicts.yml → job review_detect → step
Select one Lopu review scope derived its candidate set with an unconditional
fallback:

if   [ -n "$SELECTED_PR" ];                                    then ...one PR
elif [ "$EVENT_NAME" = push ] && [ "$EVENT_REF" != github-actions ]; then ...that branch
elif [ -n "$SELECTED_BRANCH" ];                                then ...that branch
else candidates="$open"        # <-- every open PR, for ANY other event
fi

Product-branch listeners are metadata-only by design: they carry triggers and
permissions and call this file pinned at @github-actions. A listener
therefore cannot know which revision of the controller it is calling. When a
listener activates an event this controller does not yet route, no
SELECTED_PR/SELECTED_BRANCH can be derived, execution reached the bare
else, and review_handoff dispatched a repository-wide Lopu review — one
model session covering every eligible open PR (79 at the time of writing) —
for each such signal. The control plane failed open on exactly the input it
understood least.

This is a defect class, not a single-event bug. route's if has per-event
admission gates for issue_comment, pull_request_review_comment and
check_run; detect, manage_rebases and review_detect each exclude
specific known events. Nothing established a default for an event nobody had
enumerated yet.

PR #428 is the live trigger. It adds

  workflow_run:
    workflows: [API tests, CI, Lopu CodeQL all branches, Workflow control-plane CI,
                Develop S3 PR preview, Signed Electron PR Release,
                Electron App Release, Web CI, Build all branch]
    types: [completed]

to main's listener, while the routing implementation is still open in PR #429
against github-actions. github-actions@cb7e6f2a contains exactly one
occurrence of the string workflow_run — a comment. If #428 merges first,
every completed run of those workflows on any branch — successes
included, since on: cannot filter a conclusion — enters this controller and
escalates to an all-PR review. Those nine workflows produced 348 runs in the
preceding 24 hours
(Lopu CodeQL all branches 157, Develop S3 PR preview
85, Build all branch 44, Web CI 33, Signed Electron PR Release 15,
Workflow control-plane CI 14). Concurrency bounds how many run at once, so
the failure mode is a permanently saturated Lopu fleet rather than a fork bomb,
but targeted PR reviews would queue behind repo-wide sweeps indefinitely.

Merge order was the only thing standing between the repository and that state,
and merge order across two different base branches is not expressible in
GitHub. The fix belongs in the controller, not in a merge-sequencing
convention.

Change

One elif/else in review_detect's scope selector
(.github/workflows/resolve-pr-conflicts.yml):

  • Keep candidates="$open" for the two signals that legitimately mean every
    open PR
    : a blank workflow_dispatch (operator recovery and the internal
    batch worker), and a push to github-actions (a new resolver revision
    worth re-applying everywhere).
  • Any other event that yields no exact scope now logs a ::notice::, sets
    any=false and exits 0. review_handoff needs any == 'true', so no
    worker is dispatched and no model tokens are spent.

Deliberately out of scope: the workflow_run routing itself. PR #429 already
implements it correctly (route conclusion gate, workflow_run.pull_requests[0].number
as the review selector, workflow_run excluded from detect and
manage_rebases, source run id preserved for log diagnosis). This change is
the default-deny underneath it and is written to merge cleanly alongside #429
it touches the shell body of the step, roughly 20 lines below the
SELECTED_PR: env line that #429 edits.

manage_rebases was checked and already fails closed: rebase-pr-stacks.yml's
event case ends in *) candidates='[]' ;;. detect still runs for an
unrouted event, but its scope collapses to "PRs based on github.ref_name",
which is API-only, idempotent, concurrency-serialized and identical to work the
half-hourly sweep already does. #429 removes that residual churn properly.

Validation

Run in $GITHUB_WORKSPACE/trusted:

Check Result
ruby -ryaml load (aliases: true) OK — 18 jobs
python3 -c "yaml.safe_load(...)" OK
git diff --check OK
node --check over every .github/scripts/*.mjs OK
bash -n over every .github/scripts/*.sh OK
node .github/scripts/resolve-pr-conflicts-routing-contract.mjs --self-test self-test OK
node .github/scripts/workflow-control-plane-contract.mjs --self-test self-test OK
node .github/scripts/promotion-worker-routing-contract.mjs --self-test OK
node .github/scripts/build-all-branch.mjs --self-test OK
node .github/scripts/classify-claude-credential-failure.mjs --self-test OK
node .github/scripts/electron-pr-release-contract.mjs OK
bash .github/scripts/promotion-worker-contract.sh OK
bash .github/scripts/rebase-ownership-routing-contract.sh OK

Behavioural test: the Select one Lopu review scope step body was extracted
from the YAML with yaml.safe_load (the real step, not a paraphrase) and run
against a stubbed gh returning three eligible open PRs, before and after the
change.

Before (github-actions@cb7e6f2a), unrouted workflow_run:

Lopu will review 3 PR(s) in one serialized session:
  #428 ...  #430 ...  #431 ...
any=true   pr_number=   branch=          <-- repository-wide review dispatched

After, across every event shape the job admits:

workflow_run (UNROUTED, pre-#429)   -> any=false  (no dispatch)
workflow_run (routed, #429)         -> any=true  pr=428
pull_request_target                 -> any=true  pr=428
check_run                           -> any=true  pr=431
issue_comment                       -> any=true  pr=430
push feature branch                 -> any=true  branch=feat/a
push github-actions (all-scan)      -> any=true  all 3 PRs
workflow_dispatch blank (all-scan)  -> any=true  all 3 PRs
workflow_dispatch branch selector   -> any=true  branch=develop
unrouted comment event              -> any=false  (no dispatch)

Every previously working scope is preserved; only the unrouted fallthrough
changes, from "review everything" to "do nothing, and say so".

Source Lopu workflow run

@lopugit
lopugit merged commit 908d27f into github-actions Aug 27, 2026
41 checks passed
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