fix(ci): revive Rust CI — it had never run (60/60 startup failures) - #358
Merged
Conversation
`.github/workflows/rust-ci.yml` failed 60 consecutive runs, every one at 0s with zero jobs and no logs, between 2026-06-27 and 2026-07-27. That is a startup failure: GitHub rejected the file before scheduling anything. Found via the workflow-name fallback: GitHub reported this workflow's name as `.github/workflows/rust-ci.yml` (its path) rather than the declared `Rust CI`, which is what it does when a file has never been successfully parsed. Every other workflow in this repo resolves its declared name. Impact: `cargo build` and `cargo test` live only in this workflow, so the Rust implementation — 70 source files — had no build or test gate for a month while the board showed 13/14 green. The `wasm-validate` job that guards against invalid emitted wasm (cf. #348) was equally dead. Cause: `if: hashFiles('Cargo.toml') != ''` used as a *job-level* conditional on both local jobs. Job-level `if:` is evaluated server-side before any checkout, so hashFiles() has no workspace. The estate reusable's own header calls this out as a recurring failure mode, and solves it properly with a `detect` job whose output gates the rest. Ruled out first, so the next reader need not repeat it: encoding/CRLF/BOM (clean — the only non-ASCII is an em-dash in a comment), YAML validity (parses), all three pinned action SHAs (resolve), and caller-vs-reusable permissions (both exactly `contents: read`). The guard was redundant regardless: this repo unconditionally has a Cargo.toml. Also salvaged from uncommitted sweep debris, keeping only what is useful: - .editorconfig: adds per-language indent widths (rust/zig 4, ada 3, Justfile 4) while RESTORING the SPDX header and dropping the sweep's rebrand of this file to "RSR-template-repo" (a template self-name leak). - .gitignore: adds build/tooling artefact patterns, minus the sweep's `.claude/` and `.editorconfig` entries — both are tracked here, so ignoring them would hide real changes from `git status`. Verified no tracked file is newly ignored. Discarded from the same debris: a `guix.scm` clobbered to identify as `squisher-corpus` (and relicensed to PMPL-1.0-or-later), a deletion of `.tool-versions` (which pins coq 8.18.0 / ocaml 5.4.1), a `.gitattributes` regression dropping *.zig and *.a2ml rules, and commit 55dbd3b, which replaced a valid CodeQL pin with 29b1f65c — a SHA that does not exist (HTTP 422) and would have taken the currently-green CodeQL gate down. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ough Direct consequence of the previous commit. With Rust CI reviving, the `cargo fmt --all -- --check` step ran for the first time since 2026-06-27 and failed immediately: 24 files had drifted out of rustfmt shape while nothing was checking them. This is purely mechanical `cargo fmt --all` output — no semantic edits. `cargo check --locked --all-targets` was already passing in the same CI job, so the drift was cosmetic, but it was enough to keep the revived gate red. Verified locally with rustfmt 1.9.0-stable: `cargo fmt --all -- --check` is clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hyperpolymath
marked this pull request as ready for review
July 27, 2026 18:19
hyperpolymath
added a commit
that referenced
this pull request
Jul 27, 2026
## Why main is currently red PR #358 revived Rust CI. It merged **before** this commit landed on the branch, so main now has a *working* Rust CI that immediately fails its `Cargo check + clippy + fmt` step. That is not a regression — it is the gate doing its job for the first time since 2026-06-27. This PR is the backlog it found. Current state of the revived gate on main (`d7f1b49`): ``` success wasm-tools validate (emitted modules) success Cargo build + test (ephapax-cli, --no-default-features) success rust-ci / Detect Cargo.toml failure rust-ci / Cargo check + clippy + fmt <-- this PR ``` ## What this fixes `cargo clippy --all-targets -- -D warnings` failed crate after crate. All resolved; it now exits 0. **Mechanical, behaviour-preserving:** | Lint | Fix | |---|---| | `derivable_impls` | `impl Default for Visibility` → `#[derive(Default)]` + `#[default]` | | `manual_try_fold` ×2 | `.fold(Ok(acc), ..)` → `.try_fold(acc, ..)` in the surface and core parsers' statement-sequence desugaring | | `collapsible_if` ×2, `match_like_matches_macro` | via `cargo clippy --fix` | | `ptr_arg` | `&PathBuf` → `&Path` in two `ephapax-cli` signatures | | `unnecessary_unsafe` | removed an **empty** `unsafe {}` block wrapping only comments in a placeholder test | That last one is worth a second look in a language whose entire thesis is memory safety: `ephapax-runtime::list::tests::test_list_new` contained `unsafe { /* comments only */ }`. **Deliberately allowed, each with an inline reason** (no blanket crate-level allow): - `approx_constant` — `lex("3.14")` is a float literal *under test*, not an approximation of PI - `type_complexity` — replaced with a `TokenPredicate` type alias - `too_many_arguments` ×3 — 8 params vs clippy's default threshold of 7, on option-heavy CLI entry points and the recursive import resolver - `large_enum_variant` — `Value::Closure` is ~264 bytes vs ~48 for the next largest, so every `Value` pays for it. The real fix is boxing the payload, which touches every construction and match site **in the interpreter**. That is a behavioural-risk refactor that does not belong in a CI-infrastructure change. Allowed here with a comment, tracked in **#360**. ## Verification — all local, all green ``` cargo check --locked --all-targets ok cargo clippy --all-targets -- -D warnings exit 0 cargo fmt --all -- --check clean cargo test --workspace 285 passed, 0 failed ``` The 285 passing tests matter here: the `try_fold` rewrites and the `unsafe` removal are the only changes that could alter behaviour, and the parser/interpreter suites cover both. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The finding
.github/workflows/rust-ci.ymlfailed 60 consecutive runs, every one at 0s, withzero jobs and no logs, from 2026-06-27 to 2026-07-27. That is a startup failure —
GitHub rejected the file before scheduling anything. Not a flake, not a failing test.
It was found via a workflow-name fallback: GitHub reports a workflow's
nameas itsfile path when it has never successfully parsed the file.
rust-ci.ymldeclaresname: Rust CI. GitHub never saw it.Why it matters
cargo buildandcargo testexist only in this workflow. So the Rustimplementation — 70 source files — had no build or test gate for a month, while the
board read 13/14 green. The
wasm-validatejob guarding against invalid emitted wasm(cf. #348) was equally dead.
Cause
if: hashFiles('Cargo.toml') != ''used as a job-level conditional on both localjobs. Job-level
if:is evaluated server-side before any checkout, sohashFiles()hasno workspace to hash. The estate reusable's own header names this exact construct as a
recurring failure mode, and solves it correctly with a
detectjob whose output gatesthe rest.
The guard was redundant anyway — this repo unconditionally has a
Cargo.toml.Ruled out first
So the next reader doesn't repeat the work:
contents: readAlso in this PR — salvage from uncommitted sweep debris
Kept (useful):
.editorconfig— per-language indent widths (rust/zig 4, ada 3, Justfile 4), but withthe SPDX header restored and the sweep's rebrand of this file to
RSR-template-repo(a template self-name leak) dropped..gitignore— build/tooling artefact patterns, minus the sweep's.claude/and.editorconfigentries: both are tracked here, so ignoring them would hide realchanges from
git status. Verified no tracked file becomes newly ignored.Discarded (harmful):
guix.scmclobbered to identify assquisher-corpus, relicensed toPMPL-1.0-or-later, Owner line deleted — and carrying a
//comment in a Scheme file..tool-versions(pinscoq 8.18.0/ocaml 5.4.1/rust stable)..gitattributesregression dropping*.zigand*.a2mlrules.55dbd3b, which replaced a valid CodeQL pin with29b1f65c— a SHA thatdoes not exist (HTTP 422) — and would have taken the currently-green CodeQL gate down.
How to verify
The check is self-demonstrating: if this PR's Rust CI runs at all, the fix worked.
Sixty prior runs produced zero jobs. Confirm the workflow now reports as
Rust CIrather than its path, and that
no-default-featuresandwasm-validateactually execute.Note for follow-up (not in this PR)
The same detector found two more
name == pathentries here. Both are benign, but worthrecording:
workflow-linter.yml— file deleted, registration lingers. Harmless orphan.instant-sync.yml— file exists,disabled_manually(deliberately frozen). It parsesas YAML, so its cause differs; it would need diagnosis before being re-enabled.
🤖 Generated with Claude Code