diff --git a/.github/workflows/publish-to-crates-io.yml b/.github/workflows/publish-to-crates-io.yml index fcba757a1..6a09e59cb 100644 --- a/.github/workflows/publish-to-crates-io.yml +++ b/.github/workflows/publish-to-crates-io.yml @@ -82,17 +82,20 @@ jobs: - name: Build publish helper run: rustc --edition 2024 scripts/publish.rs -o publish - # NOTE: the historical `./publish verify` step was removed in v0.7.0 - # because `cargo publish --dry-run -p ` resolves dependencies - # through the public crates.io index — so dependent workspace crates - # always fail until their synth-* deps are already on the registry - # at the new version (chicken-and-egg for any first publish of a new - # version). The actual `cargo publish` performs the same metadata - # validation before upload, and `./publish publish` has a 10-attempt - # retry loop with a 40s sleep that rides out registry index - # propagation. The verify step is recoverable as `cargo package` - # (which uses path deps) if a fail-fast metadata check is needed — - # tracked as a follow-up. + # Pre-flight fail-fast (#146): `./publish verify` now runs `cargo package` + # per crate, NOT `cargo publish --dry-run`. `--dry-run` resolved deps + # through the public crates.io index, so dependent workspace crates always + # failed until their synth-* deps were already on the registry at the new + # version (the chicken-and-egg that sank the v0.7.0 step, dropped in #144). + # `cargo package` resolves through path deps and builds each `.crate` + # end-to-end, catching broken metadata / missing files / compile errors + # before any upload. (`publish = false` crates like synth-abi are not in + # CRATES_TO_PUBLISH, so the synth-wit-version quirk in #146 is not hit.) + - name: Verify packaging (cargo package, no chicken-and-egg) + run: ./publish verify + + # `./publish publish` has a 10-attempt retry loop with a 40s sleep that + # rides out registry index propagation between dependent crates. - name: Publish workspace to crates.io run: ./publish publish env: diff --git a/scripts/publish.rs b/scripts/publish.rs index 0ad24c05b..dcac8620f 100644 --- a/scripts/publish.rs +++ b/scripts/publish.rs @@ -1,7 +1,7 @@ //! Helper script for publishing the synth workspace to crates.io. //! //! Modes: -//! ./publish verify — `cargo publish --dry-run` every publishable crate +//! ./publish verify — `cargo package` every publishable crate (#146) //! in dependency order, fail on first error. //! ./publish publish — `cargo publish` every publishable crate in //! dependency order; retries up to 10 times to @@ -102,15 +102,23 @@ fn read_workspace_version() -> String { } fn verify(crates: &[Krate]) { + // #146: use `cargo package` rather than `cargo publish --dry-run`. + // `--dry-run` resolves every workspace dep against crates.io, so for a + // first publish of any new version the dependents always fail with the + // chicken-and-egg "dep not yet published" error (this sank the v0.7.0 + // verify step, dropped in PR #144). `cargo package` resolves through the + // local path deps, builds the `.crate` end-to-end, and still catches the + // surface a pre-flight check should: missing README/license, bad + // include/exclude, broken metadata, and code that doesn't compile. let mut failed = Vec::new(); for k in crates { - println!("--- cargo publish --dry-run -p {} ---", k.name); + println!("--- cargo package -p {} ---", k.name); let status = Command::new("cargo") - .args(["publish", "--dry-run", "-p", &k.name]) + .args(["package", "-p", &k.name]) .status() .expect("invoke cargo"); if !status.success() { - println!("FAIL: {} dry-run failed: {status}", k.name); + println!("FAIL: {} package failed: {status}", k.name); failed.push(k.name.clone()); } } @@ -118,7 +126,7 @@ fn verify(crates: &[Krate]) { eprintln!("\nverify failed for: {}", failed.join(", ")); std::process::exit(1); } - println!("\nAll {} crates passed cargo publish --dry-run.", crates.len()); + println!("\nAll {} crates passed cargo package.", crates.len()); } fn publish_all(mut crates: Vec) { @@ -136,7 +144,11 @@ fn publish_all(mut crates: Vec) { } eprintln!( "\nstill failing after 10 attempts: {}", - crates.iter().map(|k| k.name.as_str()).collect::>().join(", ") + crates + .iter() + .map(|k| k.name.as_str()) + .collect::>() + .join(", ") ); std::process::exit(1); } @@ -180,4 +192,3 @@ fn already_published(name: &str, version: &str) -> bool { _ => false, } } -