Skip to content

feat(release): add bump-version script + manual-trigger release workflow#9

Merged
JohnnyVicious merged 1 commit intomainfrom
feat/release-workflow
Apr 12, 2026
Merged

feat(release): add bump-version script + manual-trigger release workflow#9
JohnnyVicious merged 1 commit intomainfrom
feat/release-workflow

Conversation

@JohnnyVicious
Copy link
Copy Markdown
Owner

Summary

Adds a manual-trigger release workflow on top of a codex-style bump-version script + check-version CI gate, so cutting a release stops being a four-file hand-edit-then-tag dance.

Components

scripts/bump-version.mjs (~210 LOC)

Adapted from openai/codex-plugin-cc/scripts/bump-version.mjs. The TARGETS table covers all four version-bearing manifests in this repo (5 fields total):

File Field
package.json version
package-lock.json version + packages[""].version
plugins/opencode/.claude-plugin/plugin.json version
.claude-plugin/marketplace.json version (root) + plugins[opencode].version

Two modes:

node scripts/bump-version.mjs 1.0.1     # bump every manifest
node scripts/bump-version.mjs --check   # verify everything matches package.json

Strict semver regex (supports prerelease + build metadata). bumpVersion / checkVersions / readPackageVersion are exported as ES module functions so tests can call them directly without spawning subprocesses; CLI dispatch is gated on import.meta.url === file://argv[1].

package.json

"bump-version": "node scripts/bump-version.mjs",
"check-version": "node scripts/bump-version.mjs --check"

.github/workflows/ci.yml

  • New Check version metadata is in sync step running npm run check-version. Catches PRs that bump one manifest and forget the others.
  • Added scripts/bump-version.mjs to the syntax-check list.

.github/workflows/release.yml (new)

  • workflow_dispatch only — never runs on push. Trigger via Actions UI → "Release" → "Run workflow".
  • Required input: version (semver string).
  • Validates the requested version is strictly greater than the current package.json version (uses sort -V).
  • Runs the bump, re-runs check-version as a sanity gate, runs the full test suite against the bumped tree, then commits with chore(release): vX.Y.Z, tags vX.Y.Z, pushes to main + tag.
  • Creates a GitHub release with gh release create --generate-notes so PRs since the previous tag are auto-summarised.
  • permissions: contents: write (CI is contents: read).

tests/bump-version.test.mjs (new, 9 tests)

Per-test tmp directory with a complete fixture set of all four manifests. Covers:

  • Full bump across all five fields ✅
  • Prerelease semver (2.0.0-rc.1) ✅
  • Malformed version rejection (v1.0.1, 1.0, latest) ✅
  • checkVersions with no drift ✅
  • checkVersions reporting drift on plugin.json
  • checkVersions reporting drift on the marketplace plugin entry ✅
  • Clean-bump roundtrip ✅
  • readPackageVersion happy path ✅
  • readPackageVersion rejecting malformed package.json

Test plan

  • Local: npm run check-version → "All version metadata matches 1.0.0."
  • Local: npm run bump-version -- 1.0.42 → updates all 4 files; check-version passes against 1.0.42
  • Local: reset to 1.0.0; check-version passes again
  • Local: npm test83 tests, 0 failures (was 74 → +9 new)
  • CI green on PR
  • End-to-end smoke after merge: trigger the Release workflow with version: 1.0.1 from the Actions UI, verify it commits, tags, pushes, and creates a GitHub release

How to release after this lands

  1. Go to https://github.com/JohnnyVicious/opencode-plugin-cc/actions
  2. Click "Release" in the left sidebar
  3. Click "Run workflow", enter the new semver (e.g. 1.0.1)
  4. The workflow bumps every manifest, commits/tags/pushes, and creates the GitHub release

Codex-plugin-cc has a bump-version script and check-version CI gate but
no release automation. This PR adds both, plus a manual-trigger release
workflow on top of them so releases stop being a four-file
hand-edit-then-tag dance.

scripts/bump-version.mjs (~210 LOC, adapted from
openai/codex-plugin-cc/scripts/bump-version.mjs):

* TARGETS table covers all four version-bearing manifests in this
  repo: package.json, package-lock.json (root + packages[""]),
  plugins/opencode/.claude-plugin/plugin.json, and
  .claude-plugin/marketplace.json (root + plugins[opencode]). Five
  fields total — codex's marketplace.json keeps the version under
  metadata.* but ours is at root, so the target paths are different.

* Two modes:
    node scripts/bump-version.mjs 1.0.1     # bump every manifest
    node scripts/bump-version.mjs --check   # verify everything matches
                                            # package.json (CI gate)
* Validates against a strict semver regex (supports prerelease and
  build metadata).
* Exposes bumpVersion / checkVersions / readPackageVersion as ES
  module exports so tests can call them without spawning a subprocess.
  CLI dispatch is gated on `import.meta.url === file://argv[1]` so
  importing the module from a test doesn't run main().

package.json:
* New scripts:
    bump-version  -> node scripts/bump-version.mjs
    check-version -> node scripts/bump-version.mjs --check

.github/workflows/ci.yml:
* New "Check version metadata is in sync" step running
  `npm run check-version`. Catches PRs that bump one manifest and
  forget the others.
* Added scripts/bump-version.mjs to the syntax-check list.

.github/workflows/release.yml (new):
* `workflow_dispatch` only — never runs on push, only when the
  maintainer clicks "Run workflow" in the Actions UI.
* Required input: `version` (a semver string).
* Validates the requested version is strictly greater than the
  current package.json version (uses `sort -V`).
* Runs the bump, re-runs check-version as a sanity gate, runs the
  full test suite against the bumped tree, then commits with
  `chore(release): vX.Y.Z`, tags `vX.Y.Z`, pushes to main + tag.
* Creates a GitHub release with `gh release create --generate-notes`
  so PRs since the previous tag are auto-summarised.
* `permissions: contents: write` (CI is contents: read).

tests/bump-version.test.mjs (new, 9 tests):
* Per-test tmp directory with a complete fixture set of all four
  manifests.
* Covers: full bump across all five fields; prerelease semver;
  malformed version rejection; checkVersions with no drift; checkVersions
  reporting drift on plugin.json; reporting drift on marketplace plugin
  entry; clean-bump roundtrip; readPackageVersion happy path; and
  readPackageVersion rejecting malformed package.json.

Test count: 74 -> 83. All passing locally.

End-to-end smoke verified locally with `npm run check-version`,
`npm run bump-version -- 1.0.42`, manual reset to 1.0.0, and
`npm run check-version` again.
@JohnnyVicious JohnnyVicious merged commit f19fbf0 into main Apr 12, 2026
1 check passed
@JohnnyVicious JohnnyVicious deleted the feat/release-workflow branch April 12, 2026 13:59
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