Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Releasing to crates.io

Step-by-step guide for publishing readstat-rs crates to crates.io.

Quick Reference

# 0. Merge the release PR, then pull main
git checkout main && git pull origin main

# 1. Run all pre-publish checks
./scripts/release-check.sh        # Linux/macOS
.\scripts\release-check.ps1       # Windows

# 2. Bump versions (updates Cargo.toml files, ARCHITECTURE.md, creates commit + tag)
cargo release minor -p readstat -p readstat-cli --dry-run   # preview first
cargo release minor -p readstat -p readstat-cli             # apply

# 3. Review the bump commit and tag, then push to trigger CI release builds
git push origin main --follow-tags

# 4. After CI builds the release artifacts, publish to crates.io:
#    Switch vendor dirs from submodules to copied files
./scripts/vendor.sh prepare       # Linux/macOS
.\scripts\vendor.ps1 prepare      # Windows

#    Publish (in dependency order)
cargo publish -p readstat-iconv-sys
cargo publish -p readstat-sys
cargo publish -p readstat
cargo publish -p readstat-cli

#    Restore submodules after publishing
./scripts/vendor.sh restore       # Linux/macOS
.\scripts\vendor.ps1 restore      # Windows

Install cargo-release once: cargo install cargo-release


Pre-Release Checklist

0. Check for Dependency Updates

./scripts/check-updates.sh              # report only (Linux/macOS)
./scripts/check-updates.sh --apply      # update safe deps in Cargo.lock
.\scripts\check-updates.ps1             # report only (Windows)
.\scripts\check-updates.ps1 -Apply      # update safe deps in Cargo.lock

This queries crates.io for outdated dependencies and their publish dates. Updates published less than 7 days ago (configurable via QUARANTINE_DAYS env var or -QuarantineDays parameter) are blocked to reduce supply chain risk.

The --apply / -Apply flag runs cargo update -p <crate> for each safe dependency, updating Cargo.lock within semver-compatible ranges. Major version bumps that require Cargo.toml edits are still manual.

1. Version Bumps

Use cargo-release (cargo install cargo-release). It updates all Cargo.toml version and dependency fields, substitutes the version strings in docs/ARCHITECTURE.md, and creates a single version-bump commit plus a git tag.

# Preview what will change (no files are modified)
cargo release minor -p readstat -p readstat-cli --dry-run

# Apply — updates Cargo.toml files, docs/ARCHITECTURE.md, commits, creates tag
cargo release minor -p readstat -p readstat-cli

Use patch / minor / major as appropriate. After running, verify the diff looks right, then push: git push origin main --follow-tags.

Version conventions:

  • readstat and readstat-cli share the same version (e.g. 0.21.0) — always bump together
  • readstat-sys and readstat-iconv-sys share the same version (e.g. 0.3.0)
  • Bump sys crates only when the vendored C library or bindings change: cargo release patch -p readstat-sys -p readstat-iconv-sys

2. Update CHANGELOG.md

Add an entry for the new version:

## [X.Y.Z] - YYYY-MM-DD

### Added
- ...

### Changed
- ...

### Fixed
- ...

3. Run Automated Checks

./scripts/release-check.sh

This runs:

  • cargo fmt --all -- --check — formatting
  • cargo clippy --workspace — linting
  • readstat-wasm fmt and clippy (excluded from workspace, checked separately)
  • cargo test --workspace — all tests
  • cargo doc --workspace --no-deps — documentation build
  • cargo deny check — license and security audit (if installed)
  • Version consistency checks
  • CHANGELOG entry check
  • cargo package dry-run for each publishable crate

Fix any failures before proceeding.

4. Manual Checks

  • README.md is up to date
  • Documentation reflects any API changes
  • Architecture docs (docs/ARCHITECTURE.md) are current
  • mdbook builds cleanly: ./scripts/build-book.sh
  • readstat-wasm builds and exports are up to date (excluded from workspace; not published to crates.io)

Vendor Preparation

The readstat-sys and readstat-iconv-sys crates vendor C source code from git submodules. cargo publish cannot include git submodule contents, so the files must be copied as regular files before publishing.

Switch to publish mode

./scripts/vendor.sh prepare       # Linux/macOS
.\scripts\vendor.ps1 prepare      # Windows

This:

  1. Records submodule commit hashes in vendor-lock.txt
  2. Copies only the files needed for building (matching Cargo.toml include patterns)
  3. Deinitializes the git submodules
  4. Places the copied files in the vendor directories

Verify package contents

cargo package --list -p readstat-sys --allow-dirty
cargo package --list -p readstat-iconv-sys --allow-dirty

Publishing

Crates must be published in dependency order. Wait for each crate to appear on the crates.io index before publishing the next one.

# 1. No crate dependencies
cargo publish -p readstat-iconv-sys

# 2. Depends on readstat-iconv-sys (Windows only)
cargo publish -p readstat-sys

# 3. Depends on readstat-sys
cargo publish -p readstat

# 4. Depends on readstat
cargo publish -p readstat-cli

Note: There may be a delay (30 seconds to a few minutes) between publishing a crate and it appearing in the index. If cargo publish fails with a dependency resolution error, wait and retry.


Post-Publish

1. Restore submodules

./scripts/vendor.sh restore       # Linux/macOS
.\scripts\vendor.ps1 restore      # Windows

2. Verify crates.io

Each published crate appears on crates.io within a few minutes:

  • https://crates.io/crates/readstat
  • https://crates.io/crates/readstat-cli
  • https://crates.io/crates/readstat-sys
  • https://crates.io/crates/readstat-iconv-sys

3. Verify docs.rs

docs.rs automatically builds documentation for every crate published to crates.io — no separate action is needed. The build is triggered by the crates.io publish and typically completes within 15–30 minutes.

The [package.metadata.docs.rs] section in crates/readstat/Cargo.toml instructs docs.rs to build with all features enabled and the docsrs cfg flag set, which causes feature-gated items to show their #[cfg(feature = "...")] badges.

Check build status and browse the rendered docs at:

  • https://docs.rs/readstat (build log: https://docs.rs/crate/readstat/latest/builds)

4. Verify the GitHub release

The tag push (step 3 of the Pre-Release Checklist above) already triggered CI to build platform binaries and create the GitHub Release. Confirm everything looks right on the Releases page.

5. Clean up

  • Remove vendor-lock.txt (or commit it for reference)

Troubleshooting

cargo publish fails with “no matching package found”

The dependency crate hasn’t appeared in the index yet. Wait 30-60 seconds and retry.

cargo package includes too many files

Check the include field in the crate’s Cargo.toml. Run cargo package --list to see exactly what will be included.

Vendor files missing after vendor.sh restore

Run git submodule update --init --recursive to re-initialize.

Build fails after switching vendor modes

Clean the build cache: cargo clean then rebuild.