Cargo
Publish and add a workspace's Rust crates with Cargo, from a sparse registry of its own on g1t.sh, from your machine and from workflows.
Every workspace has a Cargo registry of its own: a sparse index, with the
web API that cargo publish, cargo yank and cargo search use. It
works with Cargo 1.74 or later, private crates included.
sparse+https://g1t.sh/-/cargo/<workspace>/index/Crates from crates.io still come from crates.io; only the crates you name with the workspace’s registry come from g1t.
Set up .cargo/config.toml
Section titled “Set up .cargo/config.toml”Name the registry in the project’s .cargo/config.toml, or in
~/.cargo/config.toml for every project. The name you give it is the one
you pass to --registry; these pages use the workspace’s slug:
[registries.acme]index = "sparse+https://g1t.sh/-/cargo/acme/index/"credential-provider = "cargo:token"Cargo sends a token to a registry that asks for one only through a
credential provider named for it. cargo:token keeps the token in
~/.cargo/credentials.toml, which stays out of the project. To keep it in
your system’s keychain instead, name cargo:wincred (Windows),
cargo:macos-keychain (macOS) or cargo:libsecret (Linux).
Then give Cargo an access token:
cargo login --registry acmeCargo asks for the token and hands it to the provider. A token with full
access works; one with scopes needs packages:read to add private crates
and packages:write to publish and yank them.
The token can also come from the environment instead of cargo login,
as CARGO_REGISTRIES_ACME_TOKEN for a registry named acme (the name in
capitals, with - written _). The cargo:token provider reads it from
there, which is how workflows give it.
Publish
Section titled “Publish”Say in Cargo.toml where the crate is published and which repository it
comes from:
[package]name = "http-client"version = "0.3.1"edition = "2021"description = "Our HTTP client"license = "MIT"readme = "README.md"repository = "https://g1t.sh/acme/http-client"publish = ["acme"]cargo publish --registry acmeThe first publish makes the crate. When its repository is a g1t.sh
repository of the same workspace, or a repository is named like the crate
(a crate http_client is also matched to a repository http-client), it
is linked to that repository and has its visibility and roles: publishing needs Write on it.
Otherwise it is the workspace’s, private, and needs the workspace’s Write
base permission. See
who can see and publish a package.
publish = ["acme"] keeps the crate from being published to crates.io by
mistake, and lets cargo publish leave out --registry when it is the
only registry named.
A crate may depend on crates.io crates and on other crates of the workspace’s registry. The crate’s page on g1t.sh shows the README and description of its highest stable version.
Add a crate
Section titled “Add a crate”cargo add http-client --registry acmeThat writes the dependency with its registry into Cargo.toml:
[dependencies]http-client = { version = "0.3.1", registry = "acme" }Cargo.lock records each crate’s registry and the SHA-256 of its
.crate file, which g1t computes when the version is published.
cargo search --registry acme http lists the workspace’s crates you can
see whose names match.
Names and versions
Section titled “Names and versions”A crate’s name follows the crates.io rules: ASCII letters, digits, - and
_, starting with a letter, at most 64 characters. In a workspace, names
that differ only in case or in - against _ are one name: once
http-client is published, HTTP_Client is refused.
A version is published once. Publishing a version that is already there is
refused, as is one that differs from it only in build metadata (1.0.0+a
and 1.0.0+b), so bump version first.
cargo yank --registry acme http-client@0.3.1cargo yank --registry acme http-client@0.3.1 --undoA yanked version stays in the registry: projects whose Cargo.lock
names it still build, but Cargo no longer picks it for new lockfiles or
cargo update. Yanking needs what publishing does. The crate’s page marks
yanked versions, and someone with Admin on the linked repository (an
owner, for the workspace’s own crates) can delete a version there for
good.
Crate owners are not kept: who may publish a crate is decided by its
repository’s roles, or the workspace’s, so cargo owner answers with an
error that says so.
Private and public crates
Section titled “Private and public crates”A crate linked to a repository has the repository’s visibility; one of the workspace’s own is private until an owner makes it public on its page.
| The workspace’s crates | Without a token | With a token |
|---|---|---|
| All public | Cargo reads the index and downloads them. | The same; the token is sent to publish and yank. |
| Some private | The registry answers 401: Cargo needs a token for every crate in it, public ones too. |
Cargo sends the token with every request, and sees the crates the token’s owner may see. |
Cargo first asks for the registry’s config.json without a token. When
the registry answers 401, Cargo asks again with its token, and the
answer says "auth-required": true, so Cargo sends the token from then on.
A private crate you cannot see looks exactly like one that does not exist.
In workflows
Section titled “In workflows”A workflow’s G1T_TOKEN is the workspace’s own token for the run, and can
add and publish the workspace’s crates. A workflow runs no cargo login:
give Cargo the registry, its credential provider and the token in the
environment, each named for the registry:
jobs: publish: runs-on: ubuntu-latest env: CARGO_REGISTRIES_ACME_INDEX: sparse+https://g1t.sh/-/cargo/acme/index/ CARGO_REGISTRIES_ACME_CREDENTIAL_PROVIDER: cargo:token CARGO_REGISTRIES_ACME_TOKEN: ${{ secrets.G1T_TOKEN }} steps: - uses: actions/checkout@v4 - run: cargo test - run: cargo publish --registry acme| Variable | Is | Needed |
|---|---|---|
CARGO_REGISTRIES_ACME_INDEX |
The registry’s index, as index in .cargo/config.toml. |
When no .cargo/config.toml names the registry. |
CARGO_REGISTRIES_ACME_CREDENTIAL_PROVIDER |
cargo:token, as credential-provider in .cargo/config.toml. |
When no .cargo/config.toml names the provider. Without one, Cargo refuses a registry with private crates, even with the token in the environment. |
CARGO_REGISTRIES_ACME_TOKEN |
The token, for cargo:token to hand to the registry. |
Always: cargo publish sends it, and Cargo sends it to read a registry with private crates. |
With the project’s .cargo/config.toml from above
checked in, CARGO_REGISTRIES_ACME_TOKEN is all a workflow sets. The same
variables let cargo build and cargo test download the workspace’s
private crates.
A publish is one request with the .crate file inside it, and may hold at
most 100 MB. Without the g1t plan,
a workspace’s private packages may hold 500 MB and its public ones 10 GB,
as for container images.
A .crate file is stored once, by its content.
Errors
Section titled “Errors”| Error | Means |
|---|---|
401 |
No token, or a wrong or expired one. Run cargo login --registry acme with a g1t access token, or set CARGO_REGISTRIES_ACME_TOKEN. |
authenticated registries require a credential-provider to be configured |
The workspace has private crates, and Cargo has no provider for its token. Add credential-provider = "cargo:token" to the registry in .cargo/config.toml, or set CARGO_REGISTRIES_ACME_CREDENTIAL_PROVIDER=cargo:token. |
403 |
Signed in, but your role or your token’s scopes do not allow it, or the workspace is out of free package storage. The message says which. |
404 |
No such crate or version, or a private one you cannot see. |
400 |
The publish was refused: a name that is not valid or is taken, a version already published, or metadata Cargo did not send in full. The message says which. |
413 |
The publish is over 100 MB. Leave large files out with exclude or include in Cargo.toml, and check with cargo package --list. |