Kai Ole Hartwig
Go · Apache-2.0 · GitLab, GitHub, Forgejo

yasrt — the tag confirms, it does not announce.

Yet another semantic release tool: a static Go binary that reads your Conventional Commits, decides whether and what to release, and publishes the release after the artefact is built. A replacement for the semantic-release npm chain for anyone who wants the same decisions without a package manager in the release path.

  • Binary:go install github.com/ohartwig/yasrt/cmd/yasrt@latest or the signed releases
  • Forges: GitLab, GitHub, Forgejo – detected from the job environment
  • Access: the job token only; a signing key is optional
  • Licence: Apache-2.0 · two dependencies (YAML parser, glob matcher) plus git

The tag before the build

Until now

  • The tag is set before anything is built; if the build goes red, a tag stands without an artefact
  • Hundreds of unpinned npm packages are resolved at run time in the release job
  • Judged against the push range: a real fix that arrives bundled with a CI change never ships
  • One .releaserc per repository, each a little different

With yasrt

  • yasrt next decides, the build runs, yasrt release tags: a failed build leaves no tag behind
  • One static binary, two dependencies, nothing resolved at run time
  • Judged against the last release: the fix ships, whatever it arrived with
  • One file per repository, or none, because organisation defaults sit underneath

Does this fit my setup?

Use it when …

  • you run semantic-release and have had a tag without an artefact
  • your release job resolves hundreds of unpinned npm packages at run time and you no longer want that
  • a real fix was pushed together with a CI change and never shipped
  • you want one file per repository, and none for most

Do not use it when …

  • you need Windows runners: Linux and macOS are supported
  • you release to Bitbucket or Azure DevOps
  • your release process depends on semantic-release plugins that exist only as npm; yasrt has hooks that call any executable, but no plugin loading

Why

semantic-release gets the decisions right and the mechanics wrong for CI: it tags before anything is built. It resolves hundreds of unpinned packages at run time. And it judges “did anything shippable change?” against the push range instead of the last release, so a real fix that arrives bundled with a CI change never ships.

yasrt keeps the decisions (the same commit conventions, the same version arithmetic, the same changelog shape) and repairs the mechanics. The tag confirms an artefact that already exists instead of announcing one that may come to exist. In my estate exactly that left ~30 repositories with tags and no image, in a single evening; since then nothing here tags before the build.

Three commands

yasrt next --output .release.env   # decide; writes nothing to the repository
yasrt check                        # check the configuration, probe the environment
yasrt release                      # publish; idempotent, safe to repeat

 

next leaves its decision in a dotenv file: RELEASE_STATUS is release, no-bump, not-deliverable or already-released, next to RELEASE_VERSION, RELEASE_TAG, RELEASE_PREVIOUS, RELEASE_BUMP, RELEASE_REASON and RELEASE_COMMIT. Your build reads it; release reads it back and refuses to tag anything but the analysed commit. The keys and the exit codes are a public interface.

ExitMeaning
0analysis or release completed
1configuration or git error
2invalid arguments
3no-bump, with --fail-on-skip
4not-deliverable, with --fail-on-skip
5the repository moved: HEAD changed, or the tag exists on another commit

The documentation

CI pipelines

Installation, the three-stage GitLab pipeline, gating in the script, triggers after the release, and the same for GitHub Actions and Forgejo Actions.

Read →
CI pipelines

Configuration and hooks

One line per repository, organisation defaults underneath, and hooks that call any executable at five points of the release.

Read →
Configuration and hooks

Forges and signing

What differs between GitLab, GitHub and Forgejo, how yasrt tells them apart, and how the release commit and tag are signed with OpenPGP or SSH.

Read →
Forges and signing

Comparison with semantic-release

docs/semantic-release-comparison.md

What is the same, what differs, and why: option by option.

Read the comparison →
Comparison with semantic-release

Container image

Build your own from it if you would rather not pull ours

registry.ole-hartwig.eu/devops/images/yasrt:1: 30 MB of Wolfi with git, gpg and ssh-keygen. Recipe and pipeline are public.

yasrt-image on GitHub →
Container image

GitHub

Linux and macOS, amd64 and arm64

Source, releases with binaries, SHA256SUMS and cosign signature, issues. Apache-2.0.

View on GitHub →
GitHub

A release pipeline that tags before the build?

I help with the move to yasrt, with a component and a fallback net: first beside the old chain, then instead of it.

Get in touch →