Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/publish-crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
environment: crates.io
permissions:
contents: write # to push the crates-v* tag
id-token: write # to mint a short-lived crates.io token over OIDC
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -62,18 +63,21 @@ jobs:
- name: Package and verify crates
run: cargo package --locked -p dagron-core -p dagron-ui

# Exchanges this job's OIDC identity for a token scoped to these crates
# and valid for this run only. Requires a trusted publisher configured on
# each crate for ByteVeda/dagron + publish-crates.yml + environment
# crates.io. No registry token is stored in the repository.
- name: Authenticate to crates.io
id: auth
uses: rust-lang/crates-io-auth-action@v1

- name: Publish crates
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail

if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
echo "::error::CARGO_TOKEN is not set in the 'crates.io' environment"
exit 1
fi

# Re-running a release must be a no-op for versions already up.
already_published() {
local crate=$1 code
Expand Down
30 changes: 15 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,21 +159,21 @@ unsupported platforms build from, and a green wheel job proves nothing about it.

### Registry credentials

Each workflow runs in a GitHub environment that holds its own credential, so
neither is reachable from an ordinary PR build.

- **PyPI** — the `pypi` environment, using OIDC Trusted Publishing. No stored
token.
- **crates.io** — the `crates.io` environment, using a `CARGO_TOKEN` secret
(a crates.io API token with publish scope for `dagron-core` and
`dagron-ui`).

crates.io also supports OIDC Trusted Publishing, which would remove the stored
token. It can only be configured for a crate that already exists, so it is a
worthwhile follow-up once the first version of each crate is published: add a
trusted publisher on each crate's settings page pointing at `ByteVeda/dagron` /
`publish-crates.yml` / environment `crates.io`, then swap the `Publish crates`
step over to `rust-lang/crates-io-auth-action` and drop the secret.
Both registries use OIDC Trusted Publishing. **No registry token is stored in
the repository**, so there is nothing to leak or rotate: each job exchanges its
own OIDC identity for a credential valid only for that run.

- **PyPI** — the `pypi` environment, trusted publisher for `publish.yml`.
- **crates.io** — the `crates.io` environment. Each of `dagron-core` and
`dagron-ui` needs a trusted publisher on its crates.io settings page
pointing at `ByteVeda/dagron` / `publish-crates.yml` / environment
`crates.io`. A crate with none configured fails to publish — the trust is
per crate, not per repository.

Both crates should also have **Require trusted publishing for all new
versions** enabled, which makes crates.io reject API tokens outright. Note
that this closes the manual `cargo publish` break-glass path too: with it on,
a release can only go out through this workflow.

## Project Structure

Expand Down