RodarRelease
Version management and release utilities for Rodar projects. Automates semantic version bumping, changelog updates, git commits/tags.
Installation
Add rodar_release to your list of dependencies in mix.exs:
def deps do
[
{:rodar_release, "~> 0.1.0"}
]
endWith Igniter
If your project uses Igniter, you can install with automatic setup:
mix igniter.install rodar_release
This creates a CHANGELOG.md with the standard Keep a Changelog structure if one doesn't exist. To also configure a custom AI CLI:
mix igniter.install rodar_release --ai-cmd geminiWithout Igniter
If your project does not use Igniter, follow these steps after adding the dependency:
Create
CHANGELOG.mdin your project root with the Keep a Changelog structure:# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org). ## [Unreleased] ## [0.1.0] - 2026-01-01 ### Added - Initial releaseReplace
0.1.0with your current version and2026-01-01with today's date.(Optional) Configure AI CLI for changelog generation in
config/config.exs:config :rodar_release, :ai_cmd, {"claude", ["-p"]} # default (Claude Code) config :rodar_release, :ai_cmd, {"gemini", ["-p"]} # Gemini CLI config :rodar_release, :ai_cmd, {"codex", ["e"]} # OpenAI Codex config :rodar_release, :ai_cmd, {"gh", ["-p"]} # GitHub CopilotIf omitted, Claude Code is used by default.
(Recommended) Install the changelog skill for AI-assisted dev tools:
npx skills add rodar-project/rodar_skills --skill changelog
Semantic Versioning
This tool follows Semantic Versioning (MAJOR.MINOR.PATCH):
- Patch (
mix rodar_release.patch) — backward-compatible bug fixes. Use when you fix a bug without changing the public API. - Minor (
mix rodar_release.minor) — new functionality that is backward-compatible. Use when you add a feature, deprecate something, or make non-breaking changes. - Major (
mix rodar_release.major) — breaking changes. Use when you remove or change existing behavior in a way that requires consumers to update their code.
Pre-release versions
Pre-release identifiers (e.g. 1.2.0-rc.1) are supported and automatically inferred from the current git branch:
| Branch | Suffix | Example |
|---|---|---|
main / master | (none) | 1.2.0 |
develop / dev | -dev.N | 1.2.0-dev.1 |
release/* / rc/* | -rc.N | 1.2.0-rc.1 |
beta/* | -beta.N | 1.2.0-beta.1 |
alpha/* | -alpha.N | 1.2.0-alpha.1 |
The full lifecycle looks like:
main: 1.1.0 (stable)
↓ branch develop
develop: 1.2.0-dev.1 → 1.2.0-dev.2 → 1.2.0-dev.3
↓ branch release/1.2.0
release: 1.2.0-rc.1 → 1.2.0-rc.2
↓ merge to main
main: 1.2.0 (stable)Rules:
--preis rejected onmain/master— release candidates should have their own branch- Releases from unmapped branches (feature branches, etc.) are blocked
--preon a mapped branch overrides the auto-inferred suffix-
Labels must be alphanumeric and start with a letter (e.g.,
rc,beta,dev,alpha)
Custom branch mappings can be configured in config.exs:
config :rodar_release, :branch_pre, %{
"staging" => "rc",
~r/^preview\// => "beta"
}Build metadata (e.g.
1.0.0+build.42) is part of the semver spec but is not currently supported by this tool.
Usage
mix rodar_release # list available commands
mix help rodar_release.patch # help for a specific commandCommands
Release
mix rodar_release.patch # bug fix: 1.0.8 -> 1.0.9
mix rodar_release.minor # new feature: 1.0.8 -> 1.1.0
mix rodar_release.major # breaking change: 1.0.8 -> 2.0.0
mix rodar_release.minor --pre rc # pre-release: 1.1.0 -> 1.2.0-rc.1
mix rodar_release.minor --dry-run # preview changes-
Resolves the pre-release suffix from the current branch (or
--preflag) - Validates the git working directory is clean
-
If
[Unreleased]inCHANGELOG.mdis empty, offers to generate an entry using Claude Code (requiresclaudeCLI) -
Bumps the version in
mix.exs -
Updates
CHANGELOG.mdwith the release date and comparison links -
Commits changes with message
release: vX.Y.Z -
Creates an annotated git tag
vX.Y.Z
AI-generated changelog
When releasing with an empty [Unreleased] section, the tool gathers the git log and diff since the last tag and asks an AI CLI to suggest a changelog entry using Keep a Changelog headings (### Added, ### Changed, ### Fixed, ### Removed). You are prompted to confirm before anything is written.
By default it uses Claude Code. To use a different AI CLI, configure the command and args in your config.exs:
config :rodar_release, :ai_cmd, {"claude", ["-p"]} # default
config :rodar_release, :ai_cmd, {"gemini", ["-p"]} # Gemini CLI
config :rodar_release, :ai_cmd, {"codex", ["e"]} # OpenAI CodexThe prompt is appended as the last argument.
Merge (post-merge promotion)
mix rodar_release.merge # 1.5.1-dev.3 -> 1.5.1
mix rodar_release.merge minor # 1.5.1-dev.3 -> 1.6.0
mix rodar_release.merge major # 1.5.1-dev.3 -> 2.0.0
mix rodar_release.merge --dry-run # preview changes
Promotes a pre-release version to stable after merging a development branch into main/master. Without arguments, strips the pre-release suffix. Pass a segment to bump higher.
If you run mix rodar_release.patch (or minor/major) on a stable branch and the current version has a pre-release suffix, the task will detect this and suggest using merge instead.
Rollback
mix rodar_release.rollback # undo last release (soft reset)
mix rodar_release.rollback --hard # undo and discard changes
mix rodar_release.rollback --dry-run # preview rollback
Undoes the last release by deleting its tag and resetting the release commit. Requires the latest commit to be a release commit (release: vX.Y.Z).
- Soft (default): resets the commit and restores
mix.exsandCHANGELOG.mdto the pre-release state. - Hard (
--hard): discards all release changes entirely.
Amend
mix rodar_release.amend # fold changes into release commit
mix rodar_release.amend --dry-run # preview amendAmends the last release commit with any current changes and re-tags. Useful for fixing a typo or adding a missing file right after releasing.
Options
| Option | Applies to | Description |
|---|---|---|
--dry-run | all commands | Preview changes without applying them |
--pre LABEL | patch, minor, major |
Create a pre-release version (e.g., --pre rc, --pre beta) |
--hard | rollback | Discard release changes entirely |
Programmatic API
RodarRelease.read_version()
#=> "1.2.0"
RodarRelease.bump("1.2.3", :minor)
#=> "1.3.0"
RodarRelease.bump("1.1.0", :minor, "rc")
#=> "1.2.0-rc.1"
RodarRelease.bump("1.2.0-rc.1", :patch, "rc")
#=> "1.2.0-rc.2"
RodarRelease.bump("1.2.0-rc.2", :patch)
#=> "1.2.0"
RodarRelease.promote("1.5.1-dev.3", :minor)
#=> "1.6.0"
RodarRelease.has_pre?("1.2.0-rc.1")
#=> true
RodarRelease.write_version("1.3.0")