diff --git a/justfile b/justfile index b5ca94d16..8115d5cad 100644 --- a/justfile +++ b/justfile @@ -3,6 +3,8 @@ alias c := check alias f := fmt alias t := test alias p := pre-push +alias vs := verify-standalone +alias vsa := verify-standalone-all _default: @just --list @@ -57,3 +59,76 @@ _test-testenv: # Run pre-push suite: format, check, and test pre-push: fmt check test + +# Verify that a crate can be built standalone without workspace dependencies +# This ensures the crate is publishable and doesn't accidentally depend on +# breaking changes from other workspace crates +verify-standalone crate *args="": + #!/usr/bin/env bash + set -euo pipefail + + echo "Verifying {{crate}} can build standalone..." + + # Package the crate (default: --no-verify, can be overridden with args) + cargo package -p {{crate}} --no-verify {{args}} + + # Find the packaged tarball + CRATE_VERSION=$(cargo metadata --format-version 1 --no-deps | jq -r ".packages[] | select(.name == \"{{crate}}\") | .version") + TARBALL="target/package/{{crate}}-${CRATE_VERSION}.crate" + + if [ ! -f "$TARBALL" ]; then + echo "Error: Could not find packaged tarball at $TARBALL" + exit 1 + fi + + # Create a temporary directory for unpacking + TEMP_DIR=$(mktemp -d) + trap "rm -rf $TEMP_DIR" EXIT + + # Unpack the tarball + tar -xzf "$TARBALL" -C "$TEMP_DIR" + + # Build the unpacked crate with --locked to ensure it uses registry dependencies + cd "$TEMP_DIR/{{crate}}-${CRATE_VERSION}" + + # Set temporary directories to avoid using workspace dependencies + export CARGO_HOME="$TEMP_DIR/.cargo" + export CARGO_TARGET_DIR="$TEMP_DIR/target" + + echo "Building {{crate}} in isolation..." + cargo build --locked + + echo "✅ {{crate}} builds successfully in isolation!" + +# Verify all publishable crates can be built standalone +verify-standalone-all *args="": + #!/usr/bin/env bash + set -euo pipefail + + # Get all workspace crates (excluding examples) + CRATES=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[] | select(.source == null and (.name | startswith("example_") | not)) | .name' | sort) + + echo "Verifying all publishable crates can build standalone..." + echo "Crates to verify:" + echo "$CRATES" | sed 's/^/ - /' + echo + + for crate in $CRATES; do + echo "=========================================" + echo "Verifying $crate..." + echo "=========================================" + + if ! just verify-standalone "$crate" {{args}}; then + echo "❌ $crate: FAILED" + echo "=========================================" + echo "❌ VERIFICATION FAILED for: $crate" + echo "=========================================" + exit 1 + fi + echo "✅ $crate: SUCCESS" + echo + done + + echo "=========================================" + echo "✅ All crates build successfully in isolation!" + echo "========================================="