max / makeover-touch
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+43 insertions,
-0 deletions
| @@ -1,0 +1,43 @@ | |||
| 1 | + | // Publish this crate to crates.io. | |
| 2 | + | // | |
| 3 | + | // A library has no per-platform artifact, so this is the whole release: one | |
| 4 | + | // recipe, run on whichever host the manifest names. | |
| 5 | + | // | |
| 6 | + | // The preflight step is the point of routing this through Bento rather than | |
| 7 | + | // running `cargo publish` by hand. A crates.io version can be yanked but never | |
| 8 | + | // edited, so a wrong repository URL, a missing license or a duplicate version | |
| 9 | + | // is permanent the moment it uploads. | |
| 10 | + | ||
| 11 | + | let h = build_host(); | |
| 12 | + | let r = repo(); | |
| 13 | + | let v = version(); | |
| 14 | + | ||
| 15 | + | // No pull here. The runner's release preflight has already fetched and run | |
| 16 | + | // `git checkout v<version>` on every host, then compared `rev-parse HEAD` | |
| 17 | + | // across them, so a release cannot be built from two different commits. That | |
| 18 | + | // leaves the checkout on the tag, detached; pulling would move it onto the | |
| 19 | + | // branch tip and publish something other than what was tagged. | |
| 20 | + | // | |
| 21 | + | // So this step asserts the pin instead of re-doing it: HEAD must be exactly a | |
| 22 | + | // tag, or the release is not coming from where it claims. | |
| 23 | + | step("checkout"); | |
| 24 | + | sh_ok(h, "cd " + r + " && git describe --exact-match --tags HEAD"); | |
| 25 | + | ||
| 26 | + | // Gate: nothing reaches crates.io from code that fails clippy or its tests. | |
| 27 | + | // This is the last point at which a break is still cheap. | |
| 28 | + | step("prebuild"); | |
| 29 | + | sh_ok(h, "cd " + r + " && cargo clippy --workspace --all-targets " + feature_flags() + " -- -D warnings"); | |
| 30 | + | sh_ok(h, "cd " + r + " && cargo test --workspace " + feature_flags()); | |
| 31 | + | ||
| 32 | + | step("verify"); | |
| 33 | + | // Credentials are checked here and deliberately not passed through Bento: the | |
| 34 | + | // token stays in cargo's own 0600 store on the publishing host, where cargo | |
| 35 | + | // finds it. Handing it to a shell command would put it in the process list for | |
| 36 | + | // the length of the upload, and ops-exec renders env pairs into the shell line. | |
| 37 | + | // Aborts the run with the specific problems if anything is wrong. | |
| 38 | + | log(crate_preflight()); | |
| 39 | + | sh_ok(h, "cd " + r + " && cargo publish --dry-run " + feature_flags()); | |
| 40 | + | ||
| 41 | + | step("publish"); | |
| 42 | + | sh_ok(h, "cd " + r + " && cargo publish " + feature_flags()); | |
| 43 | + | log("published " + v + " to crates.io"); |