Skip to content

Releasing Onion

Onion uses git tags to drive releases. The version is derived automatically from the latest tag by sbt-dynver, so there is no manual version := ... line to update in build.sbt.

Release checklist

  1. Make sure develop is green — in both locales.

    sbt shutdown && sbt -Duser.language=en testFull
    sbt shutdown && sbt -Duser.language=ja testFull
    
    Both parts matter. Diagnostics are bilingual, and release CI runs in English while local development is usually ja_JP, so a test asserting on message text can pass in one locale and fail in the other. Under sbt 2, test delegates to testQuick and reports No tests to run on an unchanged tree, and -D is only picked up by a freshly started server — so without shutdown and testFull this step can look green having run nothing.

  2. Decide the next version. Onion follows Semantic Versioning with milestone and RC pre-releases when needed:

  3. Patch release: v0.2.1
  4. Minor release: v0.3.0
  5. Milestone: v0.3.0-M1
  6. Release candidate: v0.3.0-RC1

  7. Update CHANGELOG.md. Add a new section for the release with the date and a summary of user-facing changes, bug fixes, and internal improvements.

  8. Start the release.

Preferred — trigger the release workflow's workflow_dispatch event and let it create the tag itself. Pushing a v* tag from a client is rejected by the repository's tag protection (HTTP 403), which is what left releases stuck for months (issue #334), so the workflow creates the tag itself with the Actions token instead of relying on a client-side push:

gh workflow run release.yml -f version=v0.2.0 --ref develop
gh run watch "$(gh run list --workflow=release.yml --limit 1 --json databaseId --jq '.[0].databaseId')"

Without the gh CLI (e.g. a session with only the GitHub API/MCP tools), the same workflow_dispatch event is POST /repos/{owner}/{repo}/actions/workflows/release.yml/dispatches with {"ref": "develop", "inputs": {"version": "v0.2.0"}} — a GitHub MCP server typically exposes this as an "run workflow" action taking workflow_id: "release.yml", ref: "develop", inputs: {version: "v0.2.0"}.

The tag-push path still works for anyone whose credentials are allowed to create v* refs:

git checkout develop
git pull
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0

Do not commit a ## [X.Y.Z] CHANGELOG heading before the tag exists: if the release then fails, the heading has to be reverted, which is exactly the release-and-revert loop #334 describes. Confirm the release first, then finalize the heading.

  1. Let CI do the rest. The release workflow will:
  2. run the test suite,
  3. build the fat jar (sbt assembly) and the distribution zip (sbt dist),
  4. verify the tag matches the sbt-derived version,
  5. smoke-test the fat jar,
  6. generate SHA-256 checksums,
  7. create a GitHub Release with the artifacts and auto-generated notes.

  8. Verify the release.

  9. Check the GitHub Release page.
  10. Download onion-<version>.jar and confirm:
    java -cp onion-<version>.jar onion.tools.ScriptRunner run/Hello.on
    

Local artifact inspection

To build the same artifacts locally without creating a release:

sbt "assembly; dist"

Outputs (sbt 2's default layout nests build products under target/out/<platform>/<scalaVersion>/<project>/): - target/out/jvm/scala-3.3.7/onion/onion-<version>.jar (fat jar) - target/out/jvm/scala-3.3.7/onion/onion-dist-<version>.zip (distribution archive)

Hotfix releases

For a hotfix against an already-released version, branch from the release tag, apply the fix, and push a new patch tag (e.g. v0.2.1).