This document describes how Chromium updates crates.io Rust crates that Chromium depends on.
We have a weekly rotation (go/chromium-crates-update-rotation) of engineers responsible for creating and landing CLs that update Rust crates.
The “Rust: periodic update of 3rd-party crates” rotation requires access to an up-to-date Chromium repo. One way to start a shift is to run git fetch
, git checkout origin/main
, and gclient sync
(but other workflows should also work - e.g. ones based on git-new-workdir
).
Before creating a CL stack, check for open CLs with the cratesio-autoupdate
tag. Such CLs tend to conflict, so coordinate with owners of any open CLs.
create_update_cl.py
The first actual step of the rotation is running the script:
$ tools/crates/create_update_cl.py auto
create_update_cl.py
has to be invoked from within a Chromium repo. The script depends on depot_tools
and git
being present in the PATH
.
In auto
mode //tools/crates/create_update_cl.py
runs gnrt update
to discover crate updates and then for each update creates a new local git branch (and a Gerrit CL unless invoked with --no-upload
). Each branch contains an update created by gnrt update <old crate id>
, gnrt vendor
, and gnrt gen
. Depending on how many crates are updated, the script may need 10-15 minutes to run.
Before the auto-generated CLs can be landed, some additional manual steps need to be done first - see the sections below.
run_cargo_vet.py
The changes in the auto-generated CL need to go through a security audit, which will ensure that cargo vet
criteria (e.g. ub-risk-0
, safe-to-deploy
, etc.). still hold for the new versions. The CL description specifies what are the minimum criteria required for the updated crates (note that supply-chain/audits.toml
can and should record a stricter certification if possible). See the //docs/rust-unsafe.md
doc for details on how to audit and certify the new crate versions (this may require looping in unsafe
Rust experts and/or cryptography experts).
For each update CL, there is a separate git branch created. An audit will most likely need to be recorded in third_party/rust/chromium_crates_io/supply-chain/audits.toml
and committed to the git branch for each update CL. There are some known corner cases where audits.toml
changes are not needed:
remove_crates
in third_party/rust/chromium_crates_io/gnrt_config.toml
(e.g. the cc
crate which is a dependency of cxx
but is not actually used/needed in Chromium). This case should be recognized by the create_update_cl.py
script and noted in the CL description.third_party/rust/chromium_crates_io/supply-chain/config.toml
instead of being covered by real audits from audits.toml
. For such crates, skim the delta and use your best judgement on whether to bump the crate version that the exemption applies to. Note that supply-chain/config.toml
is generated by gnrt vendor
and should not be edited directly - please instead edit third_party/rust/chromium_crates_io/vet_config.toml.hbs
and then run tools/crates/run_gnrt.py vendor
to regenerate supply-chain/config.toml
.audits.toml
of other projects that Chromium's run_cargo_vet.py
imports. In such case you may need to commit changes that cargo vet
generates in third_party/rust/chromium_crates_io/supply-chain/imports.lock
.This step may require one or more of the commands below, for each git branch associated with an update CL (starting with the earliest branches - ones closest to origin/main
):
git checkout rust-crates-update--...
git rebase
to rebase it on top of the manual audits.toml
changes in the upstream branchestools/crates/run_cargo_vet.py check
run_cargo_vet.py check
may list a subset of the criteria that the automated script has listed in the CL description (e.g. if some of the criteria are already covered by audits.toml
imported from other projects).cargo vet
will list the minimum required criteria and audits.toml
can and should record stricter certification if possible. In particular:does-not-implement-crypto
instead of crypto-safe
if the crate does not implement crypto.ub-risk-N
if appropriate.config.toml
, then we want to bump the exemption instead of providing a delta audit that is baselined on an exemption. Note that config.toml
shouldn't be edited manually - please edit vet_config.toml.hbs
and regenerate config.toml
by running tools/crates/run_gnrt.py vendor
.git add third_party/rust/chromium_crates_io/supply-chain
.git commit -m 'cargo vet'
git cl upload -m 'cargo vet'
If the roll brings in a new transitive dependency, it will need to be audited in its entirety and the results recorded in third_party/rust/chromium_crates_io/supply-chain/audits.toml
.
The addition of transitive Rust dependencies does not need ATL approval, but an FYI email should be sent to chrome-atls-discuss@google.com in order to record the addition.
If the crate and/or audit are non-trivial, it's possible to split the additional crate into its own CL, however then it will default to global visibility and allowing non-test use.
gnrt add
and gnrt vendor
can add the dependency to a fresh checkout.allow_first_party_usage
to false
for the crate in third_party/rust/chromium_crates_io/gnrt_config.toml
.group = 'test'
for the crate in third_party/rust/chromium_crates_io/gnrt_config.toml
. This reduces the level of security review required for the library.gnrt gen
will then generate the GN rules.gn gen
will fail in CQ if the crate was placed in the 'test'
group but needs to be visible outside of tests.If updating cxx
, you will also need to update its version in
build/rust/cxx_version.gni
The create_update_cl.py
script may stop early if it detects that gnrt vendor
or gnrt gen
have reported any warnings or errors (e.g. a “License file not found for crate foo” warning). In this case, manual intervention is needed to finish the update CL. It's probably best to finish and land the CLs created so far before trying to restart the script in order to create the remaining CLs.
Other than the above, the CL can go through the normal, plain-vanilla, manual review and landing process.
git cl upload
//third_party/rust/OWNERS
Note that create_update_cl.py auto
will by default only handle minor version updates (e.g. 123.1 => 123.2, or 0.123.1 => 0.123.2). Major version changes (e.g. 1.0 => 2.0, which may include breaking API changes and other breaking changes) need to be handled separately - this section describes what to do.
As part of the rotation, one should attempt to check for new major versions of direct Chromium dependencies (i.e. dependencies directly listed in third_party/rust/chromium_crates_io/Cargo.toml
). To discover direct and transitive dependencies with a new major version, you can use the command below (running it in the final update CL branch - after all the minor version updates):
$ tools/crates/run_cargo.py -Zunstable-options -C third_party/rust/chromium_crates_io -Zbindeps update --dry-run --verbose ... Unchanged serde_json_lenient v0.1.8 (latest: v0.2.0) Unchanged syn v1.0.109 (latest: v2.0.53) ...
If updating to a new major version doesn‘t require lots of Chromium changes, then it may be possible to land the update in a single CL. This is typically possible when the APIs affected by the major version’s breaking change either weren't used by Chromium, or were used only in a handful of places.
Warning: Sometimes a new major version may be API compatible, but may introduce breaking changes in the behavior of the existing APIs.
To update:
tools/crates/create_update_cl.py auto -- some_crate_name --breaking
cargo vet
auditWhen lots of first-party code depends on the old major version, then the transition to the new major version may need to be done incrementally. In this case the transition can be split into the following steps:
docs/rust.md
(i.e. edit Cargo.toml
to add the new version, run gnrt vendor
, and so forth).Cargo.toml
to remove the old version, run gnrt vendor
, and so forth). Any leftover files in //third_party/rust/<crate>/<old epoch>
should also be removed.Note that the following Cargo.toml
syntax allows two versions of a crate to coexist:
[dependencies.serde_json_lenient_old_epoch] package = "serde_json_lenient" version = "0.1" [dependencies.serde_json_lenient] version = "0.2"
create_update_cl.py
auto
modeExtra arguments passed to create_update_cl.py auto
end up being passed to cargo update
. For a complete list of available options, see Cargo documentation here), but the most common scenarios are covered in the sections below.
tools/crates/create_update_cl.py auto
with no extra arguments will attempt to discover minor version updates for all crates that Chromium depends on and for their transitive dependencies.
tools/crates/create_update_cl.py auto -- some_crate_name
can be used to trigger a minor version update of a single crate.
tools/crates/create_update_cl.py auto -- some_crate_name --breaking
can be used to trigger a major version update of a single crate
manual
modeFor maximal control, the script can be used in manual
mode:
Cargo.toml
change:git checkout origin/main
git checkout -b manual-update-of-foo
third_party/rust/chromium_crates_io/Cargo.toml
to change the crate version of the crate (or crates) you want to update. Important: Do not edit Cargo.lock
(e.g. don't run gnrt vendor
etc.).git add third_party/rust/chromium_crates_io/Cargo.toml
git commit -m "Manual edit of Cargo.toml"
git cl upload -m "Manual edit of Cargo.toml" --bypass-hooks --skip-title --force
tools/crates/create_update_cl.py manual --title "Roll foo crate to new version X"
gnrt vendor
to discover and execute updates that were requested by the manual edits of Cargo.toml
in the previous steps.