Anodizer is a Rust-native release automation tool designed to simplify and streamline the end-to-end release process for Rust projects. It provides a declarative, config-driven approach to building, packaging, signing, publishing, and announcing software releases, enabling developers to define their entire release pipeline in a single configuration file.
Key Features:
Cross-platform builds with support for multiple targets and architectures.
Comprehensive package generation, including binaries, archives, Linux packages (deb/rpm), macOS DMGs, Windows MSI/NSIS installers, and more.
CI/CD integration with GitHub Actions, GitLab, Gitea, and other platforms.
Advanced templating system for release notes, changelogs, and artifact naming.
Reproducible builds with timestamp modification and build metadata tracking.
Audience & Benefit:
Ideal for Rust developers and teams focused on building reliable, consistent, and automated release pipelines. Anodizer saves time by automating repetitive tasks, reducing the risk of human error, and ensuring that releases are consistent across different platforms and environments. It is particularly beneficial for projects with complex release workflows or those requiring cross-platform support.
Anodizer can be installed via winget, making it easy to integrate into your development environment.
README
anodizer
The release pipeline built for Rust — workspace-aware, reproducible, and signed by default.
Anodizer reads a declarative config file and runs your entire release from a single anodizer release command: build, archive, checksum, changelog, sign, release, publish, and announce. It's built around the Rust ecosystem — Cargo workspaces, Cargo.lock-aware version bumps, crates.io, and byte-reproducible artifacts.
See What works (with proof) for a per-feature status — every "live" claim links to a real published artifact you can verify yourself.
Why anodizer?
Your release is a Cargo workspace — not a bag of loose binaries. anodizer is built that way from the ground up.
It speaks Cargo. Per-crate release cadences, per-crate tags, and a tag resolver let a single crate and a thirty-crate monorepo share one config. anodizer tag and anodizer bump rewrite Cargo.tomlandCargo.lock, then commit, tag, and push atomically — no orphaned bump commit, no hand-rolled git push, no lockfile drift.
crates.io, published in the right order. Dependency-aware ordering with sparse-index polling holds each crate until the ones it depends on have propagated — so a workspace publish never races itself into a transient "version not found."
Cross-compiles without the toolchain tax. musl, glibc, Windows, and macOS from one machine via or . No rituals, no per-target CI shards to babysit.
Reproducible — and it proves it. Deterministic artifacts by default, then anodizer check determinism rebuilds them and byte-compares. "Reproducible" becomes a fact your CI enforces, not a claim in your release notes.
Signing and attestation are first-class. cosign + GPG for binaries, archives, checksums, and images, plus SLSA-style build provenance — wired in a few lines, not bolted on after a CVE scare.
Then the long tail that Rust authors actually hit: generated per-crate READMEs, cargo-binstall metadata derived straight from your config (no hand-maintained pkg-url that 404s), version_files to pin your docs and install scripts to the released version, and post-release install smoke tests that catch a broken artifact before your users do.
Already know GoReleaser? anodizer's {{ .Field }} template syntax will feel right at home. Moving from cargo-dist, release-plz, or cargo-release? The migration guides map your setup straight over.
Features
Build
Cross-platform builds via cargo-zigbuild, cross, or native cargo build
Per-build hooks (pre/post), environment variables, feature flags, and target overrides
UPX binary compression with per-target filtering
Workspace support with per-crate independent release cadences
Package
Archives in tar.gz, tar.xz, tar.zst, zip, gz, or raw binary format with OS-specific overrides
Linux packages (.deb, .rpm, .apk, .archlinux, .ipk) via nFPM with full lifecycle scripts
Snapcraft snaps with prime-dir architecture
macOS DMG disk images and PKG installers
Windows MSI and NSIS installers
Flatpak bundles
AppImage portable Linux applications
Makeself self-extracting archives
Source RPMs (.src.rpm)
Source archives with file filtering
SBOM generation (CycloneDX/SPDX)
Checksums with SHA-256, SHA-512, SHA3, BLAKE2b, BLAKE2s, BLAKE3, CRC32, MD5, and more
Sign
GPG and cosign signing for binaries, archives, checksums, Docker images, and SBOMs
Multiple independent signing configurations
Conditional signing via template expressions
Build provenance attestations (SLSA-style) for binaries and artifacts
Publish
GitHub/GitLab/Gitea Releases with asset uploads, draft/prerelease detection, header/footer templates
crates.io with dependency-aware ordering and index polling
Homebrew formula and cask generation
Scoop manifest generation
Chocolatey package generation
Winget manifest generation
AUR PKGBUILD and .SRCINFO generation
Krew plugin manifest generation
Nix derivation generation
SchemaStore catalog registration for editor autocomplete of your config files
Generic webhooks with custom headers and templates
Advanced
Tera templates (Jinja2-like) with GoReleaser-compatible {{ .Field }} syntax
Nightly builds with date-based versioning
Config includes for shared configuration
Split/merge CI for fan-out parallel builds
Monorepo support with independent workspaces
Auto-tagging from commit message directives
Reproducible builds with mod_timestamp and builds_info
Version-string file syncing (version_files) to keep docs, scripts, and manifests in lockstep at tag
Post-release verification with install smoke tests
JSON Schema for editor autocomplete and validation
Installation
Homebrew (macOS/Linux)
brew install tj-smith47/tap/anodizer
Cargo
cargo install anodizer
From source
git clone https://github.com/tj-smith47/anodizer.git
cd anodizer
cargo install --path crates/cli
Quick Start
# Generate a starter config from your Cargo workspace
anodizer init > .anodizer.yaml
# Validate your config
anodizer check
# Check that required tools are available
anodizer healthcheck
# Build a snapshot (no publishing)
anodizer release --snapshot
# Dry run (full pipeline, no side effects)
anodizer release --dry-run
# Auto-tag from commit directives
# (Conventional Commits: feat: → minor, fix: → patch, BREAKING CHANGE: → major)
anodizer tag --dry-run # preview what tag would be created
anodizer tag # create + push the tag, which triggers the release workflow
# Or force a specific tag value:
anodizer tag --custom-tag v0.1.0
For CI-based releases, set GITHUB_TOKEN (or ANODIZER_GITHUB_TOKEN) as a secret — the release pipeline picks it up automatically.
Configuration
Anodizer uses .anodizer.yaml (or .anodizer.toml) in your project root. Add a schema comment for editor autocomplete:
cfgd — declarative, GitOps-style machine configuration management — is anodizer's first real-world adopter and dogfoods every shipped publisher. It's a 4-crate workspace (shared lib + CLI + Kubernetes operator + CSI driver) that ships to crates.io (dependency-aware ordering), GitHub Releases, Homebrew, Scoop, Chocolatey, Winget, the Snap Store, Krew, GHCR, and via cargo binstall — all from one .anodizer.yaml and one tag push.
anodizer release Full release pipeline (--snapshot, --dry-run, --split/--merge, --publish-only, --rollback-only)
anodizer tag Auto-tag from commit directives
anodizer tag rollback Delete anodize-managed tags at a SHA and revert the bump commit
anodizer check Validate configuration + run determinism harness
anodizer init Generate starter .anodizer.yaml
anodizer healthcheck Probe external tools (nfpm, cosign, ...)
anodizer tag rollback "$GITHUB_SHA" is the recommended if: failure() hook
on every release workflow — it deletes any anodize-managed tag at the failed
commit, reverts the bump, and pushes the revert so the next CI run isn't
poisoned. See Release resilience
for the flag matrix and integration recipe.