Skip to content

ci: add the CalVer release workflow and drop the dead release tooling - #2051

Open
chrisbenincasa wants to merge 2 commits into
mainfrom
ci/calver-release-flow
Open

ci: add the CalVer release workflow and drop the dead release tooling#2051
chrisbenincasa wants to merge 2 commits into
mainfrom
ci/calver-release-flow

Conversation

@chrisbenincasa

Copy link
Copy Markdown
Owner

Adds the CalVer release workflow and removes the dead release tooling. Cherry-pick of ed3bd9aa from the ci/calver-release-pilot pilot branch onto main — the pilot was cut from dev, so this rebuilds it against main with no unrelated commits.

Background and rationale: .claude/plans/versioning-repair-plan.md (Phase 1).

Why now

workflow_dispatch workflows are only dispatchable once the file is on the default branch. Nothing about this flow can be exercised — not even a dry run — until it lands on main.

What changes

  • Adds .github/workflows/release.yml. Computes YYYY.M.PATCH from the UTC date plus the count of that month's existing stable tags. Prereleases are excluded from the stable count; dev produces -dev.N hanging off the next stable. Refuses to reuse an existing tag. Notes come from conventional-changelog-cli in the same grouped shape semantic-release produced, and live only in the GitHub release from here on.
  • Removes .github/workflows/release-it.yml, .github/workflows/release-please.yml, .release-it.json.

What deliberately does not change

semantic-release.yml and release.config.mjs stay, so the next release can still be cut on semver as normal. Merging this does not switch anything over — the new workflow is workflow_dispatch only and dry_run defaults to true. Removing semantic-release, and the five now-unreferenced release dev dependencies, is a separate PR after the CalVer flow has cut one real release.

Version format

YYYY.M.PATCH, unpadded — 2026.9.0, never 2026.09.0. Unpadded is still syntactically valid semver, so three things keep working untouched:

  • docker/metadata-action's type=semver,pattern={{version}} in build-and-push-docker.yml
  • the v[0-9]+.[0-9]+.[0-9]+* Docker tag trigger
  • the three-component regex and semver.rcompare sort in scripts/generate-docs-script.ts

The jump from v1.3.13 to v2026.9.0 is monotonically increasing under semver comparison, so Docker latest resolution, tag ordering and the docs version dropdown all stay correct.

node-calver was evaluated and rejected: it elides a zero patch, rendering the first release of a month as 2026.9, which breaks all three of the above.

Token

The release is created with secrets.RELEASE_PLEASE_TOKEN, not GITHUB_TOKEN. Tags pushed with the default token do not trigger other workflows, and build-and-push-docker.yml runs on tag push. semantic-release used the same PAT for the same reason.

Verification

The version computation was verified against a fake tag set covering: prereleases not counting toward the stable patch, a month with no releases starting at .0, dev prereleases hanging off the next stable, and v2026.7.92026.7.10 rather than the .10.9 a lexicographic sort would produce.

Not yet run in CI — that is the first thing to do once this is on main. Dispatch it with dry_run: true and confirm the computed tag and generated notes before any real release.

Follow-ups (not in this PR)

  • Phase 2: derive the OpenAPI spec filename from the release version rather than the stale package.json value (this is how tunarr-v1.2.0-dev.1-openapi.json came to be referenced by the docs dropdown while untracked).
  • Phase 4: document the versioning and rollback contract.
  • Delete semantic-release.yml / release.config.mjs and drop the unreferenced dev dependencies.
  • Decide whether CHANGELOG.md is deleted or frozen with a pointer to GitHub Releases.

🤖 Generated with Claude Code

chrisbenincasa and others added 2 commits September 1, 2026 11:56
semantic-release computes the version from commit types, which is the one thing
CalVer discards. What remained of its value did not survive inspection either:
CHANGELOG.md stops at 1.1.3 (2026-01-20) while tags are at v1.3.13, because the
changelog plugin's output is deliberately never committed back; no branch
matches the configured maintenance pattern; npm publish is off. That left a tag,
a GitHub release and the dev channel, for five plugins and an action.

The replacement computes the version from git tags, which are now the only
source of truth -- package.json has been inert since the move to
semantic-release. Verified against a fake tag set covering: prereleases not
counting toward the stable patch, a month with no releases starting at .0, dev
prereleases hanging off the next stable, and v2026.7.9 -> 2026.7.10 rather than
the .10 -> .9 a lexicographic sort would produce.

Notes are generated with conventional-changelog in the same grouped format
semantic-release produced, and live only in the GitHub release from here on.

Two things worth knowing:

- The release is created with RELEASE_PLEASE_TOKEN rather than GITHUB_TOKEN.
  Tags pushed with the default token do not trigger other workflows, and
  build-and-push-docker.yml runs on tag push. semantic-release used that PAT for
  the same reason.
- node-calver was evaluated and rejected: it hides a zero patch, so the first
  release of a month renders as 2026.8 rather than 2026.8.0, which fails the
  Docker tag trigger, docker/metadata-action's type=semver, and the three
  component regex in scripts/generate-docs-script.ts.

release-it and release-please are removed. semantic-release stays until this
flow has actually cut a release; its dev dependencies are still in package.json.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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