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

Rust package readiness

RustFerry has six publishable crates. All versions come from workspace.package; a release must keep them identical.

OrderPackageRoleInternal prerequisites
1rustferry-coreConfiguration, validation, assets, process controlNone
1rustferryApplication runtime APINone
2rustferry-codegenProject, capability, and asset generationrustferry-core
3rustferry-appleApple generation and artifact backendrustferry-core, rustferry-codegen
3rustferry-androidDirect Android packaging backendrustferry-core, rustferry-codegen
4cargo-ferryPublic CLIAll backend/core/codegen crates

Wait for each prerequisite version to appear in the registry index before publishing the next group. The automated release workflow never publishes to crates.io.

Manifest contract

Every crate must declare its name, version, Rust version, description, repository, homepage, documentation URL, dual-license expression, README, keywords, categories, and an explicit include set. Internal path dependencies must also carry the exact release version so Cargo removes the path when it normalizes the package.

Each crate root links LICENSE-MIT and LICENSE-APACHE to the canonical workspace files and includes both names explicitly. Cargo dereferences those links into regular files in the portable archive. The archive scanner requires both members at the package root and verifies their exact SHA-256 digests.

The committed workspace Cargo.lock is the release lock. Use --locked for every gate. Generated package archives contain only their declared source, templates, tests, and embedded docs; they must not contain target/, signing material, absolute developer paths, or missing include_bytes!/include_str! inputs.

Package gates

Run from the repository root on a clean release revision:

cargo metadata --locked --no-deps --format-version 1
python3 scripts/check-release-contract.py
cargo package --workspace --locked --list
cargo package --workspace --locked
cargo publish --workspace --dry-run --locked --no-verify
python3 scripts/check-release-archives.py \
  --check-sources \
  --target-dir target/package-source-check \
  target/package/*.crate

cargo package --workspace verifies the normalized archives together, so unpublished internal dependencies resolve from the package set. The following publish --dry-run --no-verify repeats registry upload checks without compiling the same archives a second time. It performs no upload.

Inspect the produced archives before approving a draft:

find target/package -maxdepth 1 -name '*.crate' -print | sort
for archive in target/package/*.crate; do tar -tzf "$archive"; done

The manual draft-release workflow copies all six .crate files into one release assembly, adds the schema, VSIX, license bundle, release notes, and SHA-256 checksums, then uploads that assembly as a workflow artifact.

For the 2026-08-01 local candidate, archive/source/handshake validation passed for 6/6 crates, the package Python suite passed 19/19, and the release contract confirmed 17/17 exact internal dependency edges. The largest archive was 152.9 KiB, below the scanner’s 10 MiB compressed-size limit. These are package-gate results, not a crates.io publication. The full local workspace suite separately passed 258 Rust tests with 0 failures and 7 deliberate platform/hardware ignores.

Publish procedure

Publishing is a separate, protected manual operation. Run a complete dry-run, then publish one group at a time in the order above. Confirm each version with cargo search or the crates.io API before continuing. Do not use --no-verify for the real publish. Do not bump versions or publish from a dirty checkout.

After publication, install the CLI from the registry into an isolated Cargo root and generate/check a new project without a runtime-path environment override. This is the acceptance test for registry-based template resolution; workspace-path tests alone are insufficient.