Files
releaser/README.md
T
k3nnyandClaude Opus 5.5 e28434a030
ci / vet, staticcheck, test, build (push) Canceled after 0s
docs / Build and deploy docs (push) Canceled after 0s
ci(github): add GitHub Actions CI and release workflows for k3nnyfr/releaser mirror
- .github/workflows/ci.yml: same vet/staticcheck/test/build checks as Gitea CI
- .github/workflows/release.yml: same five binaries and build flags as the
  Gitea release workflow, published with gh release create
- docs: mention the GitHub mirror and both release pages; GitHub Actions
  example downloads from GitHub releases using RUNNER_OS/RUNNER_ARCH
- docs: fix broken latest/download URL, clone URL and Go version requirement

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 22:38:17 +02:00

214 lines
9.4 KiB
Markdown

# releaser
<img src="docs/static/images/releaser-logo-128.png" alt="releaser logo" width="128">
![release](https://img.shields.io/badge/release-v1.10.0-blue.svg)
A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.
**[Documentation](https://releaser.k3nny.fr)** · **[Repository](https://git.k3nny.fr/k3nny/releaser)** · **[GitHub mirror](https://github.com/k3nnyfr/releaser)**
## 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/GitHub tag+release creation.
## How it works
```
release/1.2 branch
└─ last tag: 1.2.3 (or none → start at 1.2.0)
└─ commits since tag → Conventional Commits analysis
└─ next version: 1.2.4
```
1. **Branch parsing** — extracts `major.minor` from branch name (e.g. `release/1.2` → `1.2`)
2. **Tag discovery** — finds the latest tag matching `major.minor.*` on the current branch
3. **Commit analysis** — parses Conventional Commits between last tag and HEAD
4. **Version bump** — increments patch (the minor is owned by the branch)
5. **Release** — updates `pom.xml` / `package.json` / `build.gradle`, commits, tags, creates GitLab or GitHub release
6. **Notify** — best-effort notification to Slack, Microsoft Teams, Google Chat, Telegram, and/or a generic webhook
## Version bump rules
By default, all releasable commits bump the **patch** component (minor is pinned to the branch). You can override this per commit type via `git.bump_rules` in `.releaser.yml`:
| Commit type | Default | Configurable via `bump_rules` |
|------------------|---------|------------------------------------------------|
| `fix:` | patch | `fix: "minor"` to bump minor instead |
| `feat:` | patch | `feat: "minor"` to bump minor instead |
| `feat!:` / `BREAKING CHANGE` | patch | `breaking: "minor"` to bump minor |
| `chore:`, `docs:`, etc. | none | — |
| unparseable msg | none | non-strict mode: silently ignored |
## Installation
Pre-built binaries (`linux-amd64`, `linux-arm64`, `darwin-amd64`, `darwin-arm64`, `windows-amd64.exe`) are published for every tag on both forges:
- **[git.k3nny.fr releases](https://git.k3nny.fr/k3nny/releaser/releases)** — primary repository
- **[GitHub releases](https://github.com/k3nnyfr/releaser/releases)** — read-only mirror of git.k3nny.fr; issues and contributions go to the primary repository
```bash
curl -sSL https://github.com/k3nnyfr/releaser/releases/download/v1.10.0/releaser-v1.10.0-linux-amd64 \
-o /usr/local/bin/releaser
chmod +x /usr/local/bin/releaser
```
See the [installation docs](https://releaser.k3nny.fr/installation/) for Docker and building from source.
## Usage
```bash
# 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, create release
releaser
# Commit and tag locally — skip push and release creation
releaser --no-push
# Push commit and tag but skip creating the 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 (detached HEAD falls back to
# CI_COMMIT_BRANCH / CI_COMMIT_REF_NAME / GITHUB_REF_NAME automatically)
releaser --branch release/1.2
# First release from a shallow clone (no previous tag exists yet)
releaser --allow-shallow
# Write changelog to a custom file
releaser --changelog-file CHANGES.md
# Show configuration sources, commit list, and version decision
releaser --verbose --dry-run
# Preflight: validate branch, working tree, remote URL, push auth,
# version files, and release target — reports all problems at once
releaser --check
# 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+)$"
# Write dotenv artifact to a custom path (or "" to disable)
releaser --release-env-file deploy/version.env
```
## Configuration
`releaser` reads `.releaser.yml` from the repository root. All fields are optional — missing values fall back to the defaults shown below.
```yaml
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
releasable_types: # default: all three
- fix
- feat
- breaking
bump_rules: # which version component each type bumps
breaking: "patch" # "minor" to bump minor on breaking changes
feat: "patch"
fix: "patch"
maven:
pom_path: "pom.xml" # single pom.xml, relative to repo root
# pom_paths: # multi-module: list overrides pom_path
# - "pom.xml"
# - "module-a/pom.xml"
# - "module-b/pom.xml"
node: # opt-in — no default; omit to skip
# package_json: "package.json" # single path
# package_jsons: # monorepo: list overrides package_json
# - "packages/frontend/package.json"
# - "packages/backend/package.json"
gradle: # opt-in — no default; omit to skip
# build_file: "build.gradle" # Groovy or Kotlin DSL; single path
# build_files: # multi-module: list overrides build_file
# - "build.gradle"
# - "module-a/build.gradle"
python: # opt-in — no default; omit to skip
# pyproject_toml: "pyproject.toml" # PEP 621 [project] or [tool.poetry]
# pyproject_tomls: # monorepo: list overrides pyproject_toml
# - "pyproject.toml"
# - "packages/cli/pyproject.toml"
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
github:
token: "" # env GITHUB_TOKEN (never commit this)
repo: "" # "owner/repo" format
notify: # opt-in — every field independent; failures are warnings, not errors
# slack_webhook_url: "" # or env SLACK_WEBHOOK_URL
# teams_webhook_url: "" # or env TEAMS_WEBHOOK_URL
# google_chat_webhook_url: "" # or env GOOGLE_CHAT_WEBHOOK_URL
# telegram_bot_token: "" # or env TELEGRAM_BOT_TOKEN (both required)
# telegram_chat_id: "" # or env TELEGRAM_CHAT_ID
# webhook_url: "" # generic {"version","notes"} JSON POST; or env RELEASER_WEBHOOK_URL
```
### Environment variables
| Variable | Used for |
|--------------------|-----------------------------------|
| `GITLAB_TOKEN` | GitLab API auth + HTTPS push auth |
| `CI_SERVER_URL` | GitLab instance URL |
| `CI_PROJECT_ID` | GitLab project identifier (numeric) |
| `CI_PROJECT_PATH` | GitLab project identifier (fallback) |
| `GITHUB_TOKEN` | GitHub API auth |
| `SLACK_WEBHOOK_URL` | Slack release notification |
| `TEAMS_WEBHOOK_URL` | Microsoft Teams release notification |
| `GOOGLE_CHAT_WEBHOOK_URL` | Google Chat release notification |
| `TELEGRAM_BOT_TOKEN` / `TELEGRAM_CHAT_ID` | Telegram release notification (both required) |
| `RELEASER_WEBHOOK_URL` | Generic webhook release notification |
When both `github.*` and `gitlab.*` are configured, GitHub takes precedence. All `notify.*` targets are independent — any combination may be configured at once, and a failed notification never fails the release.
## CI integration (GitLab CI example)
```yaml
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
GIT_DEPTH: 0 # full history — shallow clones hide previous release tags
script:
- releaser
artifacts:
reports:
dotenv: release.env # exposes NEXT_VERSION to downstream jobs
```
## License
Apache License 2.0 — see [LICENSE](LICENSE).