Skip to content

Version 0.0.3-prerelease03 (still being tested!!!)

Pre-release
Pre-release
Compare
Choose a tag to compare
@github-actions github-actions released this 16 Feb 22:05
· 2620 commits to main since this release

Install cargo-dist 0.0.3-prerelease03

Install prebuilt binaries via shell script

# WARNING: this installer is experimental
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.0.3-prerelease03/cargo-dist-v0.0.3-prerelease03-installer.sh | sh

Install prebuilt binaries via powershell script

# WARNING: this installer is experimental
irm https://github.com/axodotdev/cargo-dist/releases/download/v0.0.3-prerelease03/cargo-dist-v0.0.3-prerelease03-installer.ps1 | iex

Download cargo-dist 0.0.3-prerelease03

target kind download
x86_64-apple-darwin tarball cargo-dist-v0.0.3-prerelease03-x86_64-apple-darwin.tar.xz
x86_64-pc-windows-msvc tarball cargo-dist-v0.0.3-prerelease03-x86_64-pc-windows-msvc.zip
x86_64-unknown-linux-gnu tarball cargo-dist-v0.0.3-prerelease03-x86_64-unknown-linux-gnu.tar.xz
x86_64-pc-windows-msvc symbols cargo-dist-v0.0.3-prerelease03-x86_64-pc-windows-msvc.pdb

Release Notes

USE AT YOUR OWN RISK, SUPER ALPHA

A major overhaul has been done to the design to rationalize some improperly defined features/behaviours, when you update to this version you will need to rerun cargo dist init (and need to generate-ci).

Configuration (Cargo.toml)

You can now persistently configure cargo-dist with [workspace.metadata.dist] in your root Cargo.toml, with the ability to override some settings per-package with [package.metadata.dist].

The following settings can only be set in [workspace]:

  • cargo-dist-version: (Cargo SemVer format) specifies the desired version of cargo-dist for building the project. Currently only used when generating CI scripts. When you run cargo dist init the version you're using will be set here. If omitted, every time you run cargo dist generate-ci it will just bake in the version of cargo dist you are currently locally running.
  • rust-toolchain-version: (rustup toolchain format) species the desired version of rust/cargo for building the project. Currently only used when generating CI scripts. When you run cargo dist init we currently just select a hardcoded stable release (1.67.1). If omitted we will just select the "stable" toolchain (which will drift over time).
  • ci: a list of CI backends to support (currently only ["github"] will work). This is used by cargo dist generate-ci so you no longer need to pass the flag every time. It's also used to detect the format to use for download URLs (for things like installer scripts).

The following settings can be set on either [workspace] or [package], with the latter overriding the former:

  • dist: (bool, defaults to "undefined") whether this package's binaries should be visible to cargo-dist for the purposes of Releases. If undefined, we will defer to cargo's own publish=false config. Packages without binaries are always invisible to cargo-dist.
  • installers: (list of installer kinds) the default set of installers to generate for releases (currently only "github-shell" and "github-powershell" are defined)
  • targets: (list of rust-style target-triples) the default set of targets to use for releases (sort of, see the section on CLI configuration)
  • include: (list of paths relative to that Cargo.toml's dir) extra files to include in executable-zips (does not currently support directories or wildcards, individual files only)
  • auto-includes: (bool, defaults true) whether dist should add README/LICENSE/etc files to your executable-zips when it finds them.

Configuration (Artifact CLI flags)

Previously cargo-dist had some vague notions of what it was supposed to do when you invoked it, because there were platform-specific artifacts like executable-zips but also more platform-agnostic ones like installer scripts. This result in flags like --no-builds with messy semantics and hacks to filter out artifacts we "don't want right now" in the CI scripts (--no-builds was is removed in this release, it was busted).

Now cargo-dist can produce well-defined subsets of the all possible artifacts with the --artifacts flag:

--artifacts = "local" | "global" | "all" | "host"

Artifacts can be broken up into two major classes:

  • local: made for each target system (executable-zips, symbols, MSIs...)
  • global: made once (curl-sh installers, npm package, metadata...)

("all" selects both of these at once)

Having this distinction lets us run cargo-dist independently on multiple machines without collisions between the outputs by spinning up machines that run something like:

  • linux-runner1 (get full manifest): cargo-dist manifest --artifacts=all --output-format=json
  • linux-runner2 (get global artifacts): cargo-dist --artifacts=global
  • linux-runner3 (get linux artifacts): cargo-dist --artifacts=local --target=x86_64-unknown-linux-gnu
  • windows-runner (get windows artifacts): cargo-dist --artifacts=local --target=x86_64-pc-windows-msvc

If let unspecified, we will pick a fuzzier "host" mode that builds "as much as possible" for the local system. This mode is appropriate for local testing/debugging/demoing. If no --target flags are passed on the CLI then "host" mode will try to intelligently guess which targets to build for, which may include building targets that aren't defined in your metadata.dist config (since that config may exclude the current machine!).

The specifics of "host" mode are intentionally unspecified to enable us to provider better out-of-the-box UX for local usage. In CI environments you should always specify one of the other tree options!

Note that the introduction of persistent Cargo.toml configuration is crucial to this semantic redesign, as it allows each invocation to be aware of the "full" set of artifacts across all platforms, and then filter down to it.

If you pass --installer, --ci, or --target this will replace the Cargo.toml value for all packages for that invocation. This is most useful for --target in conjuction with --artifacts=local as it lets us precisely select which platform-specific artifacts to build on the current machine (all 3 of these flags can be passed repeatedly).

WARING! If you specify --artifacts and --target, the selected targets can only be a subset of the ones defined in your Cargo.toml. This ensures cargo dist --artifacts=global has behaviour consistent with cargo dist --artifacts=local --target=..., as global artifacts need to be aware of all targets at once. "host" mode bypasses this restriction so that runs of cargo dist on developer machines can do something useful even if the Cargo.toml doesn't know about the host platform.

Configuration (Announcement/Release Selection)

There is also now a --tag flag for specifying the git tag to use for announcing a new release. This tag must have a specific format detailed below. The tag serves two purposes:

  • It specifies the subset of the workspace that we want to Announce/Release
  • When using CI, it becomes the unique ID for a Github Release, which is necessary for everything to correctly compute download URLs

cargo dist build and cargo dist manifest now both require that you either specify a --tag that "makes sense", or that your workspace is simple enough for a tag to be computed for you. In CI, each git tag you push will create an independent run of cargo-dist's CI to make a Github Release for that tag, and each invocation of cargo-dist will have that tag passed to it, ensuring they all agree on the above details.

There are two kinds of tag formats that are accepted:

  • Unified Announcement: v{VERSION} selects all packages with the given version (v1.0.0, v0.1.0-prerelease, etc.)
  • Singular Announcement: {PACKAGE-NAME}-v{VERSION} selects only the given package (error if the version doesn't match)

Note that other criteria may prevent a package from being selected: it has no binaries, it has dist=false, it has publish=false, etc. If you do not specify a --tag, cargo-dist will check if all still-selectable packages share a version, and if they do it will make a Unified Announcement for them (erroring otherwise).

These two modes support the following workflow:

  • Releasing a workspace with only one binary-having package (either mode works but Unified is Cleaner)
  • Releasing a workspace where all binary-having packages are versioned in lockstep (Unified)
  • Releasing an individual package in a workspace with its own independent versioning (Singular)
  • Releasing several packages in a workspace at once, but all independently (Push multiple Singular tags at once)

Basically the one thing we can't deal with is you saying "I would like a single coherent Announcement (Github Release) for packageA 0.1.0 and packageB 0.2.0", because nothing really ties them together. If you disagree, please let us know how you think it can/should work!

Although you could use extremely careful versioning in conjuction with Unified Announcements to release a weird subset of the packages in your workspace, you really shouldn't because the Github Releases will be incoherent (v0.1.0 has these random packages, v0.2.0 has these other random packages... huh?), and you're liable to create painful tag collisions.

WARNING! cargo-release largely already generates tags that express these exact semantics, except for one annoying corner case (that I've found so far): if you have a non-virtual workspace (the root Cargo.toml is an actual package with child packages), it will always try to tag releases of the root package with a Unified Tag, even when trying using --workspace. This will not play well with cargo-dist. Initial testing suggests virtual workspaces behave much better.

WARNING! cargo-dist currently errors out if you provide a Singular tag for a library-only package (or a Unified Tag that selects only similarly unselectable packages). This is bad UX, but we need to figure out a story for what to do in that situation. (We could just make a Github Release with no artifacts, maybe still grab your Release Notes..?)

Release Notes

Release notes are now temporarily simplified for reliability:

  • For the purposes of a top level Announcement (Github Release), notes are now no longer associated with the individual apps being published, meaning there's only one set of notes generated.

  • If you have a RELEASES* or CHANGELOG* file in the root of your workspace, we will assume these are the release notes for any Unified Announcement (see the previous section) and try to include the relevant section at the top of the Github Release. This is done with the parse_changelog library. If parsing/lookup fails we continue on silently.

  • If the above process succeeds, the heading of the section we found will become the new title of the Github Release. For example, if we find 1.2.0 matches # Version 1.2.0 (2023-01-25), the title of the Github Release will become "Version 1.2.0 (2023-01-25)".

  • If you are publishing 1.2.0-prerelease and we don't find that in your RELEASES/CHANGELOG file, we will now also look for bare 1.2.0 (stripping the prerelease/build portions), on the assumption that these are the WIP release notes for the version you're prereleasing. This lets you iterate on a version without having to churn headings every time you want to cut a prerelease (we recommend including a parenthetical indicating the version is not yet released).

  • We will no longer attempt to include your release notes for Singular Announcements (see the previous section). They will only get auto-generated installers/downloads sections. This is obviously suboptimal, and will be fixed, we just need to do design work on the proper way to handle those cases. (Please tell me in issue #139!)

Fixes

  • The generated Github CI script is now Valid YAML. The script ran fine, but it was rightfully angering YAML linters!
  • The generated Github CI now has a single unified "build artifacts" task with a shared matrix for global artifacts (shell script installers) and local artifacts (executable zips) (previously the "global" artifacts had their own weird task)
  • We now properly detect if cargo dist init has been run by checking for the presence of [profile.dist] in your root Cargo.toml
  • There are now top level fields in dist-manifest.json for release notes for the "full announcement" of all Releases. These fields should be preferred when generating e.g. the body of a Github Release, as they will behave more correctly when there are multiple Releases.
  • If multiple binaries are defined by one Cargo package, they will now be considered part of the same "app" and bundled together in executable-zips. Previously we would give each binary its own "app". The new behaviour matches how 'cargo install' works and is compatible with the expectations of 'cargo binstall'. You kinda have to go out of your way to shove multiple binaries under one package, so we figure if you do, we should respect it!
  • If a package specifes publish=false in its Cargo.toml, we will take this as a hint to not dist it. You can override this behaviour by setting [package.metadata.dist] dist = true in that Cargo.toml.
  • Installer artifacts are now properly prefixed with the id of the Release they're part of, preventing conflicts when doing multiple Releases at once (installer.sh => my-app-v1.0.0-installer.sh).
  • Installers now properly handle packages that define multiple binaries (installing all of them, just like cargo-install)
  • Installers now properly know the Github Release they are going to point to (previously they would guess based on the version of the package which was broken in complicated workflows)