From f605ebd7212861d5d15e2369884811602a90b56d Mon Sep 17 00:00:00 2001 From: devmaxxx Date: Mon, 19 Oct 2026 12:32:18 +0200 Subject: [PATCH] chore: publish the crate to crates.io The manifest gains readme, keywords and categories, and an include list that ships src/ plus the agent, bench and docs files src/ compiles in with include_str!, so the crate is 0.7 MB rather than near the 10 MB limit. release.yml gains a crates job that publishes the tag's source through crates.io trusted publishing after verify, skipping a version already on the registry. The runbook covers the first version by hand, which trusted publishing needs, and install.md and the README name cargo install --locked zerograph. --- .github/workflows/release.yml | 24 ++++++++++++++++++++++++ Cargo.toml | 20 ++++++++++++++++++++ README.md | 2 +- docs/bench/runbook.md | 13 ++++++++++++- docs/install.md | 10 +++++++++- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f785b365..e4efecfb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -128,3 +128,27 @@ jobs: - run: | v=${GITHUB_REF_NAME#v} if [ -n "$(npm view "zerograph@$v" version 2>/dev/null)" ]; then echo "zerograph@$v is published already"; else npm publish "dist/npm/zerograph-$v.tgz"; fi + # The crate is the tag's source, through crates.io's trusted publishing: the action trades this + # workflow's OIDC token for a token that lives for the run, so there is no registry secret to keep. + # Like npm's, trusted publishing can only be configured on a crate that exists, so the first + # version was published by hand (docs/bench/runbook.md). + crates: + # After `verify` for the same reason as npm: a version number on crates.io is never given back. + needs: [build, verify] + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.98.0 + - uses: rust-lang/crates-io-auth-action@v1 + id: auth + # A version already on the registry is skipped, so a rerun after a failure, or the tag of the + # version published by hand, publishes nothing rather than failing on the refusal. + - run: | + v=${GITHUB_REF_NAME#v} + code=$(curl -s -o /dev/null -w '%{http_code}' -A 'zerograph-release (github.com/devmaxxx/zerograph)' "https://crates.io/api/v1/crates/zerograph/$v") + if [ "$code" = 200 ]; then echo "zerograph@$v is published already"; else cargo publish --locked; fi + env: { CARGO_REGISTRY_TOKEN: "${{ steps.auth.outputs.token }}" } diff --git a/Cargo.toml b/Cargo.toml index 8e615030..d8dcf72b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,26 @@ rust-version = "1.98" description = "A project knowledge graph built and queried at zero API tokens" license = "MIT" repository = "https://github.com/devmaxxx/zerograph" +readme = "README.md" +keywords = ["knowledge-graph", "code-search", "mcp", "embeddings", "cli"] +categories = ["command-line-utilities", "development-tools"] +# The crate carries what the binary compiles in and nothing else: docs, bench history and test +# fixtures put it near crates.io's 10 MB limit. The docs and bench files named here are +# `include_str!`'d by src/, so a build from the published source needs them. +include = [ + "/src/**", + "/agent/hook.mjs", + "/agent/rule.txt", + "/agent/stanza.md", + "/agent/subagent.md", + "/agent/skill/*.md", + "/bench/cases.jsonl", + "/bench/cases.pin", + "/docs/embeddings.md", + "/docs/bench/2026-09-22-embedders-results.md", + "/README.md", + "/LICENSE", +] [dependencies] anyhow = "=1.0.104" diff --git a/README.md b/README.md index 57a0fa63..58c5c85d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ quoted in comments. It answers questions about that structure in a few lines of ## Get started ```bash -npm install -g zerograph # or: pnpm add -D zerograph +npm install -g zerograph # or: pnpm add -D zerograph, or: cargo install --locked zerograph echo .zerograph/ >> .gitignore # the graph is built per checkout zerograph build # first run downloads the embedding model zerograph ask cancellation policy # stays fresh with your edits diff --git a/docs/bench/runbook.md b/docs/bench/runbook.md index d81304e3..4c54cb6e 100644 --- a/docs/bench/runbook.md +++ b/docs/bench/runbook.md @@ -383,6 +383,16 @@ Eight steps, in order. Each one exists because skipping it once cost a release r Then on npmjs.com, the package's Settings → Trusted publishing: GitHub Actions, repository `devmaxxx/zerograph`, workflow `release.yml`. Once set up, this step is skipped. + crates.io's trusted publishing has the same rule, and its first version is the real one, from + the commit step 4 read, before the tag is pushed (`cargo login` once with a token from + crates.io → Account Settings → API Tokens, scope `publish-new`): + ```bash + git worktree add ../zerograph-crate $SHA && cd ../zerograph-crate && cargo publish --locked + ``` + Then on crates.io, the crate's Settings → Trusted Publishing: GitHub, owner `devmaxxx`, + repository `zerograph`, workflow `release.yml`. The tag's `crates` job finds that version + published and skips it; every later tag publishes from there. Once set up, this is skipped too. + 6. **Tag and push.** ```bash git tag v $SHA && gh auth switch --hostname github.com --user devmaxxx && git push origin v @@ -401,8 +411,9 @@ Eight steps, in order. Each one exists because skipping it once cost a release r ```bash gh api repos/devmaxxx/zerograph/releases/latest --jq .tag_name npm view zerograph@ version + cargo info zerograph@ --registry crates-io | grep '^version' ``` - The first prints the tag, the release carries three assets, and the second prints the version: a + The first prints the tag, the release carries three assets, and the others print the version: a release is done when someone else can install it, not when the tag exists. ## Post-run cleanup, if the run was not in a worktree diff --git a/docs/install.md b/docs/install.md index 968cfaf4..bad0284f 100644 --- a/docs/install.md +++ b/docs/install.md @@ -3,7 +3,8 @@ ```bash pnpm add -D zerograph # npm: prebuilt binary for macOS arm64, Linux x64 and Windows x64 npm install -g zerograph # or globally; pnpm add -g zerograph works the same -cargo install --path . # from source; Rust 1.98, pinned in rust-toolchain.toml +cargo install --locked zerograph # from crates.io, built on this machine; Rust 1.98 or later +cargo install --path . # from a checkout; Rust 1.98, pinned in rust-toolchain.toml ``` The session hooks `install-agent` writes run the `zerograph` on `PATH` and never one inside the @@ -24,6 +25,13 @@ for the unix ones, a zip holding `zerograph.exe` for Windows) and cut the npm pa same files (`.github/workflows/release.yml`, publishing through npm's trusted publishing, so each version carries a provenance attestation; `scripts/npm-pack.sh` packs the same tarball by hand). +The crates.io crate is the source of the same tag, published by the same workflow through crates.io's +trusted publishing. `--locked` builds against the `Cargo.lock` the release was tested with; without +it cargo resolves fresh versions within the manifest's pins. The build downloads ONNX Runtime for the +target, as a checkout build does, and needs a C compiler for the tree-sitter grammars (on Windows, +the MSVC build tools). A `cargo install` binary carries no attestation: what it runs is what this +machine compiled. + ## Verifying a download Each release binary is built by `.github/workflows/release.yml` on a GitHub runner, and that