From 962b3026390672483a060e05f9397e56db5d317c Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 19 Sep 2024 13:37:22 -0700 Subject: [PATCH] chore: Simplify Release Procedures RFD This RFD recommends changes to simplify the release processes for Hipcheck, explaining the problems with the current setup, and the benefits of the proposed changes. Signed-off-by: Andrew Lilley Brinker --- .../0007-simplified-release-procedures.md | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 site/content/rfds/0007-simplified-release-procedures.md diff --git a/site/content/rfds/0007-simplified-release-procedures.md b/site/content/rfds/0007-simplified-release-procedures.md new file mode 100644 index 00000000..5b7bac51 --- /dev/null +++ b/site/content/rfds/0007-simplified-release-procedures.md @@ -0,0 +1,164 @@ +--- +title: "Simplified Release Procedures" +--- + +## The Current Situation + +Currently, the Hipcheck _project_ has the following artifacts we release +periodically. + +- `hc`: The main Hipcheck binary, produced by the `hipcheck` package. +- `hc-update`: The Hipcheck self-updater, generated by `cargo-dist`. +- `hipcheck-macros`: A Hipcheck-internal library. +- Docker image: published to Docker Hub. + +These are published to the following places: + +- `hc`: + - Crates.io (as `hipcheck`) + - GitHub Releases w/ install script generated by `cargo-dist` +- `hc-update`: + - GitHub Releases w/ install script generated by `cargo-dist` +`- `hipcheck-macros`: + - Crates.io +- Docker image: + - Docker Hub + +When we cut a new release of `hc`, the flow has been: + +1. Update the `CHANGELOG.md` for the project with release notes for the new + version, open a PR, and get that merged. +2. Run `cargo release` locally to make a new release of `hc` to Crates.io. + At the end of that process, `cargo release` creates a publishes a tag for + the new version +3. This triggers `cargo-dist`'s CI `release` job on GitHub. This job then + builds our pre-built binaries and produces the GitHub Release with our + install script and the `hc-update` tool. +4. This release triggers our Docker release build, which publishes our image + to Docker Hub. + +## The Problems + +There are quite a few problems with the above setup: + +1. __Inconsistency__: When a user installs `hc` from the install script + built by `cargo-dist` and included in each GitHub Release, they get the + `hc-update` tool, which allows Hipcheck to self-update through the + `hc update` subcommand. This means that users installing from the + install script get a strictly better outcome than users installing from + Crates.io. +2. __Bad Release Staging__: The current setup has, for `hc` at least, + three separate stages of "releasing" a new version, each of which can + fail independently: + 1. Publishing to Crates.io with `cargo release` + 2. Publishing a GitHub Release with `cargo-dist` + 3. Publishing a container image to Docker Hub + +## Proposal + +We institute a new rule: __One Artifact, One Release__. This means, for +any artifact we're publishing, there's exactly _one_ release event +that publishes to _one_ place. + +Let's walk through what this means in more detail, looking first at +`hc`, and then at the soon-to-be-released Rust plugin SDK. + +### Releasing `hc` + +Under this proposal, a release for `hc` would look like this: + +1. Write the `CHANGELOG.md` update for the new version, make a PR, and + get it merged. +2. Tag the new version as `hipcheck-v`, with `` + replaced with the SemVer version we're releasing (`X.Y.Z`). + +That's it! Then, `cargo-dist` would build our release artifacts, +including the pre-built binaries and the install scripts, and make the +GitHub Release when it's done. + +Once the GitHub Release is made, the Docker build will run, building +a Docker container to publish with the version of the container image's +`curl | sh` install script set to the just-release version. Since this +image is effectively just a wrapper around this install script, it should +run without issue. + +The `cargo-dist` folks at Axo.dev have expressed an interest in handling +generation and publication of Docker images themselves in the future, which +would fit in nicely with this flow as well. + +Also, if we wanted to generate any additional artifacts for a release in +the future, like SBOMs or SLSA attestations, they'd fit right into this +same process, being attached to the GitHub Release. + +### Releasing `hipcheck-sdk` + +In the near future we'll start publishing a new `hipcheck-sdk` crate which +provides a Rust SDK for plugin authors to use when writing plugins in Rust. +This would be a library, and would be released in its own similar way: + +1. Update the `CHANGELOG.md` for this project to reflect the new version. + Make a PR and get this `CHANGELOG.md` merged. +2. Push a tag for `hipcheck-sdk-v` with `` + reflecting the new version. + +We could then have GitHub CI set up to identify the new Git tag pushed, +and run `cargo publish` to publish the new version from CI onto Crates.io. + +This has some nice properties, including automatically permitting anyone +with access to push tags to cut new releases of the crate, and allowing +us to established trusted publication of crates from CI with attestations +in the future. + +## What We'd Lose + +The first, most conspicious thing we'd lose here is that we'd stop +publishing the `hipcheck-macros` crate to Crates.io. This is really a +piece of logic internal to Hipcheck, but is one we have to publish as +a separate crate because it exposes a procedural macro, which needs its +own crate; and that crate has to be public because the `hipcheck` crate +itself is published on Crates.io, and public crates can't have dependencies +published to other registries or not published to a registry at all. + +The second thing we'd lose (though this has substantial benefits) is that +we'd no longer publish the `hipcheck` crate to Crates.io. This means users +would no longer be able to run `cargo install hipcheck` or +`cargo binstall hipcheck` to install Hipcheck locally. This is a reduction +in flexibility for users, but _does_ simplify our processes, make releases +more reliable, and enable us to have more flexibility in the internal +structure of Hipcheck itself. + +Which brings me to a big, but as yet un-discussed, benefit… + +## Vendoring Salsa + +The thing that finally tipped me over into wanting to pursue this +simplification was the looking challenge of vendoring the `salsa` crate. +`salsa` is a Rust crate for incremental computation which we rely on +heavily within Hipcheck. Unfortunately, the maintainers of `salsa` stopped +publishing releases to Crates.io years ago, and `salsa` itself has gone +through 1 major refactor, with a second currently underway, entirely away +from the public versions. If you want to depend on `salsa` as published +to Crates.io, you have to use `salsa` 1.0, which is no longer supported +and has a number of deficits. + +Normally, this isn't a problem, as users of `salsa` can specify it as a +`git` dependency in their `Cargo.toml` file, and use the `package` key on +the dependency to specify the `salsa-2022` package (the 1st majorly-rewritten +version, now itself in the process of being replaced by Salsa 3.0). However, +because `hipcheck` has so far been published to Crates.io, this option is not +available to us. If we wanted to use the newer versions of `salsa` ourselves, +we'd need to vendor them into some sort of `hipcheck-incremental` crate, +which we'd publish to Crates.io ourselves, and which we'd need to sync with +the upstream Salsa project periodically. + +We _did_ tinker with some efforts to do this, but quickly found it to be +reasonably complicated to do. We do not believe pursuing this or maintaining +this vendored version over the long term would be a good use of the team's +time and effort. + +Finally, pursuing this would raise the additional question of the value of +exposing these "should-be-internal-but-have-to-be-external" crates, +`hipcheck-macros` and `hipcheck-incremental`. Neither are intended for others +to use, and while we can certainly _document_ this and tell people not to use +them, we can't _stop_ anyone from using them, and exposing these APIs publicly +is awkward and creates risk and complexity for the Hipcheck project.