feat(releaser): initial release v0.4.0
Complete GitFlow release automation tool for Conventional Commits workflows: - Core pipeline: branch parsing, tag discovery, commit analysis, version bump - Maven pom.xml read/write, git commit/tag, HTTPS push with token auth - GitLab release creation via API with auto-generated release notes - Configurable via .releaser.yml (tag_prefix, branch_pattern, commit_message, pom_path, gitlab) - CLI flags: --dry-run, --no-push, --no-commit, --tag-only, --branch, --pom, --tag-prefix, --branch-pattern - Dockerfile (multi-stage Alpine), .releaser.gitlab-ci.yml reusable template - Gitea CI (vet + staticcheck + test + build) and release (5-platform cross-compilation) workflows - Taskfile with build/test/cov/lint/fuzz/ci/docker tasks - 96% test coverage with real in-memory git repos and fuzz tests for all parsers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# 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
|
||||
```
|
||||
|
||||
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`, 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
|
||||
|
||||
```bash
|
||||
# Simulate next version (no side effects)
|
||||
releaser --dry-run
|
||||
|
||||
# Full release: bump pom.xml, commit, tag, push, GitLab release
|
||||
releaser
|
||||
|
||||
# Commit and tag locally — skip push and GitLab release
|
||||
releaser --no-push
|
||||
|
||||
# Update pom.xml 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
|
||||
|
||||
# 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.
|
||||
|
||||
```yaml
|
||||
git:
|
||||
tag_prefix: "v" # set to "" for tags without prefix
|
||||
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)
|
||||
|
||||
```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
|
||||
script:
|
||||
- releaser
|
||||
```
|
||||
Reference in New Issue
Block a user