Tags are now bare version numbers by default (e.g. 1.2.3). Set tag_prefix: "v" in .releaser.yml or pass --tag-prefix v to opt in to the v-prefixed convention. Updated all affected tests, the .releaser.yml template comment, and the README configuration reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
releaser
A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.
Problem
Standard tools like semantic-release are designed for trunk-based development. In a GitFlow setup with versioned release branches (release/1.1, release/1.2), they either fail to respect the branch's version range or require brittle configuration.
releaser is built for this exact workflow: it reads the branch name to pin the major.minor, parses Conventional Commits to determine the patch increment, and handles everything from pom.xml update to GitLab tag+release creation.
How it works
release/1.2 branch
└─ last tag: v1.2.3 (or none → start at v1.2.0)
└─ commits since tag → Conventional Commits analysis
└─ next version: v1.2.4
- Branch parsing — extracts
major.minorfrom branch name (e.g.release/1.2→1.2) - Tag discovery — finds the latest tag matching
major.minor.*on the current branch - Commit analysis — parses Conventional Commits between last tag and HEAD
- Version bump — increments patch (the minor is owned by the branch)
- Release — updates
pom.xml, commits, tags, creates GitLab release
Version bump rules
| Commit type | Bump | Notes |
|---|---|---|
fix: |
patch | |
feat: |
patch | minor is pinned to branch |
feat!: / BREAKING CHANGE |
patch | same — branch defines the minor boundary |
chore:, docs:, etc. |
none | |
| unparseable msg | none | non-strict mode: silently ignored |
Usage
# Scaffold a default .releaser.yml in the current repository
releaser --init
# Simulate next version (no side effects)
releaser --dry-run
# Full release: update pom.xml + CHANGELOG.md, commit, tag, push, GitLab release
releaser
# Commit and tag locally — skip push and GitLab release
releaser --no-push
# Push commit and tag but skip creating the GitLab release
releaser --no-release
# Update files but stop before committing (review first)
releaser --no-commit
# … then commit manually and re-run:
releaser --tag-only
# Explicitly target a branch (useful in detached HEAD CI)
releaser --branch release/1.2
# Write changelog to a custom file
releaser --changelog-file CHANGES.md
# Show configuration sources, commit list, and version decision
releaser --verbose --dry-run
# Target a specific pom.xml
releaser --pom path/to/pom.xml
# Override tag prefix from CLI (empty = no prefix)
releaser --tag-prefix ""
# Override branch pattern (e.g. also match hotfix/ branches)
releaser --branch-pattern "^(?:.*/)?(?:release|hotfix)/(\d+)\.(\d+)$"
Configuration
releaser reads .releaser.yml from the repository root. All fields are optional — missing values fall back to the defaults shown below.
git:
tag_prefix: "" # default: no prefix; set to "v" for v-prefixed tags
branch_pattern: "^(?:.*/)?release/(\\d+)\\.(\\d+)$" # two capture groups: major, minor
commit_message: "chore(release): {version} [skip ci]"
author_name: "" # defaults to git config user.name
author_email: "" # defaults to git config user.email
maven:
pom_path: "pom.xml" # relative to repo root
gitlab:
url: "https://gitlab.example.com" # or env CI_SERVER_URL
token: "" # env GITLAB_TOKEN (never commit this)
project: "" # env CI_PROJECT_ID or CI_PROJECT_PATH
Environment variables
GitLab-related fields are automatically read from the CI environment if not set in the config file:
| Variable | Used for |
|---|---|
GITLAB_TOKEN |
API auth + HTTPS push auth |
CI_SERVER_URL |
GitLab instance URL |
CI_PROJECT_ID |
Project identifier (numeric) |
CI_PROJECT_PATH |
Project identifier (fallback) |
CI integration (GitLab CI example)
release:
stage: release
image: registry.example.com/releaser:latest
rules:
- if: $CI_COMMIT_BRANCH =~ /^release\/.+$/
variables:
GITLAB_TOKEN: $RELEASE_TOKEN # project/group CI variable with api + write_repository scope
script:
- releaser