Releasing¶
This page describes how releases work and how to cut one manually if needed.
How it works¶
Releases are automated via Release Please. The process:
- You merge PRs with conventional commits (
feat:,fix:,docs:, etc.) - Release Please accumulates changes and opens a "release PR" that bumps the version in
gradle.propertiesand updatesCHANGELOG.md - You review and merge the release PR
- Release Please creates a git tag (
v0.2.0) - The tag triggers the release workflow, which builds and publishes to all channels
Your only manual step: merge the release PR.
What gets published¶
The release workflow (release.yml) runs 4 parallel jobs after the build:
| Channel | Artifact | Secrets needed |
|---|---|---|
| GitHub Release | Shadow JAR (algorilla-<version>.jar) |
(uses GITHUB_TOKEN) |
| npm | algorilla package on npmjs.org |
NPM_TOKEN |
| Gradle Plugin Portal | io.github.tvinke.algorilla plugin |
GRADLE_PUBLISH_KEY, GRADLE_PUBLISH_SECRET |
| Docker | ghcr.io/tvinke/algorilla image |
(uses GITHUB_TOKEN) |
All secrets are repository secrets in GitHub (Settings > Secrets > Actions).
Version management¶
The project version lives in one place: gradle.properties.
All modules read this at build time. The CLI --version flag reads it from a generated properties file in the JAR. There is no hardcoded version string anywhere in source code.
SNAPSHOT lifecycle: during development, the version is always X.Y.0-SNAPSHOT. The release workflow strips -SNAPSHOT when building from a tag. After publishing, a post-release job automatically bumps to the next SNAPSHOT (e.g. 0.3.0 → 0.4.0-SNAPSHOT).
Release Please manages the CHANGELOG and git tags, but does not touch gradle.properties — the release workflow handles that.
Manual release¶
If you need to release without Release Please (e.g., first release, hotfix):
1. Update the version¶
Set gradle.properties to the clean release version (strip -SNAPSHOT):
Also update .release-please-manifest.json to match:
2. Update the changelog¶
Edit CHANGELOG.md and replace the (unreleased) marker with the release date.
3. Commit, tag, push¶
git add gradle.properties .release-please-manifest.json CHANGELOG.md
git commit -m "chore: release 0.3.0"
git tag v0.3.0
git push origin main --tags
The tag triggers the release workflow.
4. Verify all channels¶
Check the Actions tab — all 4 publish jobs should succeed. See Troubleshooting below for common failures.
Version scheme¶
Algorilla follows Semantic Versioning:
- Patch (0.1.x): Bug fixes, documentation, minor rule tuning
- Minor (0.x.0): New rules, new CLI options, new language support
- Major (x.0.0): Breaking changes to config format, rule IDs, or output format
During the 0.x phase, minor versions may include breaking changes as the API stabilizes.
Troubleshooting¶
Release Please creates tags that don't trigger workflows¶
This is the most common gotcha. Tags created by Release Please (or any GitHub Action) using the default GITHUB_TOKEN won't trigger other workflows — it's a GitHub security restriction to prevent infinite loops.
After merging the release PR, check the Actions tab. If you see the Release Please run completed but no Release workflow started, do this:
git fetch --tags origin
git tag -d v0.3.0 # delete local tag
git push origin :refs/tags/v0.3.0 # delete remote tag
git tag v0.3.0 origin/main # recreate on same commit
git push origin v0.3.0 # push — this triggers the workflow
This works because tags pushed by a real user (not a GitHub Action bot) do trigger workflows.
Permanent fix: use a PAT or GitHub App token for Release Please instead of GITHUB_TOKEN. Haven't set this up yet because releases are infrequent enough that the manual re-tag takes 10 seconds.
Gradle Plugin Portal publishes with SNAPSHOT version¶
Fixed in v0.3.0+. The publish-gradle-plugin job checks out the repo fresh, so gradle.properties still has the -SNAPSHOT version. The build job strips it but that's a separate checkout. Fix: the plugin job now runs sed to set the release version before publishing, same as the build job does.
If you see -SNAPSHOT plugin versions not supported in the logs, the sed step is missing from the gradle plugin job.
Gradle Plugin Portal rejects com.github group ID¶
The Portal requires io.github as the prefix for GitHub-based plugins. The plugin ID is io.github.tvinke.algorilla — this is permanent once published and cannot be changed later.
npm publish fails with "cannot publish over previously published version"¶
npm doesn't allow re-publishing the same version. If the version was already published by a previous (partially failed) run, this error is harmless. To re-publish, you'd need to bump the version.
npm publish fails with 403/auth error¶
Check that the NPM_TOKEN secret is set and the token has publish permissions for the algorilla package. Generate a new token at npmjs.org > Access Tokens > Granular Access Token.
Docker push permission denied¶
The workflow uses GITHUB_TOKEN with packages: write permission. Ensure the workflow has this permission in the permissions block.
Re-triggering a failed release¶
If some publish jobs fail but others succeed:
- Fix the issue (code, secrets, or config)
- Commit and push the fix
- Move the tag to the new commit:
- This triggers a fresh workflow run. Jobs that already published will fail with "already exists" errors — those are harmless.
npm and Docker publishes are idempotent — re-runs skip gracefully if the version already exists. Gradle Plugin Portal does not support re-publishing the same version.
Caution: gh run rerun --failed re-runs with the original commit, not the latest. Always move the tag instead.
After a manual release: bump to SNAPSHOT¶
After tagging, bump gradle.properties to the next SNAPSHOT so local builds are clearly development versions:
# After releasing 0.3.0:
sed -i '' 's/^version=.*/version=0.4.0-SNAPSHOT/' gradle.properties
git add gradle.properties
git commit -m "chore: bump to 0.4.0-SNAPSHOT"
git push origin main
When using the automated release workflow, this happens automatically via the bump-snapshot job.