For each release, we will fill a new Milestone, and an Issue with a Checklist.
Over the last month before the release target date, we'll discuss the checklist and milestone progress in our weekly calls, and fine tune timing and scope.
This is a checklist of things that should be done in the weeks leading to the release.
workspace = true rather than their version number or pathdependencies, or use workspace = true.0.0.0, this will making bumping during the release easier.RUSTDOCFLAGS="--no-run --nocapture --test-builder clippy-driver -Z unstable-options" cargo +nightly test --doc --all-features --no-fail-fast and fix relevant Clippy issues in the docs (deprecated APIs, unused imports, etc.)cargo +nightly fmt -- --config=format_code_in_doc_comments=true --config=doc_comment_code_block_width=80 to prettify our docscargo update for each Cargo.lock file to update our CI to freshest dependencies. A helpful snippet is find . -name Cargo.lock | while read lockfile; do cd $(dirname $lockfile); cargo update; done, though it is best run from examples/ since you may have other lockfiles in target/cargo-semver-checks directories.ffi/capi/tests/missing_apis.txt and verify that it is empty. If it is not, component owners should either add FFI APIs, add rust_link annotations, or allowlist the relevant APIs as having been punted to the future. In case of unstable APIs, it is okay to leave things in the missing_apis file for now, see unicode-org#7181.ffi/capi depends on a released (not Git) version of Diplomat. Get it published (ask manishearth or sffc) otherwise.milestone-non-blocking. Some heuristics to apply to make this determination:Once the release checklist is complete, the assigned release driver will perform the following steps, in order:
-dev prelease tags from Cargo.tomlsicu_* crates do not follow the ICU4X versioning scheme: icu_codepointtrie_builder, icu_pattern, and icu_experimental. Be sure to give them an appropriate version based on the changelog. Major releases are always paired with a 0.x.0 release of icu_experimental.COMPONENTS in tools/make/bakeddata/src/main.rs use REPO_VERSION and not some override.experimental is using the version for icu_experimental chosen above.Cargo.toml and reset it to version.workspace = true.~ dependencies in the toplevel Cargo.toml's workspace.dependencies.icu_locale_core, icu_provider, and icu_pattern's non-~ dependency in Cargo.toml's workspace.dependenciesworkspace.dependencies. When unsure, just update. See “Updating the dependency specification of a util” below for more information.cargo workspaces publish --from-git --no-remove-dev-deps.cargo publish does not like cyclic dev-deps and will fail on some crates.cargo workspaces publish will automatically edit out dev-deps to handle this. Unfortunately, it dirties the tree when it does this. Hopefully that issue is fixed.cargo publish on individual folders (going back to cargo workspaces publish after the problematic crate is published)cargo publish from the clean git tree.main (you may need to temporarily change branch protection to do so: do not change the ruleset, just remove the default branch from our branch protection ruleset).main (or other repo branches). It is less important to ensure that the publishes are not “dirty”, but it is ideal to try and maintain that.icu4x-release group as owners to each brand new crate that was publishedcargo owner -a github:unicode-org:icu4x-releaseffi-libs completed successfully.release-ffi-libs job. It should upload the artifacts generated by ffi-libs to the release you created in the previous step.ffi/dart/pubspec.yamlffi/dart/lib/src/hook_helpers/hashes.dart to the tag created above, and run regenerate_hashes.dartcd ffi/dart && dart pub publishicu4x/ffi/npm/package.jsoncd ffi/npm && npm publishrelease/x.y including the release tag and FFI commits and push it to the upstreamicu4x-docs repo, run node tools/github-to-astro.ts and follow the instructionsThe ICU4X TC may decide to make a patch release of an ICU4X component on an old release stream, such as to fix a regression in behavior. To make a patch release:
Cargo.tomls on main to reflect the version you wish to publish, to simplify things for people making ICU4X major/minor releases in the future. In this case, try to avoid publishing the util from main: it's fine if there have already been out-of-cycle util releases on main, but if this is the first util release since the last ICU4X release, cherry pick just the necessary changes onto the release branch.release/x.y branch and make a PR. On this branch:release/x.y and have a team member review it.cargo publish was run from is available in the release/x.y branch, as Cargo includes that commit in the published crate and it is useful for supply-chain security and tracking.cargo publish --dry-run to catch many (but not all) of the reasons a publish may fail.release/x.yrelease/x.y locally and check it outcargo publish in the crate(s)cargo publish fails, make a new PR to fix the release branch and get it merged with review. You may admin-merge minor fixes that are mostly tweaking versions in Cargo.toml.ind/icu_collator@1.3.3 (for icu_collator patch version 1.3.3)ind/icu_collator_data@1.3.3 so long as the component has a tagOur utils/ crates do not follow the same versioning scheme as the rest of ICU4X, and may experience more frequent releases.
In general, if you ever cut a new release of a utils/ crate, all icu4x crates depending on new behavior should have their Cargo.toml updated to the latest version, by updating the version specification in the workspace Cargo.toml‘s workspace.dependencies section. However, there are times when you don’t have to, see below.
While code may compile using our local path dependencies, when publishing we must ensure that it will pull in the correct published version of a utils crate.
When cutting new ICU4X releases, make sure all utilities with changes have had a new release containing those changes. To do so, go through the utils/ folder and check the history of each crate since the last version bump. Bear in mind that some folders like yoke/ contain multiple crates (yoke/derive/), and to keep derive-crates' versions in sync with their crates.
If there are no changes, ensure that the current version of the crate is the version in use in ICU4X's components. If not, make sure that ICU4X is not relying on any features since the release that is in use. In case of such reliance, update the version in use in the ICU4X components.
If there are changes, go through the changes and determine if they are breaking or not. For breaking changes, perform a breaking version bump (x.y.z to x+1.0.0, and 0.x.y to 0.x+1.0) and update all of ICU4X's components to use the new version.
For non breaking changes, perform a non-breaking version bump (x.y.z to x.y.z+1 or x.y+1.0 based on the size of the changes; 0.x.y to 0.x.y+1). Then, determine if the introduced functionality is being relied upon by ICU4X (assume it is if this is tricky to determine). If it is, update the version in use by the ICU4X components, otherwise it is fine to not do so.
This can all be done in a separate PR to chunk out the work but there should be no changes to utils between this PR landing and the overall ICU4X version bump. After landing the PR, as usual, cargo publish should be run on the updated utils.
We share dependency specifications for all workspace crates in the [workspace.dependencies] section of Cargo.toml.
It is a nice-to-have feature that updating ICU4X does not require one to update every util. This reduces impact especially to people who need to audit new dependencies or vendor code, allowing more flexibility on ICU4X updates.
However, this carries risks. We do not currently CI for mininal-versions (See #2966), which means that a commit may inadvertently introduce a dependency on a newly introduced feature, which we then miss when we perform a release.
To allow for this, we follow the rule that EVERY [workspace.dependencies] entry that diverges from its current version MUST have a # Current version: comment after it, like so:
databake = { version = "0.2.0", path = "utils/databake", default-features = false } # Current version: 0.2.1
This MUST be kept up to date when releases are performed.
By default, when a util is being released, its workspace.dependencies should be updated. The following is a set of heuristics for when this rule does and doesn't need to be followed, applied in order.
Firstly, if before the release the util was already diverging, you SHOULD update to at least the already-released version. For example, if ICU4X 2.2 depends on databake = 0.2.0 and releases databake@0.2.1, ICU4X 2.3 should update workspace.dependencies to at least databake = 0.2.1. This simplifies things when it comes to the subsequent heuristics: one doesn't have to go trawl through multiple versions worth of history. There is a decent benefit for an ICU4X release to not require an update of all utils to newly released versions, but that benefit is less for util versions that have been published for a few months. We encourage users who need audits and vendoring to perform periodic rolling updates of their dependencies to reduce impact of ICU4X releases.
You MUST update if any part of ICU4X or ICU4X utils depends on APIs or behavior in the new version.
You MAY choose to not update when the changes are only:
You SHOULD update for soundness fixes.
You SHOULD update for major bug fixes.