release: rework plugin-artifact publishing to vendor into claude-plugins (v0.15.0 fan-out lessons) #44

Closed
opened 2026-07-13 20:50:19 +00:00 by hexajon · 2 comments
hexajon commented 2026-07-13 20:50:19 +00:00 (Migrated from codeberg.org)

The v0.15.0 release (first from Codeberg) surfaced three fan-out problems; the release itself published fine (tag, signed artifacts, release page) but goreleaser and the satellite steps needed manual recovery. The decisions below are the spec.

1. Plugin artifact home: vendor INTO claude-plugins, no separate artifact repo.
scripts/assemble-plugin-artifact.sh currently creates/pushes ${PLUGIN_ARTIFACT_ORG}/${PLUGIN_ARTIFACT_REPO_NAME} — which requires the write:organization token scope on first run (403 on v0.15.0) and a repo that doesn't exist. The marketplace entry already uses the relative source ./plugins/madtea. Rework: assemble stage unchanged, but publish = branch+PR in sixfold_space/claude-plugins updating plugins/madtea/ and bumping the entry's version in the same commit (v0.15.0 was landed exactly this way, claude-plugins PR #1). Drop release.sh's separate marketplace-bump step and its source.url retarget (the relative source makes it meaningless — its regex would also abort today since the entry has no url field).

2. Empty satellite repos break goreleaser's Gitea client.
homebrew-tap and scoop-bucket were commit-less shells; Gitea's contents API returns an empty ARRAY for paths in an empty repo, which goreleaser reads as "expect file, got directory" and fails AFTER publishing the release — aborting the remaining steps. Both are now seeded (v0.15.0 cask/manifest), so this is documentation: the runbook should note that a fresh satellite must carry at least one commit before its first goreleaser release, and ideally release.sh preflight should check the satellites and fail BEFORE tagging, not after publishing.

3. Failure ordering. goreleaser's satellite failure exits release.sh between publish and the plugin-artifact/marketplace steps, leaving a half-fanned-out release with no resume path. Consider: run the artifact/marketplace steps even when goreleaser exits nonzero after a confirmed-published release, or make the script's steps individually re-runnable.

Acceptance:

  • scripts/release.sh vX.Y.Z end-to-end green against the current (seeded) satellites, including the claude-plugins vendored-artifact PR.
  • No write:organization requirement anywhere in the flow.
  • Preflight validates satellite readiness before the tag is pushed.
  • docs/contributing/releasing.md updated (satellite table: homebrew-tap, scoop-bucket, claude-plugins vendored artifact; no madtea-plugin repo).
The v0.15.0 release (first from Codeberg) surfaced three fan-out problems; the release itself published fine (tag, signed artifacts, release page) but `goreleaser` and the satellite steps needed manual recovery. The decisions below are the spec. **1. Plugin artifact home: vendor INTO `claude-plugins`, no separate artifact repo.** `scripts/assemble-plugin-artifact.sh` currently creates/pushes `${PLUGIN_ARTIFACT_ORG}/${PLUGIN_ARTIFACT_REPO_NAME}` — which requires the `write:organization` token scope on first run (403 on v0.15.0) and a repo that doesn't exist. The marketplace entry already uses the relative source `./plugins/madtea`. Rework: assemble stage unchanged, but publish = branch+PR in `sixfold_space/claude-plugins` updating `plugins/madtea/` and bumping the entry's `version` in the same commit (v0.15.0 was landed exactly this way, claude-plugins PR #1). Drop release.sh's separate marketplace-bump step and its `source.url` retarget (the relative source makes it meaningless — its regex would also abort today since the entry has no `url` field). **2. Empty satellite repos break goreleaser's Gitea client.** `homebrew-tap` and `scoop-bucket` were commit-less shells; Gitea's contents API returns an empty ARRAY for paths in an empty repo, which goreleaser reads as "expect file, got directory" and fails AFTER publishing the release — aborting the remaining steps. Both are now seeded (v0.15.0 cask/manifest), so this is documentation: the runbook should note that a fresh satellite must carry at least one commit before its first goreleaser release, and ideally release.sh preflight should check the satellites and fail BEFORE tagging, not after publishing. **3. Failure ordering.** goreleaser's satellite failure exits release.sh between publish and the plugin-artifact/marketplace steps, leaving a half-fanned-out release with no resume path. Consider: run the artifact/marketplace steps even when goreleaser exits nonzero after a confirmed-published release, or make the script's steps individually re-runnable. Acceptance: - `scripts/release.sh vX.Y.Z` end-to-end green against the current (seeded) satellites, including the claude-plugins vendored-artifact PR. - No `write:organization` requirement anywhere in the flow. - Preflight validates satellite readiness before the tag is pushed. - `docs/contributing/releasing.md` updated (satellite table: homebrew-tap, scoop-bucket, claude-plugins vendored artifact; no madtea-plugin repo).
hexajon commented 2026-07-15 23:38:30 +00:00 (Migrated from codeberg.org)

Audit result (2026-07-15): every code-level acceptance criterion of this issue is already implemented on main - commit 818f3e3a carries the vendor-into-claude-plugins publish (branch + PR updating plugins/madtea/ with the version bump in the same commit, no separate artifact repo, no write:organization anywhere), the satellite non-empty preflight before tagging, and the re-runnable post-publish steps that survive a post-publish goreleaser failure; a59588bb added the tag-version stamping of the artifact plugin.json. docs/contributing/releasing.md documents the satellite table, preflight, and resume semantics, and the hooks/tests script harness covers the paths. A fresh audit branch produced zero commits - there is nothing left to build.

The full gate is green on this state. What remains is exactly what status/needs-live-check means here: the claude-plugins PR step and the preflight get their live exercise at the next release (release.sh vX.Y.Z end-to-end). This issue stays open until that release confirms the flow; no further code work is queued.

Audit result (2026-07-15): every code-level acceptance criterion of this issue is already implemented on main - commit 818f3e3a carries the vendor-into-claude-plugins publish (branch + PR updating plugins/madtea/ with the version bump in the same commit, no separate artifact repo, no write:organization anywhere), the satellite non-empty preflight before tagging, and the re-runnable post-publish steps that survive a post-publish goreleaser failure; a59588bb added the tag-version stamping of the artifact plugin.json. docs/contributing/releasing.md documents the satellite table, preflight, and resume semantics, and the hooks/tests script harness covers the paths. A fresh audit branch produced zero commits - there is nothing left to build. The full gate is green on this state. What remains is exactly what status/needs-live-check means here: the claude-plugins PR step and the preflight get their live exercise at the next release (release.sh vX.Y.Z end-to-end). This issue stays open until that release confirms the flow; no further code work is queued.
hexajon commented 2026-07-16 17:30:10 +00:00 (Migrated from codeberg.org)

Live-verified by the v0.15.2 release (2026-07-16), end-to-end green in one run: satellite readiness preflight passed before tagging (homebrew-tap and scoop-bucket both reachable and non-empty), goreleaser published the release with signed checksums and bumped the cask + scoop manifests, and the plugin artifact was vendored into sixfold_space/claude-plugins as a single branch + PR (#7 there) that updated plugins/madtea/ and bumped the marketplace entry to 0.15.2 in the same commit - opened, merged, and synced by release.sh itself. No separate artifact repo, no write:organization scope anywhere, and the post-publish steps ran to completion. Every acceptance criterion is now both code-verified (commit 818f3e3a, audit 2026-07-15) and exercised against the live forge.

Live-verified by the v0.15.2 release (2026-07-16), end-to-end green in one run: satellite readiness preflight passed before tagging (homebrew-tap and scoop-bucket both reachable and non-empty), goreleaser published the release with signed checksums and bumped the cask + scoop manifests, and the plugin artifact was vendored into sixfold_space/claude-plugins as a single branch + PR (#7 there) that updated plugins/madtea/ and bumped the marketplace entry to 0.15.2 in the same commit - opened, merged, and synced by release.sh itself. No separate artifact repo, no write:organization scope anywhere, and the post-publish steps ran to completion. Every acceptance criterion is now both code-verified (commit 818f3e3a, audit 2026-07-15) and exercised against the live forge.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#44
No description provided.