rational-release

Trunk-based releases for Deno, Node, and Bun projects. Conventional commits in, a release PR out, a tagged GitHub Release on merge. No bots to install, no secrets to manage.

Get started → View on GitHub
Validate PR
conventional-commit title check, report-only or gating
Prepare Release
test, lint, build, force-push release/v…, open release PR
Cut Release
tag, finalise CHANGELOG, build artefacts, GitHub Release

Why this exists

We wanted the shape of release-please — a release PR you can review and squash-merge — but with the prepare commit fully under our control. Re-build a search index, mirror the changelog into a docs page, run an integration suite as a gate, attach custom artefacts to the GitHub Release. All in plain GitHub Actions, no external app.

Three reusable workflows

validate-pr, prepare-release, and cut-release — drop in thin wrappers and you’re done.

Conventional commits

feat:, fix:, !: on commit subjects drive the next semver bump. Pre-1.0 cap is one input flip.

Keep-a-Changelog

[Unreleased] is regenerated from merged PR titles on every push to main. Cut-release promotes it to [X.Y.Z] - date.

Multi-runtime CLI

The Deno CLI underneath uses only node:* standard-library imports, so it runs on Deno, Node, and Bun unchanged.

Custom pre-tasks

pre-tasks runs your test/lint/build/regenerate steps before the release PR is opened. Failures keep the PR closed.

Custom artefacts

artefact-task runs after the tag is cut. Glob with artefact-paths and the files attach to the GitHub Release.

Quick start

Drop three thin wrapper workflows into .github/workflows/. The minimum for a Deno project:

# .github/workflows/validate-pr.yml
on: { pull_request: { types: [opened, edited, synchronize, reopened] } }
jobs:
  title:
    uses: sigmadigitalza/rational-release/.github/workflows/validate-pr.yml@v1
# .github/workflows/prepare-release.yml
on: { push: { branches: [main] } }
permissions: { contents: write, pull-requests: write }
jobs:
  prepare:
    uses: sigmadigitalza/rational-release/.github/workflows/prepare-release.yml@v1
    with:
      pre-tasks: |
        deno task test
# .github/workflows/cut-release.yml
on: { pull_request: { types: [closed], branches: [main] } }
permissions: { contents: write, pull-requests: read }
jobs:
  cut:
    uses: sigmadigitalza/rational-release/.github/workflows/cut-release.yml@v1

That’s the floor. The zero-to-hero tutorial walks through wiring it up to a real repo end-to-end, and the advanced examples cover artefacts, mirror paths, custom pre-tasks, and triggering JSR / npm publishes.

Heads-up. Tags pushed by cut-release use the default GITHUB_TOKEN. GitHub intentionally does not fire downstream push workflows from those tags, so a naïve on: push: tags: [v*] publish workflow will never run. Use workflow_run on Cut Release instead — see the publish trigger pattern.

License

MIT.