Skip to content

AX-1736: Add tag/release mechanism - #26

Open
YoniMelki wants to merge 13 commits into
mainfrom
ax-1736-release-mechanism
Open

AX-1736: Add tag/release mechanism#26
YoniMelki wants to merge 13 commits into
mainfrom
ax-1736-release-mechanism

Conversation

@YoniMelki

@YoniMelki YoniMelki commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a tag/release mechanism, with plugin/.claude-plugin/plugin.json as the canonical version.

  • release.yml — on push to main, if the commit subject carries [major], [minor] or [patch], reads the version from plugin.json, confirms marketplace.json agrees, tags vX.Y.Z, and publishes a GitHub Release with a repo zip attached.
  • validate-version.yml — PR check that the marketplace.json entry matches plugin.json.
  • No VERSION file. plugin.json already carries the version, so a VERSION file would be a third copy.
  • CONTRIBUTING.md gains a Releasing section.

Notes for reviewers

Why a drift check survives here. This repo genuinely has two manifests: the plugin's own plugin.json and the marketplace.json listing. The check compares manifest to manifest, with plugin.json canonical — 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 main since mid-July. Both conflicts were in files it only wanted a version bump in, and main had moved past it: 1.0.71.0.10, plus removal of plugin.json's hooks key as part of the move to skills. Resolved by taking main's side wholesale, so the net diff is now only the two workflows and CONTRIBUTING.md.

Test plan

  • validate-version passes on this PR (both manifests at 1.0.10)
  • A PR that desyncs the two manifests fails validate-version with a clear error
  • A follow-up PR bumping both manifests, merged with [patch] in the subject, produces the matching tag and GitHub Release

Closes AX-1736 / part of AX-1733

YoniMelki and others added 8 commits June 23, 2026 22:00
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>
@YoniMelki
YoniMelki requested a review from yanivt-jfrog July 23, 2026 07:29
…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.
@YoniMelki
YoniMelki requested a review from a team as a code owner August 2, 2026 14:34
YoniMelki and others added 4 commits August 3, 2026 09:58
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant