Release process

Cargo is released with rustc using a “train model”. After a change lands in Cargo’s master branch, it will be synced with the rust-lang/rust repository by a Cargo team member, which happens about once a week. If there are complications, it can take longer. After it is synced and merged, the changes will appear in the next nightly release, which is usually published around 00:30 UTC.

After changes are in the nightly release, they will make their way to the stable release anywhere from 6 to 12 weeks later, depending on when during the cycle it landed.

The current release schedule is posted on the Rust Forge. See the release process for more details on how Rust’s releases are created. Rust releases are managed by the Release team.

Build process

The build process for Cargo is handled as part of building Rust. Every PR on the rust-lang/rust repository creates a full collection of release artifacts for every platform. The code for this is in the dist bootstrap module. Every night at 00:00 UTC, the artifacts from the most recently merged PR are promoted to the nightly release channel. A similar process happens for beta and stable releases.

Submodule updates

Cargo is tracked in the rust-lang/rust repository using a git submodule. It is updated manually about once a week by a Cargo team member. However, anyone is welcome to update it as needed.

@ehuss has a tool called subup to automate the process of updating the submodule, updating the lockfile, running tests, and creating a PR. Running the tests ahead-of-time helps avoid long cycle times waiting for bors if there are any errors. Subup will also provide a message to include in the PR with a list of all PRs it covers. Posting this in the PR message also helps create reference links on each Cargo PR to the submodule update PR to help track when it gets merged.

The following is an example of the command to run in a local clone of rust-lang/rust to run a certain set of tests of things that are likely to get broken by a Cargo update:

subup --up-branch update-cargo \
    --commit-message "Update cargo" \
    --test="src/tools/linkchecker tidy \
        src/tools/cargo \
        src/tools/rustfmt" \
    src/tools/cargo

If doing a beta backport, the command is similar, but needs to point to the correct branches:

subup --up-branch update-beta-cargo \
    --rust-branch beta \
    --set-config rust.channel=beta \
    --commit-message "[beta] Update cargo" \
    --test="src/tools/linkchecker tidy \
        src/tools/cargo \
        src/tools/rustfmt" \
    rust-1.66.0:src/tools/cargo

Version updates

Shortly after each major release, a Cargo team member will post a PR to update Cargo’s version in Cargo.toml. Cargo’s library is permanently unstable, so its version number starts with a 0. The minor version is always 1 greater than the Rust release it is a part of, so cargo 0.49.0 is part of the 1.48 Rust release. The CHANGELOG is also usually updated at this time.

Also, any version-specific checks that are no longer needed can be removed. For example, some tests are disabled on stable if they require some nightly behavior. Once that behavior is available on the new stable release, the checks are no longer necessary. (I usually search for the word “nightly” in the testsuite directory, and read the comments to see if any of those nightly checks can be removed.)

Sometimes Cargo will have a runtime check to probe rustc if it supports a specific feature. This is usually stored in the TargetInfo struct. If this behavior is now stable, those checks should be removed.

Cargo has several other packages in the crates/ directory. If any of these packages have changed, the version should be bumped before the beta release. It is rare that these get updated. Bumping these as-needed helps avoid churning incompatible version numbers. This process should be improved in the future!

@ehuss has a tool called cargo-new-release to automate the process of doing a version bump. It runs through several steps:

  1. Creates a branch
  2. Updates the version numbers
  3. Creates a changelog for anything on the master branch that is not part of beta
  4. Creates a changelog for anything on the beta branch

It opens a browser tab for every PR in order to review each change. It places each PR in the changelog with its title, but usually every PR should be rewritten to explain the change from the user’s perspective. Each PR should also be categorized as an Addition, Change, Fix, or Nightly-only change. Most PRs are deleted, since they are not relevant to users of Cargo. For example, remove all PRs related to Cargo internals, infrastructure, documentation, error changes, refactorings, etc. Usually about half of the PRs get removed. This process usually takes @ehuss about an hour to finish.

Docs publishing

Docs are automatically published during the Rust release process. The nightly channel’s docs appear at https://doc.rust-lang.org/nightly/cargo/. Once nightly is promoted to beta, those docs will appear at https://doc.rust-lang.org/beta/cargo/. Once the stable release is made, it will appear on https://doc.rust-lang.org/cargo/ (which is the “current” stable) and the release-specific URL such as https://doc.rust-lang.org/1.46.0/cargo/.

The code that builds the documentation is located in the doc bootstrap module.

crates.io publishing

Cargo’s library and its related dependencies (like cargo-util) are published to crates.io as part of the 6-week stable release process by the Release team. There is a publish.py script that is used by the Release team’s automation scripts (see https://github.com/rust-lang/simpleinfra/) to handle determining which packages to publish. The build tool crates aren’t published. This runs on the specific git commit associated with the cargo submodule in the stable branch in rust-lang/rust at the time of release.

On very rare cases, the Cargo team may decide to manually publish a new release to crates.io. For example, this may be necessary if there is a problem with the current version that only affects API users, and does not affect the cargo binary shipped in the stable release. In this situation, PRs should be merged to the associated stable release branch in the cargo repo (like rust-1.70.0) that fix the issue and bump the patch version of the affected package. Then someone with permissions (currently a subset of the Cargo team, or the Release team) should publish it manually using cargo publish.

Some packages are not published automatically because they are not part of the Rust release train. This currently only includes the home package. These are published manually on an as-needed or as-requested basis by whoever has permissions (currently @ehuss or the Release/Infra team).

In the future, these manual publishing options should be integrated with GitHub Actions so that any team member can trigger them. Likely that should involve getting Infra to create scoped tokens that can be added as GitHub Secrets, and setting up GitHub Actions workflows with the appropriate permissions which can be manually triggered to launch a release.

Beta backports

If there is a regression or major problem detected during the beta phase, it may be necessary to backport a fix to beta. The process is documented in the Beta Backporting page.

Stable backports

In (hopefully!) very rare cases, a major regression or problem may be reported after the stable release. Decisions about this are usually coordinated between the Release team and the Cargo team. There is usually a high bar for making a stable patch release, and the decision may be influenced by whether or not there are other changes that need a new stable release.

The process here is similar to the beta-backporting process. The rust-lang/cargo branch is the same as beta (rust-1.XX.0). The rust-lang/rust branch is called stable.