Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9d0ffb1
ci: guard against version drift between main and the published skill
BenKalsky Jul 21, 2026
7c8358e
ci: dispatch the ClawHub publish explicitly (Codex round-1 P1)
BenKalsky Jul 21, 2026
04595bd
ci: roll back the release when the ClawHub publish fails (Codex round…
BenKalsky Jul 21, 2026
0c749a7
ci: pin the release and its publish to the released commit; roll back…
BenKalsky Jul 21, 2026
5a53fc0
ci: close the remaining release-existence loopholes (Codex round-4 P1…
BenKalsky Jul 21, 2026
2be563e
ci: abort pre-flight on lookup errors; roll back canceled UI publishe…
BenKalsky Jul 21, 2026
ecc50e2
ci: block freestanding real publishes from manual dispatch (Codex rou…
BenKalsky Jul 21, 2026
ab8550c
ci: replace release-existence proof with a publish-completion marker …
BenKalsky Jul 21, 2026
decbc79
ci: never delete a release once the registry has the version; seriali…
BenKalsky Jul 21, 2026
a205e2e
ci: re-run the failed main guard after the release flip (Codex round-…
BenKalsky Jul 21, 2026
dc2b13e
ci: fail closed on every gh run listing (Codex round-10 P1 + P2, plus…
BenKalsky Jul 21, 2026
1f44772
ci: decide rollback from the child's Publish step outcome; re-run mai…
BenKalsky Jul 21, 2026
5414d31
ci: fail the child on exhausted marker attempts, correlate the dispat…
BenKalsky Jul 21, 2026
0bc7bcb
ci: UI rollback only on a verified publish failure (Codex round-13 P1)
BenKalsky Jul 21, 2026
4de4997
ci: verified_failure is the only deletion evidence; interrogate befor…
BenKalsky Jul 21, 2026
dfd633b
ci: ambiguity is sticky across every attempt (Codex round-15 P1)
BenKalsky Jul 21, 2026
186d1c1
ci: no deletion on a no-show dispatch; UI tag must match the version;…
BenKalsky Jul 21, 2026
9f7d3df
ci: lineage-gate UI releases; clean verifiably-untouched failures (Co…
BenKalsky Jul 21, 2026
a387015
ci: published releases delete only on deterministic proof — the two-g…
BenKalsky Jul 21, 2026
70cab35
ci: address the Copilot review — close the draft-sweep two-generals h…
BenKalsky Jul 22, 2026
4840ea0
ci: rerun after rollback finds no release; prior publish failure bloc…
BenKalsky Jul 22, 2026
34ea214
ci: preserve on lost dispatch ack; aggregate every real run before sw…
BenKalsky Jul 22, 2026
4f959c9
ci: default branch everywhere, not hardcoded main (Copilot x3)
BenKalsky Jul 22, 2026
f3006f3
ci: outstanding-dispatch breadcrumb closes the hidden-child sweep rac…
BenKalsky Jul 22, 2026
12488fd
ci: breadcrumb resolves by correlation, never by clock; dry_run expre…
BenKalsky Jul 22, 2026
c32329c
ci: fetch the run listing before the breadcrumb consults it (Codex P1…
BenKalsky Jul 22, 2026
5f1756f
ci: badge version extraction is color-agnostic (Copilot)
BenKalsky Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,92 @@ on:
pull_request:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Trigger the guard again after release publication

After every version-bump merge, the push run evaluates before the release exists and fails as intended, but publishing the release does not emit either of these configured events. The new release workflow only flips the draft in .github/workflows/release.yml:230 and never reruns or dispatches CI, so the failed check on the main commit remains red even after ClawHub and the marker are synchronized; explicitly invoke the guard after the flip or add an event path that the token-driven release flow can trigger.

Useful? React with 👍 / 👎.


jobs:
version-sync:
name: Version sync (declarations always; release+marker on main only)
runs-on: ubuntu-latest
permissions:
contents: read
env:
SKILL: .claude/skills/cloudways-mcp/SKILL.md
steps:
- uses: actions/checkout@v7

- name: All three version declarations agree
id: ver
run: |
skill_v=$(grep -m1 '^version:' "$SKILL" | sed 's/^version:[[:space:]]*//' | tr -d '"' | tr -d "'" | xargs)
pkg_v=$(jq -r .version package.json)
# Color-agnostic: match the semver itself, not the badge color suffix.
readme_v=$(grep -oE 'badge/version-[0-9]+\.[0-9]+\.[0-9]+' README.md | head -1 | sed 's|badge/version-||')
echo "SKILL.md=$skill_v package.json=$pkg_v README badge=$readme_v"
[ -n "$skill_v" ] || { echo "::error::no version in $SKILL"; exit 1; }
if [ "$skill_v" != "$pkg_v" ] || [ "$skill_v" != "$readme_v" ]; then
echo "::error::version mismatch — SKILL.md=$skill_v, package.json=$pkg_v, README badge=$readme_v. Bump all three in the same commit."
exit 1
fi
echo "version=$skill_v" >> "$GITHUB_OUTPUT"

# Only on main: a PR that bumps the version cannot have a release yet
# (the tag has to point at the merged commit), so gating PRs would deadlock.
#
# THE PROOF IS THE MARKER ASSET, not release existence. Only
# publish-clawhub.yml writes `clawhub-published.txt` onto the release, and
# only after its publish command succeeded — so a queued/canceled/failed
# publish behind a UI release, a leftover draft, or a bare tag all stay red
# here no matter what the releases page shows. Release existence alone
# proved nothing: a UI release satisfies it seconds before its publish run
# has even started.
- name: A published release exists, ClawHub confirmed it, payload matches
if: github.event_name == 'push'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.ver.outputs.version }}
run: |
# Capture stderr instead of discarding it: a network/auth failure must not
# be misread as "no release" (and vice versa).
if ! out=$(gh release view "v$VERSION" --repo "$GITHUB_REPOSITORY" --json tagName,isDraft,assets 2>"$RUNNER_TEMP/gherr"); then
out=$(cat "$RUNNER_TEMP/gherr")
echo "$out"
case "$out" in
*"release not found"*|*"Not Found"*|*"HTTP 404"*)
echo "::error::SKILL.md is at $VERSION but there is no v$VERSION release, so ClawHub is still serving the previous version. Cut one with: gh workflow run release.yml"
;;
*)
echo "::error::could not query releases (this is NOT a verdict on whether v$VERSION exists): $out"
;;
esac
exit 1
fi

# A draft is not a publication: no release event fired, nothing reached
# ClawHub — and gh release view DOES find drafts when authenticated.
if [ "$(jq -r '.isDraft' <<<"$out")" = "true" ]; then
echo "::error::v$VERSION exists only as a DRAFT release — nothing was published to ClawHub. Publish it via release.yml (or delete the leftover draft and re-run: gh workflow run release.yml)"
exit 1
fi

# The marker is uploaded by publish-clawhub.yml after a successful real
# publish, and by nothing else. No marker = the publish never completed
# (still queued, canceled, or failed) even though the release is up.
if [ "$(jq -r '[.assets[].name] | index("clawhub-published.txt") != null' <<<"$out")" != "true" ]; then
echo "::error::the v$VERSION release exists but carries no clawhub-published.txt marker — its ClawHub publish never completed. Check the publish-clawhub.yml runs for v$VERSION; once ClawHub really serves $VERSION, re-attach the marker (gh release upload v$VERSION clawhub-published.txt --clobber), or delete the release and re-run release.yml."
exit 1
fi
echo "release v$VERSION is published and ClawHub confirmed it (marker present)"

# Same version ⇒ same payload. A push that edits the skill directory
# without bumping the version would otherwise pass here while ClawHub
# keeps serving the payload frozen at the tag.
PAYLOAD_DIR=$(dirname "$SKILL")
git fetch --no-tags --depth=1 origin "+refs/tags/v$VERSION:refs/tags/v$VERSION"
if git diff --quiet "v$VERSION" HEAD -- "$PAYLOAD_DIR"; then
echo "payload matches the released v$VERSION tag — ClawHub is in sync"
else
echo "::error::$PAYLOAD_DIR changed since v$VERSION was released, but the version was not bumped — ClawHub is serving the old payload under the same version. Bump the version (all three declarations + CHANGELOG) and release."
git diff --stat "v$VERSION" HEAD -- "$PAYLOAD_DIR"
exit 1
fi

skill:
runs-on: ubuntu-latest
env:
Expand Down
Loading