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
).
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 all possible minor version 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.
(Side-note: outside the rotation one may also use the script to update a single crate - e.g. tools/crates/create_update_cl.py single <crate name>
.)
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 which criteria apply to the updated crates. 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 (but only once https://crrev.com/c/5368743 lands) 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).git add third_party/rust/chromium_crates_io/supply-chain
. git commit -m 'cargo vet'
git cl upload -m 'cargo vet'
If updating cxx
, you may need to also update its version in:
build/rust/BUILD.gn
third_party/rust/cxx/v1/cxx.h
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
will only handle minor version changes (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.
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 the 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:
third_party/rust/chromium_crates_io/Cargo.toml
to change the version being depended upon.docs/rust.md
for importing a new crate (e.g. gnrt vendor
, gnrt gen
, etc.)//third_party/rust/<crate>/<old epoch>
When 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"