Skip to main content

Releases with catladder

A release is what produces a vX.Y.Z git tag (with a changelog), which in turn triggers the taggedRelease pipeline that deploys to stage and prod (see the catladder-pipelines skill). Enable it in catladder.ts:

releases: {
when: "auto", // "manual" (default) | "auto"
method: "semantic-release", // "semantic-release" (default) | "changesets"
}

Change catladder.ts and regenerate (yarn catenv) — the release jobs are generated, never hand-edited.

when — who triggers the release​

  • manual (default) — the create release job on the main branch can be clicked at any time, even while the pipeline is still running: it queues the release, which then runs automatically as soon as every other job of the pipeline succeeded (and is skipped if the pipeline fails). Clicking after a green pipeline releases right away.
    • On GitLab the button is a quick no-op job; the actual release runs in the automatic 🚀 release once pipeline succeeds job (skipped when the button was never clicked — never run it by hand).
    • On GitHub, releasing is the 🚀 catladder create release workflow (Actions sidebar → Run workflow): it releases immediately when the main workflow for HEAD is green, queues the release when it is still running (the đŸ› ī¸ catladder release on green workflow then picks it up on completion), and fails when the run concluded red.
  • auto — the release job runs automatically on every main-branch pipeline (it still no-ops when there is nothing to release).

There is always also a force release escape hatch that releases immediately, ignoring the state of the pipeline: on GitLab the manual âš ī¸ force create release job, on GitHub the force checkbox of the 🚀 catladder create release workflow. With method: "changesets" forcing has an extra meaning: it releases even when no changesets are pending (patch bump with a generic changelog entry) — the recovery path when a change was merged without a changeset and must ship now.

On GitHub, other manual tasks are split into per-kind dispatch workflows the same way (â–ļī¸ catladder deploy, âšī¸ catladder stop, â†Šī¸ catladder rollback), each with a dropdown of its tasks.

method — how the version is decided​

Whichever method runs, the release ends the same way: a vX.Y.Z tag, a CHANGELOG.md entry, a chore(release): <version> commit, and an entry on the releases page of the git host (gitlab /-/releases, github /releases) carrying the release notes.

semantic-release (default)​

The version is derived automatically from conventional commit messages since the last release (fix: → patch, feat: → minor, BREAKING CHANGE → major). Nothing to declare by hand — just write conventional commits.

changesets​

Developers declare changes intentionally as .changeset/*.md files (the official changesets format: a bump type + a human-written summary). The release job consumes all pending changesets, takes the highest bump, computes the next version from the last v* git tag, writes the changelog, commits chore(release): <version>, pushes the tag and creates the release entry on the git host (gitlab /-/releases, github /releases) with the changelog as its description. An empty .changeset/ folder means there is nothing to release.

Add a changeset by creating .changeset/<name>.md:

---
"my-app": minor
---

Add the new export endpoint.

When you (an agent) make a user-facing change in a changesets project, add a changeset file in the same MR — bump level major (breaking) / minor (feature) / patch (fix), and a one-to-two sentence summary written for the changelog reader. Docs/chore-only changes need none. The package name in the frontmatter is ignored (versions come from git tags); only the bump counts.

The changeset check (MR/PR pipelines)​

Changesets projects get a đŸĻ‹ changeset check job in every merge-request pipeline. It reports what merging would do — the changesets this MR adds, everything pending, and the version the next release would get (with a changelog preview) — and warns without blocking (allow_failure) when the MR adds no changeset:

  • GitLab: report in the job log and as an exposed artifact (changeset-report.md) in the MR widget. If the project makes GL_TOKEN available to MR pipelines it also maintains a sticky MR comment (opt-in — an api-scope token in MR pipelines is a security trade-off).
  • GitHub: maintains a sticky PR comment via the workflow token; the job stays green and reports a warning annotation (github has no yellow job state, and a red job would read like a real failure).

A yellow changeset-check job on an MR is a prompt to ask: is this change user-facing? If yes, add a changeset; if not, ignore it.

The security-audit gate​

Both methods gate on a dependency security audit before releasing. The release entrypoint runs the audit first; only if it passes does it create the version, changelog and tag. On GitLab, if the audit document is missing or invalid the job opens a merge request with a security-audit template and fails — resolve that MR, then re-run the release. See the security commands in the catladder-cli reference.

Debugging a failed release​

  • Fails immediately on the audit → handle the security-audit gate above.
  • changesets released nothing → no .changeset/*.md files were pending. To ship anyway, force the release (patch bump) — gitlab: âš ī¸ force create release job, github: force checkbox — or merge an MR adding a changeset describing the accumulated work.
  • Wrong version bump → check commit types (semantic-release) or the bump levels in the changeset files (changesets).
  • Tag pushed but nothing on the releases page → with changesets the entry is created via the host api after the push and never fails the job (the release itself is done); look for the could not create the release entry warning at the end of the release job log. On gitlab it needs GL_TOKEN (catladder project renew-token). Releases tagged before catladder created entries have none — that is not fixed retroactively, create them by hand from the tag.
  • Inspect the job with yarn catladder project ci job-log (see the catladder-cli skill).
  • catladder-config — catladder.ts structure and regeneration
  • catladder-pipelines — the taggedRelease trigger and stage/prod deploys
  • catladder-cli — project ci and security commands
  • catladder-migrate-release-method — switching an existing project between semantic-release and changesets (incl. backfilling changesets for everything merged since the last release tag)