@wtf/semantic-release-cargo
v3.1.0
Published
The plugin of semantic-release that publishes the crates of a train of a Cargo workspace, by @wtf/release-cargo: the version of the release written into the manifests of the train's crates in prepare, and the last release of each other train into its crat
Maintainers
Readme
@wtf/semantic-release-cargo
The plugin of semantic-release that publishes the crates of a train of a Cargo workspace, by
@wtf/release-cargo, as @semantic-release/npm publishes a package,
and writes no version into git: each Cargo.toml holds a placeholder, as 0.0.0-development, and
the tag is the version. It is the run of the tag that publishes, beside the npm packages of the
same release, so one version and one tag name both.
Use
Put it in the plugins of the run of a tag, before the plugin that makes the release of the host,
of a workspace whose crates depend on one another by { path = "…", version = "…" }. It reads
trains, ecosystems and train of the root of the config, as
@wtf/semantic-release-npm does, the train RELEASE_TRAIN of
the environment where train is not given, and the crates as the trains read them, by the
ecosystem of cargo, the default export of @wtf/release-cargo, which ecosystems names so the
trains order and check the crates too: the crates of the release are the crates of the train, whose
paths hold their folders. A crate that depends on a crate of another train is published depending
on that train's last release, by its tags.
// release.config.mjs
export default {
trains: {
runtime: { paths: ['crates/runtime', 'crates/build'] },
// codecs' crates depend on runtime's, which the ecosystem of cargo reads: no dependsOn.
codecs: { paths: ['crates/codec', 'crates/codec-avro'] }
},
ecosystems: ['@wtf/release-cargo'],
train: process.env.RELEASE_TRAIN,
tagFormat: `${process.env.RELEASE_TRAIN}-v\${version}`,
plugins: [
['@wtf/semantic-release-trains', { wrap: '@semantic-release/commit-analyzer' }],
'@wtf/semantic-release-cargo'
]
}verifyConditionschecks the options, thatecosystemslists'@wtf/release-cargo'(ECARGOECOSYSTEM, of no default: add it toecosystems), and the train, reads the workspace bycargo metadata, selects the crates of the train and puts them in order, and reads the last release of each other train, by the trains' own checks (releasedVersionsof@wtf/release-trains/packages), so a workspace that cannot be published fails before the tag: of a crate of the train that depends on a crate of no train (EDEPENDENCYNOTRAIN), or of a train with no release (EDEPENDENCYNORELEASE), or of a crate of two trains (ETRAINOVERLAP);preparewrites the version of the release into the crates of the train, the last release of each other train into its crates, and each into the dependencies on them, and reads the workspace again, so a crate that is not at the version of its train fails the run;publishpublishes each crate the registry lacks, in the order of their dependencies, and skips each it has: a release that stopped part way is finished by running it again. It gives the release of the crates, linked to the page of the first on crates.io.
cargo runs where the release runs, with a credential in the environment of the run, by one of
two ways:
- Trusted publishing, which needs no secret in the project: the job has an ID token
(
id_tokens: CRATES_IO_ID_TOKEN: { aud: crates.io }on GitLab), and each crate has a trusted publisher in its settings on crates.io.publishexchanges the ID token with the registry's API for a publish token that lives a short while, as late as it can, before the first crate it publishes; gives it tocargoalone, asCARGO_REGISTRY_TOKEN, which is not the ID token; and revokes it when it is done, a failed run too. A release with nothing to publish exchanges nothing. Of a token the registry has expired, as in a long release, it exchanges a new one, once, and tries the crate again. No token is in a log or an error. - A token:
CARGO_REGISTRY_TOKEN(orCARGO_REGISTRIES_<NAME>_TOKENof another registry), a protected, masked variable of the CI.
With both, the ID token is used, and the log says so. With neither, verifyConditions fails with
ECRATEAUTH before the tag; of a dry run, which runs verifyConditions alone, it only warns, as
semantic-release skips prepare and publish of one. The
guide shows both. No step commits or pushes.
Options
| Option | Default | What it is |
| ------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| trains | required | Every train of the repo, of the root of the config: the crates of each are those whose folder its paths hold |
| ecosystems | required | The ecosystems of the repo, of the root of the config, which the trains read: '@wtf/release-cargo' among them, or ECARGOECOSYSTEM |
| train | RELEASE_TRAIN | The train of the run, of the root of the config |
| include | every crate that may publish | The crates of the train to publish, by name |
| exclude | none | The crates of the train not to publish, by name, as an example; a crate of publish = false is never published |
| registry | crates.io | The registry, by its name in .cargo/config.toml; crates-io is crates.io |
| index | https://index.crates.io | The base URL of the registry's sparse index, which the plugin asks which versions exist; required of a registry that is not crates.io |
| verify | true | Whether cargo builds each crate before it publishes it |
| idToken | CRATES_IO_ID_TOKEN | The variable of the environment that holds the ID token of the job, for trusted publishing |
| registryApi | https://crates.io | The base URL of the registry's API, where the ID token is exchanged; required of an ID token and a registry |
| system | Node's | The system the plugin runs by, over Node's |
The schema of the options is ./schema, and schema.json its JSON Schema, which an editor reads.
When a publish fails
A crate version is immutable, so what is published stays. A crate that fails to publish stops the run, and the crates before it are on the registry. Fix what cargo says, and run the release of the tag again: each crate the registry has is skipped, and the rest are published. A registry that cannot be asked stops the run before anything is published.
