cargo-promote (0.1.1)
Installation
[registry]
default = "gitea"
[registries.gitea]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add cargo-promote@0.1.1About this package
cargo-promote
Crate publishing and promotion pipeline for Rust projects. Publishes to private registries (Gitea/cratebox) and optionally crates.io, with configurable pipelines, per-package overrides, deferred promotions, and forge integration.
Install
cargo install --path .
Commands
Publishing
# Publish current crate to the first pipeline stage
cargo-promote publish
# Publish a specific workspace member
cargo-promote publish -p my-crate
# Publish to a named registry directly
cargo-promote publish --registry cratebox
# Publish even if the version already exists on the registry
cargo-promote publish --force
# Publish + promote through all pipeline stages
cargo-promote ship -p my-crate
# Publish all crates under a directory in dependency order
cargo-promote publish-all --path ~/dev --dry-run
cargo-promote publish-all --force --skip "sandbox,experiments"
Promotion
# Promote from one pipeline stage to the next
cargo-promote promote -p my-crate --from cratebox
# Bump version and create promote.lock
cargo-promote bump
# Merge branch stage forward
cargo-promote branch --from develop
Deferrals
Defer a promotion for later confirmation (e.g. after manual QA):
# Defer a registry promotion
cargo-promote defer --from cratebox
# Defer a branch promotion
cargo-promote defer --branch --from develop
# Confirm or reject a pending deferral
cargo-promote confirm <ticket>
cargo-promote reject <ticket> --reason "failed QA"
# List deferrals
cargo-promote deferrals
cargo-promote deferrals --pending
Info
# List crates on a registry
cargo-promote list
cargo-promote list --registry crates-io
# Show local crate versions
cargo-promote status
Configuration
Place a promote.toml in your crate or workspace root:
# Automatically bump version before publishing (patch | minor | major)
autobump = "patch"
[registries.cratebox]
cargo_name = "cratebox"
api_url = "http://100.105.75.7:3000/api/packages/joe/cargo"
[registries.crates-io]
confirm = true # prompt before publishing
[pipelines.default]
stages = ["cratebox", "crates-io"]
Per-Package Overrides
Override autobump, pipeline, or publishing behavior per crate:
autobump = "patch"
[packages.my-internal-crate]
publish = false # skip during publish-all
[packages.important-lib]
autobump = "minor" # override global autobump
pipeline = "staging-only" # use a different pipeline
Forge Integration
Connect to a Gitea or GitHub forge for PR-based deferral workflows.
When configured, defer creates a PR on the forge, and confirm
closes it automatically.
[forge]
type = "gitea"
url = "http://localhost:3000"
owner = "joe"
repo = "my-project"
token_env = "GITEA_TOKEN" # env var holding the API token
Branch Pipeline
For environment-based promotion through git branches:
autobump = "patch"
[pipeline]
stages = ["develop", "staging", "production"]
release_branch = "production" # default: last stage
[registries.cratebox]
cargo_name = "cratebox"
The pipeline works as a CI chain:
- Push to
develop-- CI runs -- on green,cargo-promote bumpwrites version andpromote.lock, thencargo-promote branch --from developmerges tostaging - CI on
staging-- on green,cargo-promote branch --from stagingmerges toproduction cargo-promote publishonproductiontags the release -- a tag-triggered CI workflow handles registry publishing
promote.lock tracks the version and a SHA-256 hash of publishable
source files (src/, Cargo.toml, Cargo.lock). The hash is
verified at every branch hop to ensure nothing mutated mid-pipeline.
Registry Auto-Discovery
cargo-promote automatically discovers registries from
.cargo/config.toml files by walking ancestor directories and
checking $CARGO_HOME. Entries in promote.toml take precedence
over discovered registries.
Cargo Registry Setup
Add cratebox to ~/.cargo/config.toml:
[registries.cratebox]
index = "sparse+http://<your-host>/api/packages/<user>/cargo/"
[registry]
default = "cratebox"
Add your token to ~/.cargo/credentials.toml:
[registries.cratebox]
token = "Bearer <your-token>"
Default Behavior
Without a promote.toml, cargo-promote uses built-in defaults:
- Registry: cratebox at
http://100.105.75.7:3000/api/packages/joe/cargo(override withREGISTRY_URLandREGISTRY_USERenv vars) - Pipeline: cratebox -> crates-io (crates-io requires confirmation)
Architecture
Hexagonal architecture with domain ports (traits) and infrastructure adapters:
- Domain:
CrateRef,Pipeline,Stage,PublishOpts,Deferral,PromoteLock - Ports:
Publisher,RegistryQuery,PipelineRunner,BranchMerger,RemotePusher,Tagger,TokenResolver,Notifier,Forge - Adapters:
CargoPublisher,GiteaRegistry,GiteaForge,LocalGit,CargoTokenResolver - API:
Apifacade withApiBuilderfor dependency injection
Build
cargo build --release
cargo test
cargo clippy
Dependencies
| ID | Version |
|---|---|
| anyhow | ^1.0 |
| cargo_metadata | ^0.18 |
| chrono | ^0.4 |
| clap | ^4 |
| secrecy | ^0.10 |
| semver | ^1 |
| serde | ^1.0 |
| serde_json | ^1.0 |
| serde_yaml | ^0.9 |
| sha2 | ^0.10 |
| thiserror | ^2 |
| toml | ^0.8 |
| toml_edit | ^0.22 |
| ureq | ^2 |
| tempfile | ^3.0 |