ci: fail on main when SKILL.md's version has no release - #22
Conversation
The ClawHub publish workflow runs only on a published GitHub Release, so a version bump merged to main without one leaves ClawHub serving the previous version - silently. hostinger-mcp and siteagent-elementor-studio each sat two months behind that way, and it surfaced by chance in the ClawHub UI rather than from anything in this repo. The check fails on main when SKILL.md's version has no matching release, so the gap is a red check instead of stale published content. It deliberately enforces the mechanism rather than the outcome: a skill published by hand still reads as drift until a release exists, because the release notes are where 'what changed' is supposed to live. It does not run on pull requests - the PR that bumps the version legitimately has no release yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98e5c49294
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| echo "::error::No 'version:' found in $SKILL_DIR/SKILL.md" | ||
| exit 1 | ||
| fi | ||
| if gh release view "v$VERSION" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then |
There was a problem hiding this comment.
Reject draft releases when checking drift
When a matching tag belongs to a draft release, gh release view still succeeds, so this marks the version as released even though .github/workflows/publish-clawhub.yml runs only for release.types: [published] and ClawHub remains stale. The installed CLI documentation confirms that gh release view exposes the isDraft field, while gh release list requires --exclude-drafts to filter drafts; query --json isDraft/publishedAt here and only pass for a published release.
Useful? React with 👍 / 👎.
Two findings, each reported independently across the five repos carrying this check. A draft release passed it. 'gh release view' succeeds for a draft, but publish-clawhub.yml triggers on 'release: published', so a draft turned the check green while ClawHub kept serving the old version - exactly the failure the check exists to catch. It now reads isDraft and fails with the command to publish. A prerelease still passes: publishing one does fire the release event. Publishing the release did not clear the red run. The triggers were push, schedule and dispatch, and creating a release moves no branch - so main stayed red until an unrelated push or the following Monday, which teaches people to ignore the check. 'release: published' is now a trigger. Verified against real releases: v3.9.4 -> isDraft false (pass), an absent tag -> missing (fail). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Both fixed in the latest commit. Five reviews ran in parallel across the repos carrying this check and converged on the same two problems, which is a fair signal they are real. Draft releases passed. Publishing the release did not clear the red run. The triggers were push, schedule and dispatch, and creating a release moves no branch — so Verified against real releases rather than reasoned about: @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ead6292696
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| env: | ||
| SKILL_DIR: "wordpress-api-pro" | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
Check out main for release-triggered drift checks
When a draft is published after main has advanced beyond the release tag (or any older release is published), the default checkout for a release event uses that tag's commit rather than current main. The job can therefore validate the old commit's SKILL.md and pass on the tag SHA while the failed check on the latest main SHA remains red—the exact recovery path this trigger is intended to provide. Set the checkout ref to the default branch for release-triggered runs so the newly published release is compared against the current version on main.
Useful? React with 👍 / 👎.
Three findings from the second review round. A release-triggered run checked out the TAG, so publishing an older draft - or publishing after main had moved on - read that tag's SKILL.md and reported on a version nobody was asking about. The checkout is pinned to main, which is what the invariant is actually about. '|| echo missing' classified every nonzero exit as 'no release exists', so a transient API, network or auth failure would have told someone to cut a release that already exists. The three cases are now distinct: published, absent (404), and lookup failure (anything else, which fails loudly with the error attached). Verified against the live API rather than reasoned about: v3.9.4 -> draft=false -> pass v9.9.9 -> 404 -> fail, cut the release bad token -> HTTP 401 -> fail as a lookup error, not as missing Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Pushed two more fixes, found in the parallel reviews of this same workflow in the sibling repos — worth applying here even where this PR's own round came back clean, since the file is meant to stay identical across them. The release-triggered run checked out the tag, not
(The @codex review |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
On a release event GITHUB_SHA is the TAGGED commit, so a release published after main has advanced produces a green run attached to the tag's commit - which cannot replace the red check sitting on main's head. The ref: main checkout fixes which FILES are read; it cannot move the run's own SHA. Closing that exactly would mean re-dispatching the workflow against main, and the repository GITHUB_TOKEN is precisely what GitHub suppresses to prevent recursion - the same rule behind the cloudways-mcp finding. A stored PAT in five repos is a worse trade than a check that self-heals, so the schedule moves from weekly to daily and the residual is written down where the next reader will see it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Correct, and the distinction is one I had blurred: I did not close it exactly, and want to be plain about why. Doing so means re-dispatching this workflow against What I did instead: the schedule moves from weekly to daily, so the residual self-heals within a day rather than up to seven, and the whole reasoning is written into the workflow where the next reader meets it rather than living in this thread. The residual, stated precisely: publishing a release after If you would rather have it exact, the PAT route is a deliberate call for a human to make, not something I will add unasked. @codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
I got the underlying fact wrong and the decision followed it: GitHub's recursion suppression for GITHUB_TOKEN-triggered events explicitly EXEMPTS workflow_dispatch and repository_dispatch. A self-dispatch needs no stored credential, so the trade I described - a PAT in five repos versus a check that self-heals in a day - was not the trade on offer. A release or workflow_run event now re-dispatches this workflow against main instead of checking anything itself, and that run reports on main's head commit, which is where the red check sits. The two jobs guard on event name so they cannot call each other forever. The daily schedule stays as belt and braces for a release published from a path that emits no event at all. cloudways-mcp also moves to actions/checkout@v7, matching the four other checkouts in that repo; the remaining repos stay on v4, which is theirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
You are right, and the correction goes deeper than the fix: I had the underlying fact wrong, and my decision followed the wrong fact. GitHub's recursion suppression for A Worth naming the pattern, since it has now happened twice in this PR: I reasoned from a plausible-sounding platform rule instead of checking it, and then wrote the conclusion into a comment where it would have outlived the mistake. The workflow comments now state the exemption explicitly, so the next reader inherits the fact rather than my inference. @codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
A published v$VERSION was not enough. The TAG can point at an older commit - a draft cut before the bump merged - and publish-clawhub.yml checks out the TAGGED commit and reads ITS SKILL.md, so it would publish the older version (or fail as 'already exists') while main stayed unpublished and this check stayed green. That is the false green this whole workflow exists to prevent, reintroduced one layer down. The check now reads SKILL.md at the tag and requires it to match main. Verified against real tags: v3.9.4 carries 3.9.4 (passes), v3.9.0 carries 3.9.0 against a main at 3.9.4 (now fails, previously passed). The jobs also tested github.event_name == 'workflow_run' in repos whose on: block never subscribes to it - dead code that read as a capability. It stays only in cloudways-mcp, which has the trigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Both fixed in the latest commit, and the P1 is the one that matters. A published It now reads The dead event test is gone from the four repos whose @codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
The ClawHub publish workflow runs only on a published GitHub Release. A version bump merged to
mainwithout one leaves ClawHub serving the previous version, silently.That is not hypothetical:
hostinger-mcp(1.1.0 on main, 1.0.1 on ClawHub) andsiteagent-elementor-studio(1.4.0 on main, 1.3.2 on ClawHub) each sat two months behind, and it surfaced because someone happened to look at the ClawHub UI — nothing in either repo said anything was wrong.This check fails on
mainwhenSKILL.md's version has no matching release, so the gap is a red check instead of stale published content.Deliberate limits
meta-ads-mcpturned out to be exactly that case — ClawHub already had 1.1.0 with no release behind it, which is also why "no release" is not a reliable staleness detector on its own. Requiring the release keeps the release notes as the single place "what changed" is recorded.workflow_dispatch, so a repo that goes quiet still reports.Verified
The version parse was tested against the real files before this was written, including the failure path:
The
|| trueon that pipeline is load-bearing: underset -euo pipefaila non-matchinggrepaborts the step before the error message can explain why.🤖 Generated with Claude Code