Skip to content

ci: run rustfmt, clippy and the test suite against rainix-static/ itself - #346

Merged
thedavidmeister merged 3 commits into
mainfrom
2026-08-21-issue-345-static-crate-coverage
Aug 21, 2026
Merged

thedavidmeister merged 3 commits into
mainfrom
2026-08-21-issue-345-static-crate-coverage

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

rainix-static/ is the crate that implements every org-wide gate — release-guard,
soldeer-gate, snapshots-append-only, rpc-preflight — and rainix's own CI could not
see it. Every job in the self-test matrix runs with working-directory: test/fixture
(.github/workflows/test.yml:28), and test/fixture/Cargo.toml is a workspace whose only
member is crates/test-rs, so that matrix's cargo test and its rainix-rs-static
(cargo fmt --all -- --check plus cargo clippy --all-targets --all-features -- -D warnings -D clippy::all) resolve against the fixture and never against rainix-static/.

This adds a named rainix-static job that runs cargo test (ubuntu + macos) and
rainix-rs-static (ubuntu, mirroring the matrix's own "no rust static analysis on
multiple platforms" rule) with working-directory: rainix-static. The fixture matrix is
untouched — it proves the tasks work for a downstream consumer, which is a different
claim from covering rainix's own crate, and both claims are now made.

The commands run in the dev shell rather than as nix build .#rainix-static on
purpose
, for the reason the next section measures: that derivation's tests are
cache-conditional, and cargo fmt/cargo clippy are not in it at all.

The open question, settled by measurement

whether rainix-static's unit tests execute in CI today at all

They do — sometimes. It is decided by the Cachix cache, not by the code, and it is not
nix flake check that decides it.
Three measurements, no reasoning from defaults:

1. nix flake check evaluates the derivation but does not build it. From the
check-shell run on #343's branch (run
32457734763
):

Run NIXPKGS_ALLOW_INSECURE=1 nix flake check --impure
  07:14:38.05  checking derivation packages.x86_64-linux.rainix-static...
  07:14:38.31  derivation evaluated to /nix/store/gffwx5w342kd1ql8a2avsyhszzzy9pjy-rainix-static-0.1.0.drv

No build follows in that step. nix flake check builds checks.*; packages.* it only
evaluates. The build happens later, in a different step, because rainix-static is in
common-shell-inputs (flake.nix:367) and instantiating a dev shell realises it:

Run nix develop --command cargo release --version
  07:15:42.78  building '/nix/store/gffwx5w342kd1ql8a2avsyhszzzy9pjy-rainix-static-0.1.0.drv'...

2. On a Cachix hit nothing runs — same commit, same crate, opposite outcome per
runner.
In that same run, the macOS job reached the same step and got the cache:

Run nix develop --command cargo release --version
  07:18:32.48  copying path '/nix/store/ak6x1jvr9g9pwm2m3j143yzvq2qj9q1h-rainix-static-0.1.0' from 'https://rainlanguage.cachix.org'...

A substituted path runs no phases at all, so on that commit the crate's unit tests
executed on ubuntu and did not execute on macos. On unchanged main the hit is
guaranteed, not incidental: nix eval --raw .#rainix-static at 74bfa3b gives
/nix/store/b185bvvj9v0wnn7vfgcny8669gzgf6ki-rainix-static-0.1.0, and

$ curl -s -o /dev/null -w '%{http_code}\n' https://rainlanguage.cachix.org/b185bvvj9v0wnn7vfgcny8669gzgf6ki.narinfo
200

so every CI job on today's main substitutes that output and runs zero of its tests.

3. When it is built, the tests genuinely run — and only the tests. Forcing a real
build of main's derivation (nix build .#rainix-static -L --rebuild --option substituters "https://cache.nixos.org"):

rainix-static> Running phase: checkPhase
rainix-static> Executing cargoCheckHook
rainix-static>      Running unittests src/main.rs (target/x86_64-unknown-linux-gnu/release/deps/rainix_static-...)
rainix-static> running 159 tests
rainix-static> test result: ok. 159 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

(that command exits 1 only on --rebuild's reproducibility comparison — may not be deterministic: output ... differs — not on a test failure.) cargoCheckHook runs
cargo test and nothing else: cargo fmt and cargo clippy never run in this
derivation under any cache state
, which is why the answer to the open question does not
change the conclusion. flake.nix's comment claiming the tests "run inside the nix build
via doCheck" was true but load-bearing in a way it could not carry; it is corrected in
place to say what it actually guarantees and to point at the job that is the coverage.

Formatting: main is clean, #343 is not — stated, not fixed here

The issue predicts a red first run on cargo fmt --check. Measured rather than assumed:
at main (74bfa3b) the crate is already clean

$ cd rainix-static && cargo fmt --all -- --check ; echo $?
0
$ cargo clippy --all-targets --all-features -- -D warnings -D clippy::all ; echo $?
0

so there is nothing to format on this branch, and the new job is green here. The diffs the
issue cites are real, but they live on #343's branch (0b46830), which is not merged.
Running the same check in a read-only worktree of
origin/2026-08-20-issue-341-release-determinism exits 1 with three hunks —
frozen_snapshots.rs:111, frozen_snapshots.rs:142, and in production code
release_guard.rs:251 (a read_dir(...).unwrap_or_else(...) that rustfmt wants as a
block) — while that PR reports 14 green checks. That is the bug this job fixes, observed.

#343 is not touched by this PR, and there is a sequencing consequence to state plainly:
whichever of the two merges second produces a main commit carrying both this job and
#343's unformatted code, so main goes red on rainix-static (ubuntu-latest, rainix-rs-static) until cargo fmt is run over the crate. #343 should run cargo fmt
in rainix-static/ before it merges. That is the check working, not a defect in it.

QA

  • The new job verified in this PR's own CI, not just locally. From the job logs of
    run 32458880233:
    rainix-static (ubuntu-latest, cargo test)Run nix develop .. --command cargo test
    running 159 teststest result: ok. 159 passed; 0 failed;
    rainix-static (macos-latest, cargo test) → the same 159 passed; 0 failed;
    rainix-static (ubuntu-latest, rainix-rs-static)++ cargo fmt --all -- --check,
    ++ cargo clippy --all-targets --all-features -- -D warnings -D clippy::all,
    Checking rainix-static v0.1.0 (/home/runner/work/rainix/rainix/rainix-static). That
    last path is the point: the lints are now resolving against this repo's own crate on a
    real runner. Also run locally beforehand with the identical invocation from
    rainix-static/ after rm -rf target, both exit 0.
  • Discriminating tests: the new job itself is the test, and its discriminating case is
    fix(tag-release): determinism check that never removes the frozen record #343's branch — nix develop .. --command rainix-rs-static from rainix-static/ exits 1
    there (release_guard.rs:251, production code) and exits 0 from test/fixture/, which is
    what base CI runs. Verified by running both invocations in a read-only worktree of
    origin/2026-08-20-issue-341-release-determinism (0b46830): base's fixture-scoped
    command passes the code the new crate-scoped command fails. On this branch, at main
    74bfa3b, both are green, so the job is not merely red-by-construction.
  • Pre-commit (nix develop .#rust-shell --command pre-commit run --files flake.nix .github/workflows/test.yml): deadnix, nil, nixfmt, statix, yamlfmt, no-consumer-prettier
    all Passed; the rest skip with no matching files.
  • Mutation evidence: n/a. The diff is CI wiring plus a corrected flake.nix comment —
    no Rust logic changed (git diff main --stat touches .github/workflows/test.yml and
    flake.nix only, zero files under rainix-static/src/), so there is nothing for
    mutation-probe to mutate. The mutation-relevant effect of this PR is the opposite
    direction: it is what makes rainix-static/'s existing 159 tests, and its lint gates,
    actually run on every push.
  • Oracle: derived from the workflow and manifest as filed rather than from the
    implementation — test.yml:28 pins working-directory: test/fixture;
    test/fixture/Cargo.toml lists members = ["crates/test-rs"]; flake.nix:342-348
    defines rainix-rs-static as fmt + clippy over --all; flake.nix:367 puts
    rainix-static in common-shell-inputs. Cargo resolves --all against the workspace
    rooted at the working directory, so no invocation from test/fixture can reach
    rainix-static/.
  • Category check: issue asks (A) add a named check running rainix-rs-static and the
    test suite against rainix-static/ itself, alongside the fixture matrix rather than
    replacing it; (B) determine and state whether the crate's unit tests execute in CI today;
    (C) expect a red first run on formatting and fix it by formatting the crate, never by
    loosening the check. Covered A and B. C is n/a with a reason, measured: at main
    74bfa3b the crate is already fmt-clean and clippy-clean (exit 0, shown above), so there
    is nothing here to format and nothing was loosened — the diffs the issue saw are on
    fix(tag-release): determinism check that never removes the frozen record #343's unmerged branch, are reproduced above, and are flagged for fix(tag-release): determinism check that never removes the frozen record #343 to format rather
    than silenced.

Closes #345

🤖 Generated with Claude Code

Every job in the self-test matrix runs with `working-directory: test/fixture`,
whose workspace has exactly one member (`crates/test-rs`), so `cargo test` and
`rainix-rs-static` there resolve against the fixture — never against
`rainix-static/`, the crate implementing release-guard, soldeer-gate,
snapshots-append-only and rpc-preflight.

Adds a named `rainix-static` job that runs `cargo test` (both platforms) and
`rainix-rs-static` (ubuntu) with `working-directory: rainix-static`. The fixture
matrix is untouched: it proves the tasks work for a downstream consumer, which
is a different claim.

The commands run in the dev shell, not as `nix build .#rainix-static`, because
that derivation's checkPhase only runs on a cache miss.

Closes #345

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e4f3f569-6f34-4a38-a5fe-d05f543aa4cf

📥 Commits

Reviewing files that changed from the base of the PR and between 432cd1a and d97c498.

📒 Files selected for processing (3)
  • flake.nix
  • rainix-static/src/frozen_snapshots.rs
  • rainix-static/src/release_guard.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8e5eeecc-246e-4020-a0dd-de21170e4bd5

📥 Commits

Reviewing files that changed from the base of the PR and between 74bfa3b and 432cd1a.

📒 Files selected for processing (2)
  • .github/workflows/test.yml
  • flake.nix

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The workflow adds dedicated rainix-static checks for Rust tests and static analysis. The flake documentation explains that derivation checks run only on uncached builds and do not replace CI coverage.

Changes

rainix-static CI coverage

Layer / File(s) Summary
Add explicit rainix-static checks
.github/workflows/test.yml, flake.nix
The CI matrix runs cargo test on Ubuntu and macOS and rainix-rs-static on Ubuntu from rainix-static. The existing fixture checks remain unchanged. The flake documentation describes cached derivation behavior and separate CI coverage.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 432cd

This change adds CI coverage for the repository's own Rust tests, formatting, and clippy checks without changing production code or runtime behavior. No actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: findolor

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds explicit test, rustfmt, and clippy coverage for rainix-static/ while preserving the fixture matrix, satisfying issue #345.
Out of Scope Changes check ✅ Passed The CI workflow and flake.nix documentation changes directly support the linked issue and PR objectives; no unrelated changes are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main CI change: running rustfmt, clippy, and tests against the rainix-static directory.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-08-21-issue-345-static-crate-coverage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

baku-ccron and others added 2 commits August 21, 2026 07:38
Merging main brought #343's Rust under the new crate-scoped job, and it does
not pass: 11 clippy errors and a dirty `cargo fmt`. Neither was ever visible,
because nothing has run either tool against this crate.

- 10 x `doc_overindented_list_items` in `release_guard.rs`'s module doc. `a.`
  and `b.` are not markdown list markers — markdown ordered lists are digits
  only — so the block is a continuation paragraph of item 4 and belongs at
  item 4's content indent, not a nested one. Flattened to that, with a blank
  `//!` between the two so they still render apart. The labels stay: line 371
  refers to "4a." in a code comment.
- `frozen_tags.iter().any(|t| *t == dir)` -> `frozen_tags.contains(&dir)`, from
  `cargo clippy --fix`. Same `PartialEq` comparison over the same `Vec<String>`;
  no behaviour change.
- `cargo fmt` over the crate, which is what the job now enforces.

Verified in the dev shell on this tree: `cargo fmt --all -- --check` clean,
`cargo clippy --all-targets --all-features -- -D warnings -D clippy::all` zero
errors, 174 tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeister
thedavidmeister merged commit 3d1c85e into main Aug 21, 2026
17 checks passed
@github-actions

Copy link
Copy Markdown

@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment:

S/M/L PR Classification Guidelines:

This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed.

Small (S)

Characteristics:

  • Simple bug fixes, typos, or minor refactoring
  • Single-purpose changes affecting 1-2 files
  • Documentation updates
  • Configuration tweaks
  • Changes that require minimal context to review

Review Effort: Would have taken 5-10 minutes

Examples:

  • Fix typo in variable name
  • Update README with new instructions
  • Adjust configuration values
  • Simple one-line bug fixes
  • Import statement cleanup

Medium (M)

Characteristics:

  • Feature additions or enhancements
  • Refactoring that touches multiple files but maintains existing behavior
  • Breaking changes with backward compatibility
  • Changes requiring some domain knowledge to review

Review Effort: Would have taken 15-30 minutes

Examples:

  • Add new feature or component
  • Refactor common utility functions
  • Update dependencies with minor breaking changes
  • Add new component with tests
  • Performance optimizations
  • More complex bug fixes

Large (L)

Characteristics:

  • Major feature implementations
  • Breaking changes or API redesigns
  • Complex refactoring across multiple modules
  • New architectural patterns or significant design changes
  • Changes requiring deep context and multiple review rounds

Review Effort: Would have taken 45+ minutes

Examples:

  • Complete new feature with frontend/backend changes
  • Protocol upgrades or breaking changes
  • Major architectural refactoring
  • Framework or technology upgrades

Additional Factors to Consider

When deciding between sizes, also consider:

  • Test coverage impact: More comprehensive test changes lean toward larger classification
  • Risk level: Changes to critical systems bump up a size category
  • Team familiarity: Novel patterns or technologies increase complexity

Notes:

  • the assessment must be for the totality of the PR, that means comparing the base branch to the last commit of the PR
  • the assessment output must be exactly one of: S, M or L (single-line comment) in format of: SIZE={S/M/L}
  • do not include any additional text, only the size classification
  • your assessment comment must not include tips or additional sections
  • do NOT tag me or anyone else on your comment

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master)"
git diff --stat "$base"...HEAD
git diff --numstat "$base"...HEAD
git diff -- "$base"...HEAD -- .github/workflows/test.yml flake.nix

Length of output: 392


SIZE=S

You are interacting with an AI system.

thedavidmeister pushed a commit that referenced this pull request Aug 21, 2026
#346 landed the crate-scoped rustfmt/clippy/test job after this branch was cut,
so 833e8a7 would have shipped #343's checks and left #346's inert — a second
bump behind the first. Merging main and repointing at its tip makes one bump
cover both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rainix's own CI never runs rustfmt, clippy or tests against rainix-static/

1 participant