feat(releaser): release v1.4.0 — GitHub, SSH agent, configurable bumps
ci / vet, staticcheck, test, build (push) Successful in 3m54s
release / Build and publish release (push) Successful in 4m11s

- GitHub release support: internal/ghclient (no SDK, minimal HTTP client);
  GITHUB_TOKEN env var; github.token/github.repo config; GitHub takes
  precedence over GitLab when both are configured; publisher interface
  (releasePublisher) in cmd/main.go makes providers interchangeable
- SSH agent push: gitutil.Push() now tries gitssh.NewSSHAgentAuth for
  git@/ssh:// remotes before falling back to the system git binary
- --release-env-file flag: override dotenv artifact path; pass "" to disable
- git.releasable_types config: filter which commit types trigger a bump
  (defaults to fix, feat, breaking); useful for maintenance branches
- commits.Group(), ExtractSubject(), ReleasableSet() exported helpers:
  notes.go and changelog.go now delegate to these instead of duplicating
- CHANGELOG deduplication guard: changelog.Update() is idempotent — skips
  write if ## [version] section already exists
- Always load config sources: LoadWithSources() called unconditionally;
  removes the dual config path that previously only tracked sources in
  --verbose mode
- .releaser.gitlab-ci.yml: adds artifacts: reports: dotenv: release.env

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 00:15:09 +02:00
parent 62a702fb89
commit 5af107b06d
15 changed files with 428 additions and 175 deletions
+30 -15
View File
@@ -1,6 +1,6 @@
# releaser
![release](https://img.shields.io/badge/release-v1.3.0-blue.svg)
![release](https://img.shields.io/badge/release-v1.4.0-blue.svg)
A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.
@@ -8,22 +8,22 @@ A CI-friendly release automation tool for GitFlow workflows using Conventional C
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.
`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: v1.2.3 (or none → start at v1.2.0)
└─ last tag: 1.2.3 (or none → start at 1.2.0)
└─ commits since tag → Conventional Commits analysis
└─ next version: v1.2.4
└─ 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`, commits, tags, creates GitLab release
5. **Release** — updates `pom.xml`, commits, tags, creates GitLab or GitHub release
## Version bump rules
@@ -44,13 +44,13 @@ releaser --init
# Simulate next version (no side effects)
releaser --dry-run
# Full release: update pom.xml + CHANGELOG.md, commit, tag, push, GitLab release
# Full release: update pom.xml + CHANGELOG.md, commit, tag, push, create release
releaser
# Commit and tag locally — skip push and GitLab release
# Commit and tag locally — skip push and release creation
releaser --no-push
# Push commit and tag but skip creating the GitLab release
# Push commit and tag but skip creating the release
releaser --no-release
# Update files but stop before committing (review first)
@@ -75,6 +75,9 @@ 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
@@ -88,6 +91,10 @@ git:
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
maven:
pom_path: "pom.xml" # relative to repo root
@@ -96,18 +103,23 @@ 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
```
### Environment variables
GitLab-related fields are automatically read from the CI environment if not set in the config file:
| 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 |
| 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) |
When both `github.*` and `gitlab.*` are configured, GitHub takes precedence.
## CI integration (GitLab CI example)
@@ -121,4 +133,7 @@ release:
GITLAB_TOKEN: $RELEASE_TOKEN # project/group CI variable with api + write_repository scope
script:
- releaser
artifacts:
reports:
dotenv: release.env # exposes NEXT_VERSION to downstream jobs
```