ci(publish): fail loudly when no runner can accept the job - #28
Merged
Conversation
The publish job runs on a single workflow-restricted host, so the ways it can become unschedulable are real and silent: the host down, or the allow-list naming a ref the caller no longer writes. Neither raises an error. The job sits queued until the 24-hour limit expires, runner reported online and idle, with no red check anywhere — which is how every plugin stopped publishing for days in 2026-08 without a single failed run to point at. A timeout turns that into a red check on the first release after the break, which is the only signal anyone was ever going to look at. Fifteen minutes for a job that uploads a zip in under a minute; thirty for the GitHub-hosted candidate build. The header's ref policy is rewritten to match what the callers now do. A SHA in the caller was not a second lock: the runner group matches its allow-list against that exact ref, so the same decision lived twice — once in a reviewed workflow file, once in an org setting no pull request sees — and drift between the two is precisely the outage above. What guards the credential is unchanged and stated where the next reader will look: protected main here, a dispatch-only caller, one workflow admitted to the publisher host, and the tag proofs that run before the key is in scope. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W9K9WE1ATSqYFStZGtLpNk
This was referenced Aug 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failure this closes
The publish job runs on a single workflow-restricted host. When it becomes unschedulable — host down, or the group's allow-list naming a ref the caller no longer writes — GitHub does not raise an error. The job queues until the 24-hour limit expires, with the runner reported
onlineandbusy: falseand no annotation anywhere.That is exactly what happened in 2026-08: every plugin repo's publish stopped working for days, and there was no red check to point at. The pins were repointed, CI went green, and publishing was still silently stuck because moving the caller's ref moved it out of the runner group's allow-list.
timeout-minutes: 15on the publish job turns that into a red check on the first release after a break.timeout-minutes: 30on the GitHub-hosted candidate build for the same reason. The publish job uploads a zip in well under a minute, so neither bound is near legitimate work.Ref policy, brought in line with the callers
All seven plugin repos now reference this workflow as
@mainrather than a commit SHA, and the org allow-list is...@refs/heads/main— one entry that never has to move again. The header comment claimed the opposite, so it is rewritten rather than left to be "fixed" back into the trap.A SHA in the caller was never a second lock. The runner group matches its allow-list against the exact ref the caller writes, so a SHA meant the same decision lived twice — once in a reviewed workflow file, once in an org setting no pull request sees — and drift between the two is the outage above.
What actually guards the credential is unchanged, and now stated where the next reader will look:
mainin this repo is branch-protected — a revision reaches the pipeline only through a reviewed merge here.repository_dispatch-only, so it is always loaded from its own protected default branch and a tag can never supply the workflow that receives the key.origin/main, version matchingplugin.json, slug matchingplugin.json.id.Verified
lvis-plugin-local-indexerpublished0.5.35through this path after the allow-list was corrected (plugin_id 9, ed25519,signer_key_id prod-v1) — the first successful publish since 2026-08-21.🤖 Generated with Claude Code
https://claude.ai/code/session_01W9K9WE1ATSqYFStZGtLpNk