k3nny a14c3f1181
ci / vet, staticcheck, test, build (push) Successful in 3m2s
docs / Build and deploy docs (push) Failing after 13s
release / Build and publish release (push) Successful in 4m29s
feat(pyproject): release v1.7.0 — Python pyproject.toml version bump
Add internal/pyproject package with ReadVersion and WriteVersion for
pyproject.toml files. Reads [project].version (PEP 621) first, then
falls back to [tool.poetry].version. Section boundaries are detected
via TOML's rule that headers always start at the beginning of a line
(\n[ pattern), so inline arrays with [ characters don't interfere.

Config follows the established multi-value pattern:
- python.pyproject_toml: single path (opt-in, no default)
- python.pyproject_tomls: list for monorepos (overrides single)
- --pyproject flag overrides pyproject_toml and clears pyproject_tomls

100% per-package statement coverage maintained across all 14 packages;
FuzzReadVersion and FuzzWriteVersion added per fuzzing guidelines.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-12 00:22:49 +02:00
2026-07-07 00:07:53 +02:00
2026-07-07 00:07:53 +02:00

releaser

releaser logo

release

A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.

Documentation · Repository

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.21.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

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

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, 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 (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+)$"

# 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.

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

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

When both github.* and gitlab.* are configured, GitHub takes precedence.

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
  artifacts:
    reports:
      dotenv: release.env          # exposes NEXT_VERSION to downstream jobs
S
Description
A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.
https://releaser.k3nny.fr/
Readme 545 KiB
v1.7.0 Latest
2026-07-12 00:22:49 +02:00
Languages
Go 99.8%
Dockerfile 0.2%