-
Notifications
You must be signed in to change notification settings - Fork 385
crate publishing workflow #755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
96952ee
6affcd3
f717d30
52849b1
4710c0d
556f9af
0759b3c
24b706a
11eee5b
b300f77
db5b6ed
b5fb444
d6d61f9
2da92af
7b31be4
d7b3e87
37f755c
21363c6
9b8611d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # Release Process | ||
|
|
||
| Publishing DiskANN crates to [crates.io](https://crates.io). | ||
|
|
||
| ## Overview | ||
|
|
||
| All workspace crates are published together with synchronized version numbers using `cargo publish --workspace`, which automatically resolves dependency order and waits for each crate to be indexed before publishing its dependents. The Rust toolchain version is read from [`rust-toolchain.toml`](../../rust-toolchain.toml). | ||
|
|
||
| Releases follow a pull-request workflow: bump the version on a branch, open a PR, let the dry-run check pass, merge, then tag the release via the GitHub UI. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| 1. **CRATES_IO_TOKEN Secret**: A crates.io API token configured as a GitHub repository secret named `CRATES_IO_TOKEN` with publish permissions for all DiskANN crates. | ||
| - Create a token: [crates.io/settings/tokens](https://crates.io/settings/tokens) | ||
| - Add the secret: Repository Settings → Secrets and variables → Actions → New repository secret | ||
|
|
||
| 2. **Maintainer Access**: Write access to the repository and owner/maintainer of all crates on crates.io. | ||
|
|
||
| ## Dry-Run Testing | ||
|
|
||
| A `cargo publish --workspace --dry-run` runs **automatically** as a pull-request check whenever `Cargo.toml` is changed. You can also trigger a dry-run manually: | ||
|
|
||
| ### Manual: GitHub Actions | ||
|
|
||
| 1. Navigate to: `https://github.com/microsoft/DiskANN/actions/workflows/publish.yml` | ||
| 2. Click **Run workflow**, select your branch, keep **dry-run = true** | ||
| 3. Watch the workflow — look for successful `cargo publish --workspace --dry-run` | ||
|
|
||
| ### Manual: Local | ||
|
|
||
| ```bash | ||
| cargo publish --locked --workspace --dry-run | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ### What Dry-Run Tests | ||
|
|
||
| - Crate metadata and packaging validation | ||
| - Dependency resolution and publish ordering | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - Build verification | ||
|
|
||
| ### What It Does NOT Test | ||
|
|
||
| - Actual publishing, registry token auth, upload reliability | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may want to mention what to do if the publish step fails. Basically, we either need to manually fix and publish the remaining crates, or fix the publish issue, bump the version number, and bump again (or if the fix doesn't change the versions that succeeded, then the remaining ones can be updated and pushed potentially in the same release). If the publishing fails part way through for networking issues, then we'll need to handle the remaining ones manually.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not certain of the behavior. Coudl it be that running the action again uploads missing crate? can we handle this when it happens? |
||
|
|
||
| ## Release Steps | ||
|
|
||
| 1. **Create a release branch** from `main`: | ||
|
|
||
| ```bash | ||
| git checkout main && git pull | ||
| git checkout -b release-0.46.0 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This conflicts with the tags in the PR description and the comments of the workflow yaml. I assume this one should be v0.46.0.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is 0.46.0 right? Perhaps I pushed after your comment? |
||
| ``` | ||
|
|
||
| 2. **Update version** in root `Cargo.toml`: | ||
|
|
||
| - Set `workspace.package.version`: | ||
|
|
||
| ```toml | ||
| [workspace.package] | ||
| version = "0.46.0" | ||
| ``` | ||
|
|
||
| - Update **all internal crate entries** under `[workspace.dependencies]` to match: | ||
|
|
||
| ```toml | ||
| diskann-wide = { path = "diskann-wide", version = "0.46.0" } | ||
| diskann-vector = { path = "diskann-vector", version = "0.46.0" } | ||
| # ... etc | ||
| ``` | ||
|
|
||
| Member crates inherit `workspace.package.version` via `version.workspace = true`, | ||
| but `[workspace.dependencies]` versions must be set explicitly (they're baked into | ||
| published manifests for crates.io consumers). | ||
|
|
||
| 3. **Update CHANGELOG** (if applicable). | ||
|
|
||
| 4. **Push and open a pull request** to `main`: | ||
|
|
||
| ```bash | ||
| git commit -am "Bump version to 0.46.0" | ||
| git push origin release-0.46.0 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tag wrong here as well.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, is the version syntax wrong or the concrete number wrong? this is just an example, right? |
||
| ``` | ||
|
|
||
| Open a PR on GitHub. The **Publish to crates.io / Dry-run publish test** check runs automatically. | ||
|
|
||
| 5. **Wait for checks** — the dry-run and CI must both pass before merge. | ||
|
|
||
| 6. **Merge the PR** into `main`. | ||
|
|
||
| 7. **Create a release** via the GitHub UI: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this not automatable?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean publish crate whenever a PR with new version is merged to main? Possibly. Being a bit conservative for now |
||
| - Go to **Releases → Draft a new release** | ||
| - Create a new tag `v0.46.0` targeting `main` | ||
| - Add release notes describing changes | ||
| - Click **Publish release** | ||
|
|
||
| Pushing the tag triggers the real publish workflow. | ||
|
|
||
| 8. **Verify** the published crates — confirm the new version appears in the output: | ||
|
|
||
| ```bash | ||
| cargo search diskann --limit 20 | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ## Pre-release Checklist | ||
|
|
||
| - [ ] All CI checks pass on the PR | ||
| - [ ] Version number is updated in `Cargo.toml` | ||
| - [ ] CHANGELOG is updated (if applicable) | ||
| - [ ] Documentation is up to date | ||
| - [ ] Breaking changes are clearly documented | ||
| - [ ] **Dry-run publish check passes on the PR** | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT license. | ||
|
|
||
| # Publishes all workspace crates to crates.io. | ||
| # | ||
| # Triggers: | ||
| # - push tag v{major}.{minor}.{patch} → real publish | ||
| # - pull_request touching Cargo.toml → automatic dry-run (pre-merge check) | ||
| # - workflow_dispatch → manual dry-run or real publish | ||
| # | ||
| # Requires CRATES_IO_TOKEN secret. Rust toolchain version is read from rust-toolchain.toml. | ||
|
|
||
| name: Publish to crates.io | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v[0-9]+.[0-9]+.[0-9]+' | ||
| pull_request: | ||
| branches: ["main"] | ||
| paths: | ||
| - 'Cargo.toml' | ||
| workflow_dispatch: | ||
| inputs: | ||
| dry_run: | ||
| description: 'Run in dry-run mode (test without actually publishing)' | ||
| required: false | ||
| default: 'true' | ||
| type: choice | ||
| options: | ||
| - 'true' | ||
| - 'false' | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | ||
| cancel-in-progress: true | ||
|
|
||
| env: | ||
| RUST_BACKTRACE: 1 | ||
|
|
||
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| publish: | ||
| name: >- | ||
| ${{ | ||
| (github.event_name == 'pull_request' || github.event.inputs.dry_run == 'true') | ||
| && 'Dry-run publish test' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do these strings evaluate as or do? I don't understand the test condition.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed unnecessary clauses |
||
| || 'Publish crates to crates.io' | ||
| }} | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| lfs: true | ||
|
|
||
| - name: Read Rust version from rust-toolchain.toml | ||
| id: rust-version | ||
| run: | | ||
| RUST_VERSION=$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml) | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| echo "channel=$RUST_VERSION" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Install Rust ${{ steps.rust-version.outputs.channel }} | ||
| uses: dtolnay/rust-toolchain@master | ||
| with: | ||
| toolchain: ${{ steps.rust-version.outputs.channel }} | ||
|
|
||
| - uses: Swatinem/rust-cache@v2 | ||
|
|
||
| - name: Prevent publish from non-main branch | ||
| if: >- | ||
| github.event_name == 'workflow_dispatch' | ||
| && github.event.inputs.dry_run != 'true' | ||
| && github.ref != 'refs/heads/main' | ||
| run: | | ||
| echo "::error::Live publishing is only allowed from main. Use dry-run for other branches." | ||
| exit 1 | ||
|
|
||
| - name: Verify version matches tag | ||
| if: github.event_name == 'push' | ||
| run: | | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| TAG_VERSION="${GITHUB_REF#refs/tags/v}" | ||
| CARGO_VERSION=$(grep -A 5 '^\[workspace\.package\]' Cargo.toml | grep 'version = ' | head -n1 | sed 's/.*"\(.*\)".*/\1/') | ||
| if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then | ||
| echo "::error::Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)" | ||
| exit 1 | ||
| fi | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| - name: Verify all crates use workspace version | ||
| run: | | ||
| bad_crates=() | ||
| for manifest in $(cargo metadata --no-deps --format-version 1 | jq -r '.packages[].manifest_path'); do | ||
| dir=$(dirname "$manifest") | ||
| name=$(basename "$dir") | ||
| if [ "$manifest" != "$(pwd)/Cargo.toml" ] && ! grep -qE 'version\s*=\s*\{\s*workspace\s*=\s*true\s*\}|version\.workspace\s*=\s*true' "$manifest"; then | ||
| bad_crates+=("$name") | ||
| fi | ||
| done | ||
| if [ ${#bad_crates[@]} -gt 0 ]; then | ||
| echo "::error::The following crates do not use version.workspace = true: ${bad_crates[*]}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Publish workspace crates | ||
| env: | ||
| CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} | ||
| run: | | ||
| DRY_RUN_FLAG="" | ||
| if [ "${{ github.event_name }}" = "pull_request" ] || [ "$DRY_RUN" = "true" ]; then | ||
| DRY_RUN_FLAG="--dry-run" | ||
| echo "🧪 DRY-RUN MODE" | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else | ||
| echo "📦 LIVE MODE - Publishing to crates.io" | ||
| fi | ||
| cargo publish --locked --workspace $DRY_RUN_FLAG | ||
harsha-simhadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.