ci(digstore-core): publish the library crate to crates.io - #22
Merged
Conversation
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 <noreply@anthropic.com>
Comment on lines
+36
to
+51
| 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: |
Comment on lines
+52
to
+103
| 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 }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TLDR
Publishes the
digstore-corelibrary crate to crates.io by adding crates.io packaging metadata + a dedicated, idempotent publish workflow. This is WU1 of #680 — the release-first predecessor that unblocks WU2 (dig-urn-resolver's own crates.io publish, a separate later lane). WU2 fails today becausedig-urn-resolvergit-depends ondigstore-coreand crates.io forbids git deps; publishingdigstore-coreby-version is the root fix.Refs #680 (NOT
Closes— WU2 is the dig-urn-resolver side, separate lane).What changed
crates/digstore-core/Cargo.toml— added crates.io-required/recommended[package]metadata:description,repository,readme,keywords,categories.licensealready inherited from the workspace (GPL-2.0-only). No dependency or code change.crates/digstore-core/README.md— new (referenced byreadme =), describes the crate + the.digformat-stability guarantee (§5.1) + features..github/workflows/publish-crate.yml— new publish workflow (test → package → skip-if-exists → publish).Cargo.toml— workspace version0.13.3→0.13.4.Packaging-only: no code/format behavior change. Per §5.1 the store-format read-crypto and
.digformat are untouched.Trigger design — why it won't collide with nightlies
digstore is a nightlies repo (§3.6): binaries release via
nightly-release.ymlon a cron/dispatch, and thev*tag fires the binary build (release.yml). Hooking a crate publish tov*or the cron would re-attempt adigstore-corepublish on every binary release; crates.io rejects duplicate versions → red runs every night.Instead the crate publish rides its own tag namespace
digstore-core-v*(e.g.digstore-core-v0.13.4) plusworkflow_dispatch, and is idempotent: it queries crates.io for the resolved version and no-ops if already published (skip-if-exists, mirroring the nightlies stable skip-if-tagged posture). A re-run or stray duplicate tag never fails red.Publish flow after merge: bump the workspace version → merge → push
digstore-core-vX.Y.Z(or dispatch the workflow) → publishes that version.Dry-run proof
cargo publish -p digstore-core --dry-run --allow-dirty:Packages + verifies cleanly: all deps resolve from crates.io, metadata complete, no path/git dep leak (digstore-core has no path/git deps).
Token status
CARGO_REGISTRY_TOKENis NOT a repo secret onDIG-Network/digstore, and is not onDIG-Network/chia-queryeither — yet chia-query publishes to crates.io, so it is an org-level secret available to org repos (org secrets propagate unless restricted). The workflow referencessecrets.CARGO_REGISTRY_TOKENand fails with a clear error if absent. Action for orchestrator/user: confirm the orgCARGO_REGISTRY_TOKENis scoped to includedigstore(or add it) before the first real publish.SemVer bump rationale
Patch
0.13.3 → 0.13.4:ci/packaging-only, no public API or behavior change (§2.4). Satisfies the version-increment gate (reads[workspace.package].version), and becomes digstore-core's first published version (it inheritsversion.workspace = true).Co-Authored-By: Claude noreply@anthropic.com