From 3ee2e84671a7a4f1520b121c2e48e4d52a5eb528 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 16 Jul 2026 10:13:33 -0700 Subject: [PATCH] ci(digstore-core): publish the library crate to crates.io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add crates.io packaging metadata to `digstore-core` (description, repository, readme, keywords, categories; license already inherited GPL-2.0-only) and a dedicated publish workflow so downstream crates (dig-urn-resolver, #680 WU2) can depend on it BY VERSION instead of via a git dependency crates.io forbids. The publish rides its OWN tag namespace `digstore-core-v*` (plus dispatch), NOT the `v*` binary-release tag or the nightly cron, and is idempotent (skip-if-already-published) so it never re-attempts a duplicate version. digstore-core has no path/git deps; `cargo publish -p digstore-core --dry-run` packages and verifies cleanly. Packaging-only — no code/format behavior change (§5.1 store-format read-crypto unchanged). Bump workspace version 0.13.3 -> 0.13.4 (patch) to satisfy the version-increment gate; digstore-core inherits it as its published version. Refs #680 Co-Authored-By: Claude --- .github/workflows/publish-crate.yml | 103 ++++++++++++++++++++++++++++ Cargo.lock | 10 +-- Cargo.toml | 2 +- crates/digstore-core/Cargo.toml | 5 ++ crates/digstore-core/README.md | 34 +++++++++ 5 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/publish-crate.yml create mode 100644 crates/digstore-core/README.md diff --git a/.github/workflows/publish-crate.yml b/.github/workflows/publish-crate.yml new file mode 100644 index 00000000..e4bbb99c --- /dev/null +++ b/.github/workflows/publish-crate.yml @@ -0,0 +1,103 @@ +# ───────────────────────────────────────────────────────────────────────────────────────────── +# Publish the `digstore-core` LIBRARY crate to crates.io (dig_ecosystem #680, WU1). +# +# `digstore-core` is the store-format read-crypto crate downstream crates (e.g. dig-urn-resolver) +# want to depend on BY VERSION — crates.io forbids the git deps they use today, so the root fix is +# to publish digstore-core by-version. This crate has NO path/git dependencies (all deps are +# crates.io-versioned), so it publishes standalone. +# +# TRIGGER — deliberately NOT the `v*` tag and NOT the nightly cron: +# • `v*` tags fire the BINARY release (release.yml) and are cut by nightly-release.yml. Reusing +# `v*` here would re-attempt a crate publish on every binary release; crates.io rejects a +# duplicate version, spamming red runs. So the crate publish rides its OWN tag namespace, +# `digstore-core-v*` (e.g. `digstore-core-v0.13.4`), plus manual `workflow_dispatch`. +# • The publish is IDEMPOTENT: it queries crates.io for the version first and NO-OPS if that +# version is already published (skip-if-exists, mirroring the nightlies stable skip-if-tagged +# posture), so a re-run or an accidental duplicate tag never fails red. +# +# The version published is the workspace version (digstore-core inherits `version.workspace = true`), +# so bump the workspace `[workspace.package].version`, merge, then push `digstore-core-vX.Y.Z` +# (or run this workflow via dispatch) to publish that version. +# ───────────────────────────────────────────────────────────────────────────────────────────── +name: Publish digstore-core to crates.io + +on: + push: + tags: + - 'digstore-core-v*' + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + CRATE: digstore-core + +jobs: + test: + name: Test digstore-core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Check formatting + run: cargo fmt -p digstore-core -- --check + - name: Clippy (warnings are errors) + run: cargo clippy -p digstore-core --all-features -- -D warnings + - name: Run tests + run: cargo test -p digstore-core --all-features + - name: Check documentation + run: cargo doc -p digstore-core --no-deps --all-features + + publish: + name: Publish to crates.io + runs-on: ubuntu-latest + needs: test + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + # Package first — proves metadata is complete and no path/git dep leaks, without publishing. + - name: Package (dry check) + run: cargo package -p digstore-core --allow-dirty + + # Read the version cargo will publish (the resolved workspace version). + - name: Resolve crate version + id: ver + run: | + V=$(cargo metadata --no-deps --format-version 1 \ + | python3 -c 'import sys,json; d=json.load(sys.stdin); print(next(p["version"] for p in d["packages"] if p["name"]=="digstore-core"))') + echo "version=$V" >> "$GITHUB_OUTPUT" + echo "digstore-core version to publish: $V" + + # Skip-if-exists: crates.io rejects duplicate versions, so a re-run / stray tag must NO-OP, + # never fail red. Query the crate's versions and stop cleanly if this version is already up. + - name: Skip if version already published + id: exists + run: | + V="${{ steps.ver.outputs.version }}" + # crates.io requires a descriptive User-Agent; 404 => crate not yet published at all. + BODY=$(curl -sS -A "dig-ecosystem-ci (help@dig.net)" \ + "https://crates.io/api/v1/crates/digstore-core/versions" || echo '{}') + if echo "$BODY" | python3 -c 'import sys,json; d=json.load(sys.stdin); vs=[v["num"] for v in d.get("versions",[])]; sys.exit(0 if sys.argv[1] in vs else 1)' "$V"; then + echo "digstore-core@$V already on crates.io — skipping publish (no-op)." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "digstore-core@$V not on crates.io — will publish." + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check CARGO_REGISTRY_TOKEN is available + if: steps.exists.outputs.skip == 'false' + run: | + if [ -z "${{ secrets.CARGO_REGISTRY_TOKEN }}" ]; then + echo "::error::CARGO_REGISTRY_TOKEN is not available (repo or org secret)." + echo "Add a crates.io API token as CARGO_REGISTRY_TOKEN (org secret preferred) and re-run." + exit 1 + fi + + - name: Publish to crates.io + if: steps.exists.outputs.skip == 'false' + run: cargo publish -p digstore-core --allow-dirty --token "$CARGO_REGISTRY_TOKEN" + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index 83c546f0..58f5f94e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2289,7 +2289,7 @@ dependencies = [ [[package]] name = "digstore-chain" -version = "0.13.3" +version = "0.13.4" dependencies = [ "aes-gcm", "anyhow", @@ -2327,7 +2327,7 @@ dependencies = [ [[package]] name = "digstore-chunker" -version = "0.13.3" +version = "0.13.4" dependencies = [ "digstore-core", "hex", @@ -2337,7 +2337,7 @@ dependencies = [ [[package]] name = "digstore-cli" -version = "0.13.3" +version = "0.13.4" dependencies = [ "anstream 0.6.21", "anstyle", @@ -2403,7 +2403,7 @@ dependencies = [ [[package]] name = "digstore-core" -version = "0.13.3" +version = "0.13.4" dependencies = [ "aes-gcm-siv", "hex", @@ -2500,7 +2500,7 @@ dependencies = [ [[package]] name = "digstore-remote" -version = "0.13.3" +version = "0.13.4" dependencies = [ "async-trait", "axum", diff --git a/Cargo.toml b/Cargo.toml index 1fcccc61..599849b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ exclude = ["crates/digstore-prover/guest", "crates/dig-client-wasm"] [workspace.package] edition = "2021" -version = "0.13.3" +version = "0.13.4" license = "GPL-2.0-only" [workspace.dependencies] diff --git a/crates/digstore-core/Cargo.toml b/crates/digstore-core/Cargo.toml index 4f63b16b..f46142dc 100644 --- a/crates/digstore-core/Cargo.toml +++ b/crates/digstore-core/Cargo.toml @@ -3,6 +3,11 @@ name = "digstore-core" version.workspace = true edition.workspace = true license.workspace = true +description = "Core read-crypto and format primitives for the DIG Network store (.dig) format: capsules, manifests, merkle proofs, URN grammar, and the AES-256-GCM-SIV chunk seal." +repository = "https://github.com/DIG-Network/digstore" +readme = "README.md" +keywords = ["dig", "chia", "content-addressed", "merkle", "storage"] +categories = ["cryptography", "encoding", "data-structures"] [lib] name = "digstore_core" diff --git a/crates/digstore-core/README.md b/crates/digstore-core/README.md new file mode 100644 index 00000000..70977973 --- /dev/null +++ b/crates/digstore-core/README.md @@ -0,0 +1,34 @@ +# digstore-core + +Core read-crypto and format primitives for the [DIG Network](https://dig.net) store +(`.dig`) format — the `no_std`-friendly, wasm-clean foundation every DIG layer +(producer, host, and in-browser verifier) shares. + +It defines the on-the-wire building blocks of a `.dig` capsule and the symmetric +read-crypto used to seal and open its chunks: + +- **Capsules & manifests** (`capsule`, `manifest`, `public_manifest`) — the + content-addressed store layout and its serialized shape. +- **Merkle proofs** (`merkle`) — inclusion proofs over capsule content. +- **URN grammar** (`urn`, `urn_grammar`) — parsing and canonicalizing DIG URNs. +- **Read-crypto** (`crypto`) — the AES-256-GCM-SIV chunk seal and HKDF content-key + derivation, with `aes-gcm-siv`'s RNG-pulling defaults disabled so the crate stays + wasm-clean (encryption runs under a fixed nonce, no randomness required). +- **Codec, hashing, and error types** (`codec`, `hash`, `error`, `bytes`). + +## Format stability + +The `.dig` format is a permanent, on-chain-anchored artifact: published content stays +readable forever. Changes to this crate's format types are **additive and backwards +compatible** — a newer reader decodes every older `.dig` byte-identically. + +## Features + +- `std` (default) — enable `std` on the underlying dependencies. +- `serde` (default) — derive `serde` on the public types. + +Disable default features (`default-features = false`) for a `no_std`, wasm-clean build. + +## License + +GPL-2.0-only. See [LICENSE](https://github.com/DIG-Network/digstore/blob/main/LICENSE).