This document describes how Chromium updates crates.io Rust crates that Chromium depends on.
We have aweekly rotation of Google engineers responsible for creating and landing CLs that update Rust crates.
Google engineers can join the rotation by emailingchrome-safe-coding@google.com.
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 rungit fetch
,git checkout origin/main
, andgclient sync
(but other workflows should also work - e.g. ones based ongit-new-workdir
).
Before creating a CL stack, check for open CLs with thecratesio-autoupdate
tag. Such CLs tend to conflict, so coordinate with owners of any open CLs.
You may also check a doc with notes from previous rotations, where we may note known issues and their workarounds. See (Google-internal, sorry):https://docs.google.com/document/d/1S7gsrJFsgoU5CH0K7-X_gL55zIIgd6UsFpCGrJqjdAg/edit?usp=sharing
create_update_cl.py
The first actual step of the rotation is runningcreate_update_cl.py
. You must invoke it from within thesrc/
directory of a Chromium repository checkout, and it depends ondepot_tools
andgit
being present in thePATH
.
$ cd~/chromium/src# or wherever you have your checkout$ tools/crates/create_update_cl.py auto
Inauto
mode, it runsgnrt 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 bygnrt update <old crate id>
,gnrt vendor
, andgnrt gen
. Depending on how many crates are updated, the script may need 10-15 minutes to run.
The script should Just Work in most cases, but sometimes it may fail when dealing with a specific crate update. SeeRecovering from script failures below for what to do when that happens.
Before the auto-generated CLs can be landed, you will need to get an LGTM from//third_party/rust/OWNERS
. A review checklist can be found at//third_party/rust/OWNERS-review-checklist.md
.
Notes from//third_party/rust/OWNERS-review-checklist.md
apply:
If the new crate is 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
andgnrt vendor
can add the dependency to a fresh checkout.allow_first_party_usage
tofalse
for the crate inthird_party/rust/chromium_crates_io/gnrt_config.toml
.group = 'test'
for the crate inthird_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.create_update_cl.py
script may stop early if it detects thatgnrt vendor
orgnrt 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 thatcreate_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 ofdirect Chromium dependencies (i.e. dependencies directly listed inthird_party/rust/chromium_crates_io/Cargo.toml
). To discover directand 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_gnrt.py update----verbose--dry-run...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 thebehavior of the existing APIs.
To update:
tools/crates/create_update_cl.py auto -- some_crate_name --breaking
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. editCargo.toml
to add the new version, rungnrt vendor
, and so forth).Cargo.toml
to remove the old version, rungnrt vendor
, and so forth). Any leftover files in//third_party/rust/<crate>/<old epoch>
should also be removed.Note that the followingCargo.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 tocreate_update_cl.py auto
end up being passed tocargo update
. For a complete list of available options, seeCargo 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 discoverminor version updates forall 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 aminor version update of a single crate.
tools/crates/create_update_cl.py auto -- some_crate_name --breaking
can be used to trigger amajor version update of a single crate
manual
modeFor maximal control, the script can be used inmanual
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 editCargo.lock
(e.g. don't rungnrt 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 ofCargo.toml
in the previous steps.Sometimes thecreate_update_cl.py
script will fail when dealing with a specific crate update. The general workflow in this case is to
--upstream-branch
that points to the last successful update branch (or to the fix CL) rather than defaulting toorigin/main
.Examples of a few specific situations that may lead to script failure:
gnrt
didn‘t recognize new crate’s license kind or license file. In that case a prerequisite CL needs to be landed first, teachinggnrt
about the new license kinds/files (in readme.rs). You can seean example CL with such a fix.//third_party/rust/chromium_crates_io/patches/
no longer apply cleanly to the new version of a crate. In that case the crate update CL needs to 1) first update the patches, and then 2) update the crate as usual. This is not very well supported by the script... But something like this should work:$ git checkout rust-crates-update--last-successful-update$ git checkout-b fix-patches-for-foo$ git branch--set-upstream-to=rust-crates-update--last-successful-update
$# Fix the patches$ git commit-a-m...$ git cl upload
--upstream-branch
parameter:$ tools/crates/create_update_cl.py auto \--upstream-branch=fix-patches-for-foo \-- name-of-failed-crate
$ git map-branches-v# to orient yourself$ git checkout rust-crates-update--new-successful-update$ git branch--set-upstream-to=rust-crates-update--last-successful-update$ git cl upload-mRebasing...# --bypass-hooks as needed
//third_party/rust/chromium_crates_io/gnrt_config.toml
needs to be updated to work with a new crate version. The same workflow should work as for fixing//third_party/rust/chromium_crates_io/patches/
(see the item above).