AX-1736: Add tag/release mechanism - #26
Open
YoniMelki wants to merge 13 commits into
Open
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tep comments Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Releases landed on main after this branch was cut, bumping plugin.json and marketplace.json to 1.0.7. The branch was conflicting (DIRTY) because both main and our branch modified the same JSON files to different versions. Bring VERSION and both manifests in line with current main so the merge is clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…SION Resolves the marketplace.json and plugin.json conflicts by taking main's side. This branch only wanted a version bump to 1.0.7 in those files; main has since reached 1.0.10 and also dropped the plugin.json "hooks" key as part of the move to skills. Drops the VERSION file: plugin.json already carries the version, so VERSION was a third copy. plugin.json is now canonical and validate-version.yml cross-checks marketplace.json against it instead of both against VERSION. Both now select the marketplace entry by name rather than by array index, so reordering or adding a plugin can't silently compare the wrong entry. release.yml reads plugin.json, re-checks the two manifests agree before tagging, refuses to re-tag a version that already shipped, and reads the commit message from env rather than interpolating it into the script.
These repos squash-merge, and GitHub pre-fills the squash message body from the branch's commit messages (or the PR description). Both of those quote [major]/[minor]/[patch] while only documenting the flow, so matching the whole message meant merging this very PR would have cut a release nobody asked for. Matching the subject line alone keeps the trigger deliberate: a release happens when someone writes the marker in the subject they are merging, not when a marker happens to appear in generated body text.
… release Three fixes from review, all in release.yml. An orphan tag was possible: the tag was pushed in its own step before `gh release create`, so a failure in between left a tag with no release behind it. The re-run then hit the "already exists" check with nothing actually wrong but the tag, and it needed deleting by hand. The tag is now created by `gh release create --target "$GITHUB_SHA"` in the same API call as the release, so there is no window between the two. Nothing pushes over git anymore, so the write token is gone from the checkout step. Releases were not gated on validation. The validate workflow triggers on the same push, but as a separate workflow with no relationship to this one, so it could still be red while a release went out. The same check now runs here, before the release is created. `zip -r release.zip .` packed the working tree, so anything an earlier step left on the runner would ship inside the artifact. Replaced with `git archive`, which exports tracked files at HEAD, still excluding .github.
…TRIBUTING Review feedback: the per-step comments in release.yml had grown into several paragraphs of rationale, which is documentation rather than a code comment. Each step now carries at most two lines - what it does, or the one constraint a reader could otherwise undo by "simplifying" it: subject-line matching, env rather than interpolation, git archive rather than the working tree, --target creating the tag. A pointer at the top of the file sends readers to CONTRIBUTING.md for the full flow. CONTRIBUTING.md gains the parts the comments had that it did not already say: what the workflow does in order, what ends up in the release zip, why validation runs inside the release job instead of relying on the separate validate workflow, and why the tag is created by the release rather than pushed before it. No behaviour change - the release.yml diff is comments only.
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.
Summary
Adds a tag/release mechanism, with
plugin/.claude-plugin/plugin.jsonas the canonical version.release.yml— on push tomain, if the commit subject carries[major],[minor]or[patch], reads the version fromplugin.json, confirmsmarketplace.jsonagrees, tagsvX.Y.Z, and publishes a GitHub Release with a repo zip attached.validate-version.yml— PR check that themarketplace.jsonentry matchesplugin.json.VERSIONfile.plugin.jsonalready carries the version, so aVERSIONfile would be a third copy.CONTRIBUTING.mdgains a Releasing section.Notes for reviewers
Why a drift check survives here. This repo genuinely has two manifests: the plugin's own
plugin.jsonand themarketplace.jsonlisting. The check compares manifest to manifest, withplugin.jsoncanonical — rather than comparing both against a third file that exists only to be compared against.Both places select the marketplace entry by
name == "jfrog", not.plugins[0]. Indexing by position would silently compare the wrong entry the moment a second plugin is added or the list is reordered.The version comes from the manifest, not from the marker. The marker only decides whether to release; it does not compute a bump. The version change stays reviewable in the PR that makes it, and no bot ever pushes to
main.The marker is matched on the subject line only. This repo squash-merges, and GitHub pre-fills the squash body from the branch's commit messages — which quote
[minor]while merely documenting the flow. Matching the whole message would have meant merging this very PR cut a release nobody asked for.Merging a marker without bumping the manifests fails the release rather than re-tagging a version that already shipped.
The commit message is read through
env, not interpolated into the script, so a crafted commit subject cannot inject shell.Conflict resolution
This branch had conflicted with
mainsince mid-July. Both conflicts were in files it only wanted a version bump in, andmainhad moved past it:1.0.7→1.0.10, plus removal ofplugin.json'shookskey as part of the move to skills. Resolved by takingmain's side wholesale, so the net diff is now only the two workflows andCONTRIBUTING.md.Test plan
validate-versionpasses on this PR (both manifests at1.0.10)validate-versionwith a clear error[patch]in the subject, produces the matching tag and GitHub ReleaseCloses AX-1736 / part of AX-1733