Release complex cargo-workspaces automatically with changelog generation, used by `gitoxide`

Overview

cargo smart-release

Fearlessly release workspace crates and with beautiful semi-handcrafted changelogs.

asciicast

Key Features

  • zero-configuration
    • cargo smart-release needs no extra flags to do the right thing™️ smartly. If your intervention is needed it will let you know before it makes changes.
    • It won't do anything if there are no changes.
  • made for multi-crate workspaces
    • "Nothing stands by itself, and everything is interconnected" - is how it sees the world, allowing it to efficiently handling complex workspace graphs.
    • works just as well for single-crate workspaces
  • changelogs-deluxe
    • It maintains beautiful changelogs for you while allowing you to edit them for the final polish.
    • See your release notes via in-repository tag objects and in GitHub Releases
    • plays well with cargo release
      • cargo changelog writes changelogs non-destructively, and only that, leaving the release workflow to cargo-release.

If seeing is believing, here is a 12 minute demonstration, and the same in 30 minutes is also available.

Made for this Workflow

When developing various crates in a workspace, when committing changes and if the edit is breaking, a feature, or another change I want to see in changelogs, conventional git messages will be used. This helps building changelog scaffolding automatically later.

When ready for releasing a particular crate or set of crates of interest, run cargo smart-release [<crate-name> ...] to simulate a release. For particularly thorough but error-prone simulations (as in false positives) one could run cargo smart-release --dry-run-cargo-publish. To polish changelogs, run cargo changelog --write <crate-name> to update the scaffolding and edit it by hand until it fits.

After evaluating the release procedure and following instructions, cargo smart-release --execute will cause the fully automatic release of one or more crates.

There are various other options that shouldn't be needed in the common case, use cargo smart-release --help to see them.

Installation

Cargo

Via cargo, which can be obtained using rustup

cargo install cargo-smart-release

Features

  • safe to use as actually performing an operation requires the --execute flag
  • avoid inconsistent states by making operations as atomic as possible, leveraging gitoxide technology to the fullest
  • handle workspace dependencies and cycles gracefully, allowing one invocation to publish multiple crates
  • avoid making any releases if there are no changes
  • avoid bumping versions if the current version isn't released, allowing you to control the version by editing the cargo manifest
  • conventional commit message drive changelog scaffolding and to automatically derive the crate version to publish
  • automatically release dependent workspace IDP crates along with the desired one if they changed since their last release
  • automatically adjust manifest versions and update manifests of crates which use those whose versions were incremented
  • conservatively bump downstream workspace crates in the light of breaking changes, even though these won't be published, making downstream breakage impossible
  • use git tags to know if a crate changed at all, skipping publishes if there is no code change at all
  • it's too eager to release and there should be a way to control patch releases.
  • Handle pre-release versions, like 1.0.0-beta.1
  • Support other remote names than 'origin' - currently the latter name is assumed. Fix by getting the remote of the currently checked out branch.
  • handle version specifications correctly (tables vs values)
  • handle all version comparators correctly (see here for how it's done)
  • Automatically detect if crate changes are breaking to suggest the correct version increment

Comparison to cargo release

cargo-release is the reason this tool exists, as it got me addicted to an all automatic release workflow that knows git. This works perfectly for simple workspaces or single-crate workspaces, as of 2021-08-12, so use it: cargo install cargo-release.

Here is what cargo smart-release does differently: "It tries really hard to do what I want most of the time when publishing workspace gitoxide crates".

  • be safe to execute, so it's disarmed by default
  • specify one or more crates, and detect which crates need publishing automatically
  • handle dependency cycles in such a way that increases the chances of overall success
  • try really hard to not leave the workspace in an inconsistent state when something goes wrong
  • be a playground for gitoxide to have a reason to make it much more convenient and more feasible for application authors (aka dog-fooding)
  • create changelogs non-destructively, along with annotated tags and GitHub releases

Limitations

  • it requires tables to be used when specifying versions, i.e. crate = { version = "1" } instead of `crate = "1".
  • it gracefully fails when encountering version requirement comparators which are not ^, like =
  • it's tested only by using it on gitoxide, there are only very few regression tests with little coverage.
  • short object ids in changelogs may be ambiguous, as they are unconditionally truncated to 7 characters.
  • changelog rewriting of user content will drop links if they are not of the 'inline' form
  • it's very young and probably tries to eat underwear
  • it needs a git repository to govern the workspace

Changelogs

  • When determining if something changed in top-level crates, only the src/ directory is used, unless there is only a single crate in the workspace. This value is hard-coded.
  • For change tracking, it will only obtain manifest values once to know where a crate lives, and expects it to not be moved.
  • If list items populated by commit messages contain items themselves, round-tripping will fail. Ideally there was a way to parse an item on the same level only.

Acknowledgements

Thanks to cargo-release for showing the way and for incredible fast response times. I'd recommend everyone to participate there instead of writing your own.

Special thanks go to git-cliff which gave me the nudge needed to want to write my own.

Comments
  • [smart-release] Add option to skip published crate version checks

    [smart-release] Add option to skip published crate version checks

    Summary 💡

    Add cli option to remove any checking/verification against crates.io

    e.g.

    --no-published-crate-verification
       Do not verify version against published crates. Also implies --no-publish as this
       crate likely should not be published.
    

    I'm happy to take a stab at this as a PR if you think it's not too difficult.

    Motivation 🔦

    I'm using smart-release in a bit of an unusual way (excellent tool btw!). Basically, I'm using it to create tags in GitHub for various releases and ignore crates entirely. In my case my cargo targets are embedded binaries which will never be published to crates.io (the build also use cargo-make and selective linkers and compiler targets which makes typical cargo publish tests difficult anyways).

    Unfortunately in my case, there's a duplicate name of one of the packages and I get an error.

    cargo smart-release -u keystonetkl keystonefs kira gemini --no-publish  --no-isolate-dependencies-from-breaking-changes
    [INFO ] Updating crates-io index
    [WARN ] Crate 'kira' computed version not greater than the current package version. Updating crates index to assure correct results.
    [WARN ] Refused to publish 'keystonetkl' as as it didn't change.
    [WARN ] Refused to publish 'keystonefs' as as it didn't change.
    [WARN ] Refused to publish 'gemini' as as it didn't change.
    [INFO ] Will not publish or alter 4 dependent crates: unchanged = 'kiibohd-atsam4s', 'keystonetkl', 'keystonefs', 'gemini'
    [ERROR] Latest published version of 'kira' is 0.7.1, the new version is 0.1.1. Consider using --bump <level> or update the index with --update-crates-index.
    [INFO ] WOULD auto-bump provided package 'kira' from 0.1.0 to 0.1.1 for publishing, 0.7.1 on crates.io
    Error: Aborting due to previous error(s)
    

    I can obviously just rename kira to something else, but since I can't easily reserve the names (and really I shouldn't name-squat something I'm not going to be using anyways...) it would be nice to just remove this check entirely.

    enhancement 
    opened by haata 2
  • Better handling of stable/1.0 crates

    Better handling of stable/1.0 crates

    Currently one has two options:

    • use --auto-publish-of-stable-crates to safety-bump stable crates just like unstable ones, causing unnecessary churn downstream
    • not do the above and see the publish fail as the manifest wasn't updated with new/bumped versions of workspace dependencies.

    What would be required is the give them a patch-level bump instead, while keeping everything else as is (maybe even by default). That way they could be published as usual and everything should work fine.

    bug good first issue 
    opened by Byron 0
  • cargo-smart-release doesn't update `[workspace.dependencies]` version

    cargo-smart-release doesn't update `[workspace.dependencies]` version

    First off, this crate is awesome. It is so close to being a does-what-you-want publish tool for cargo crates.

    For this project though, we set our version numbers in the root workspace and cargo-smart-release doesn't seem to update things there. When the publish step comes, cargo fails because versions don't match.

    If organizing workspaces like this is bad practice, I can change it. That's one major problem with large Rust projects and workspaces. There is no "do it this way" guide that actually works from start to publish.

    I tried to reorganize the project to align with git-oxide. I moved the binary to the root and combined the package & workspace Cargo.toml, but it wasn't enough.

    If this seems like a bug in cargo-smart-release vs how we structured our project, I'll gladly submit a PR if you can guide me to the part of the codebase I should start in.

    Thanks again!

    enhancement help wanted 
    opened by jsoverson 1
  • smart-release path must exist in current commit (panic)

    smart-release path must exist in current commit (panic)

    Current behavior 😯

    ❯ RUST_BACKTRACE=1 cargo smart-release
    [WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
    [WARN ] Using 'brix' as crate name as no one was provided. Specify one if this isn't correct
    thread 'main' panicked at 'path must exist in current commit', /home/xeno/.asdf/installs/rust/1.71.1/registry/src/index.crates.io-6f17d22bba15001f/cargo-smart-release-0.20.0/src/git/mod.rs:50:26
    stack backtrace:
       0: rust_begin_unwind
                 at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
       1: core::panicking::panic_fmt
                 at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
       2: core::panicking::panic_display
                 at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:150:5
       3: core::panicking::panic_str
                 at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:134:5
       4: core::option::expect_failed
                 at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/option.rs:1932:5
       5: cargo_smart_release::git::change_since_last_release
       6: cargo_smart_release::traverse::dependencies
       7: cargo_smart_release::command::release_impl::release_depth_first
       8: cargo_smart_release::command::release_impl::release
       9: cargo_smart_release::main
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    

    Expected behavior 🤔

    I'm not sure; this is my first attempt to use it. I would expect more helpful messaging; at the very least. a stack trace feels weird.

    Steps to reproduce 🕹

    this repo/sha should reproduce

    https://github.com/xenoterracide/brix/commit/178ece2401ab64bd1d014311bf6824618fd94db5

    help wanted 
    opened by xenoterracide 1
  • [cargo-smart-release] Release Commits Flow

    [cargo-smart-release] Release Commits Flow

    Summary 💡

    Create a mode of cargo-smart-release that is aware of special commits with type "release". The idea being that release commits are where changelogs and versions are automatically updated, and the commit description identifies which of the crates are being released. This has the benefit that a. it provides a way to signal to CI which things need to be released (by reading the commit description), b. the tool can know that it is only traversing back to the last release commit, c. and because it doesn't go past the release commit they act as a safe place to rename/relocate crates.

    What do you think about adding this flow to cargo smart-release?

    Motivation 🔦

    I'm working on developing a release process for wit-bindgen, a Bytecode Alliance project, which has multiple crates that I would like to version more separately using something like cargo smart release. The features I'm asking for would help us implement the proposed process without requiring a ton of maintainer work.

    enhancement help wanted 
    opened by esoterra 1
  • [cargo-smart-release]: `cargo publish` fails due to dirty files which wouldn't be included

    [cargo-smart-release]: `cargo publish` fails due to dirty files which wouldn't be included

    See this comment for details: https://github.com/rust-lang/cargo/pull/9478#issuecomment-1153392615.

    If it becomes a cargo issue we can track it here.

    In the mean time, one can delete the generated files in question .

    Tasks

    • [ ] make the issue reproducible and file an issue, PR (see this comment for more information
    • [ ] maybe even provide a fix
    question 
    opened by Byron 1
Owner
Sebastian Thiel
Sebastian Thiel
Ingraind - a security monitoring agent built around RedBPF for complex containerized environments and endpoints.

ingraind is a security monitoring agent built around RedBPF for complex containerized environments and endpoints. The ingraind agent uses eBPF probes to provide safe and performant instrumentation for any Linux-based environment.

KingoOo 5 Apr 6, 2022
Fiddi is a command line tool that does the boring and complex process of checking and processing/watching transactions on EVM compatible Blockchain.

Fiddi is a command line tool that does the boring and complex process of checking and processing/watching transactions on EVM compatible Blockchain.

Ahmad Abdullahi Adamu 7 Jan 9, 2023
Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations in complex protocols.

Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations (e.g. hashing, encryption, message authentication codes, and authenticated encryption) in complex protocols.

Coda Hale 3 Dec 27, 2022
`llm-chain` is a powerful rust crate for building chains in large language models allowing you to summarise text and complete complex tasks

llm-chain ?? llm-chain is a collection of Rust crates designed to help you work with Large Language Models (LLMs) more effectively. Our primary focus

Sobel IO 36 Apr 6, 2023
Cryptographic Primitive Code Generation by Fiat

Fiat-Crypto: Synthesizing Correct-by-Construction Code for Cryptographic Primitives Building This repository requires Coq 8.11 or later. Note that if

Programming Languages and Verification Group at MIT CSAIL 538 Jan 7, 2023
Next-generation implementation of Ethereum protocol ("client") written in Rust, based on Erigon architecture.

?? Martinez ?? Next-generation implementation of Ethereum protocol ("client") written in Rust, based on Erigon architecture. Why run Martinez? Look at

Arthur·Thomas 23 Jul 3, 2022
Validity is a next-generation, deduction-based language for formally verified, context-aware, autonomous & reactive smart contracts.

Validity Language Validity is a next-generation, deduction-based language for formally verified, context-aware, autonomous & reactive smart contracts.

Tempest Labs 4 Nov 11, 2022
A pretty simple tool for password generation, written in Rust.

passwdgen A pretty simple tool for password generation, written in Rust. Usage: passwdgen - a pretty simple tool for password generation Usage: passw

Kirill Belolipetsky 9 Feb 19, 2023
CYFS:Next Generation Protocol Family to Build Web3

CYFS is the next-generation technology to build real Web3 by upgrading the basic protocol of Web (TCP/IP+DNS+HTTP). It has a subversive architectural design that everyone brings their own OOD (Owner Online Device) to form a truly decentralized network.

CYFS Core Dev Team 2k Jul 6, 2023
deductive verification of Rust code. (semi) automatically prove your code satisfies your specifications!

Le marteau-pilon, forges et aciéries de Saint-Chamond, Joseph-Fortuné LAYRAUD, 1889 About Creusot is a tool for deductive verification of Rust code. I

Xavier Denis 609 Dec 28, 2022
shavee is a Program to automatically decrypt and mount ZFS datasets using Yubikey HMAC as 2FA or any USB drive with support for PAM to auto mount home directories.

shavee is a simple program to decrypt and mount encrypted ZFS user home directories at login using Yubikey HMAC or a Simple USB drive as 2FA written in rust.

Ashutosh Verma 38 Dec 24, 2022
Kubernetes controller written in Rust for automatically generating and updating secrets

Kubernetes controller written in Rust for automatically generating and updating secrets

Loc Mai 6 Nov 8, 2022
Automatically assess and score software repositories for supply chain risk.

Hipcheck Hipcheck scores risks for software projects; yours and your dependencies. It analyzes repositories to assess risks, review development practi

The MITRE Corporation 6 Jan 26, 2023
A Rust port of the password primitives used in Django Project.

Rust DjangoHashers A Rust port of the password primitives used in Django Project. Django's django.contrib.auth.models.User class has a few methods to

Ronaldo Ferreira 52 Nov 17, 2022
A temporary repo for ETH connector to be used by EVM

ETH connector for Rainbow bridge Definitions bridgedETH - NEP-141 fungible-token representation of ETH inside Near. nETH - native ETH inside Near EVM.

Project Aurora 36 Jul 26, 2022
This is the Repo used to learn blockchain development in conjusction with the CyberGen NFT Project.

Environment Setup Install Rust from https://rustup.rs/ Install Solana from https://docs.solana.com/cli/install-solana-cli-tools#use-solanas-install-to

null 1 Nov 3, 2021
A pairing-based threshold cryptosystem for collaborative decryption and signatures used in HoneybadgerBFT implementation

threshold_crypto A pairing-based threshold cryptosystem for collaborative decryption and signatures. The threshold_crypto crate provides cryptographic

null 166 Dec 29, 2022
CLI tool written in Rust which can be used to generate hashes

rustgenhash rustgenhash is a tool to generate hashes on the commandline from stdio. It can be used to generate single or multiple hashes for usage in

Volker Schwaberow 11 Dec 29, 2022
A Rust port of the password primitives used in Django Project.

Rust DjangoHashers A Rust port of the password primitives used in Django Project. Django's django.contrib.auth.models.User class has a few methods to

Ronaldo Ferreira 52 Nov 17, 2022