Skip to content

feat(ci): assert all rainix-*.yaml reusables share one pinned RAINIX_SHA#252

Open
thedavidmeister wants to merge 5 commits into
mainfrom
2026-07-04-issue-248-flake-pin-consistency-check
Open

feat(ci): assert all rainix-*.yaml reusables share one pinned RAINIX_SHA#252
thedavidmeister wants to merge 5 commits into
mainfrom
2026-07-04-issue-248-flake-pin-consistency-check

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Closes #248

What

Adds a CI consistency check that verifies every .github/workflows/rainix-*.yaml reusable workflow file pins its flake ref to the same RAINIX_SHA commit and contains no bare unpinned github:rainlanguage/rainix# refs.

Files

  • lib/check-rainix-flake-pin.sh — shell library with:

    • _extract_sha <file> — extracts RAINIX_SHA from a single workflow file
    • _count_unpinned_refs <dir> — counts bare github:rainlanguage/rainix# refs across all rainix-*.yaml files
    • check_rainix_flake_pin_consistent [dir] — asserts all files share one SHA, fails with diagnostic on any mismatch, missing SHA, bare unpinned ref, or empty dir
  • test/bats/task/check-rainix-flake-pin.test.bats — 10 BATS unit tests covering all pass/fail branches; added to default-shell-test

  • flake.nix — new rainix-check-flake-pin nix package (mkTask) so downstream consumers can run nix run ..#rainix-check-flake-pin against their own .github/workflows/ directory

  • .github/workflows/check-shell.yml — new step nix run .#rainix-check-flake-pin runs the live check against the rainix repo itself on every push

Approach

Detection-only guard: fails loudly when a toolchain bump leaves one reusable behind. Catches drift before it ships without requiring templating or a pre-commit hook.

Summary by CodeRabbit

  • New Features
    • Added a CI validation step to verify consistent RAINIX_SHA pinning across reusable workflow files.
    • Introduced a new exported check task for enforcing flake pin alignment.
  • Bug Fixes
    • The check now fails when RAINIX_SHA is missing, differs between workflows, or when any unpinned github:rainlanguage/rainix#… references are detected.
  • Tests
    • Added Bats test coverage for SHA extraction, unpinned ref detection, consistency enforcement, and behavior when no matching workflows are found.

Adds a shell library (`lib/check-rainix-flake-pin.sh`) with
`check_rainix_flake_pin_consistent` that verifies every
`.github/workflows/rainix-*.yaml` file defines the same RAINIX_SHA
value and contains no bare unpinned `github:rainlanguage/rainix#` refs.
A missed SHA during a toolchain bump silently leaves one reusable on a
stale toolchain; this guard catches the drift before it reaches CI.

Wired up as:
- A `nix run .#rainix-check-flake-pin` package so downstream consumers
  can run it against their own workflow directory.
- A step in `check-shell.yml` that runs the live check against the
  rainix repo itself on every push.
- 10 BATS unit tests in `test/bats/task/check-rainix-flake-pin.test.bats`
  exercising all pass/fail branches; tests run via `default-shell-test`.

Closes #248

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 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: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e9f7b0a-9382-41fe-92bd-68d16a47ac25

📥 Commits

Reviewing files that changed from the base of the PR and between 2eec7d0 and bb0c548.

📒 Files selected for processing (2)
  • flake.nix
  • lib/check-rainix-flake-pin.sh
📝 Walkthrough

Walkthrough

This PR adds a shell check that verifies RAINIX_SHA is present and consistent across rainix-*.yaml workflows, rejects unpinned github:rainlanguage/rainix# refs, wires the check into Nix and CI, and adds Bats coverage for the helper functions and end-to-end behavior.

Changes

Flake-pin consistency check

Layer / File(s) Summary
Consistency check script
lib/check-rainix-flake-pin.sh
Adds _extract_sha, _count_unpinned_refs, and check_rainix_flake_pin_consistent to validate workflow pin consistency and unpinned references.
Nix task and CI wiring
flake.nix, .github/workflows/check-shell.yml
Adds the rainix-check-flake-pin task and package export, includes its Bats test in default-shell-test, and runs the check in CI.
Bats test suite
test/bats/task/check-rainix-flake-pin.test.bats
Adds unit, behavior, and smoke tests for the helper functions and the workflow consistency check.

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

Possibly related PRs

  • rainlanguage/rainix#245: Introduces the pinned github:rainlanguage/rainix/<sha>#sol-shell`` workflow pattern that this check validates.
  • rainlanguage/rainix#247: Updates reusable workflows to use pinned Rainix refs, which is the state enforced by the new consistency check.
  • rainlanguage/rainix#249: Closely related follow-up around the same flake-pin consistency rule and workflow pinning workflow.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the new CI check that enforces a single pinned RAINIX_SHA across reusable workflows.
Linked Issues check ✅ Passed The PR satisfies #248 by adding a guard that all rainix reusable workflows share one SHA and do not use bare unpinned refs.
Out of Scope Changes check ✅ Passed The changes stay within the stated goal: a shell check, its tests, and CI wiring for rainix flake-pin consistency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-07-04-issue-248-flake-pin-consistency-check

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@flake.nix`:
- Around line 291-303: Add GNU grep and GNU sed to the default-shell-test input
set, since check-rainix-flake-pin is exercised by
test/bats/task/check-rainix-flake-pin.test.bats through
lib/check-rainix-flake-pin.sh and currently only pkgs.bats plus the existing
build inputs are included; update the default-shell-test definition so it also
includes pkgs.gnugrep and pkgs.gnused, matching the tooling used by
rainix-check-flake-pin and keeping RAINIX_SHA parsing consistent on macOS CI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 020c0548-e776-4526-8b48-f52716bc08f1

📥 Commits

Reviewing files that changed from the base of the PR and between 40d814d and 539df1c.

📒 Files selected for processing (4)
  • .github/workflows/check-shell.yml
  • flake.nix
  • lib/check-rainix-flake-pin.sh
  • test/bats/task/check-rainix-flake-pin.test.bats

Comment thread flake.nix
Comment on lines +291 to +303
# Verifies all rainix-*.yaml reusable workflows pin their RAINIX_SHA
# to the same commit SHA and contain no bare unpinned flake refs.
# Catches toolchain-bump drift across the 11 reusable workflow files.
rainix-check-flake-pin = mkTask {
name = "rainix-check-flake-pin";
body = ''
set -euo pipefail
source ${./lib/check-rainix-flake-pin.sh}
check_rainix_flake_pin_consistent ".github/workflows"
'';
additionalBuildInputs = [ pkgs.gnugrep pkgs.gnused pkgs.coreutils ];
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
ast-grep outline flake.nix --view expanded | rg -n 'default-shell-test|rainix-check-flake-pin|mkTask'
rg -n -B3 -A20 'default-shell-test = mkTask' flake.nix
rg -n 'gnused|gnugrep' flake.nix

Repository: rainlanguage/rainix

Length of output: 1342


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show relevant definitions with line numbers.
sed -n '1,220p' flake.nix | cat -n
printf '\n==== SPLIT ====\\n'
sed -n '220,420p' flake.nix | cat -n
printf '\n==== SEARCH ====\\n'
rg -n 'mkTask|sol-build-inputs|node-build-inputs|devShell|gnugrep|gnused|coreutils' flake.nix

Repository: rainlanguage/rainix

Length of output: 20622


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' flake.nix | cat -n
printf '\n==== SPLIT ====\\n'
sed -n '220,420p' flake.nix | cat -n
printf '\n==== SEARCH ====\\n'
rg -n 'mkTask|sol-build-inputs|node-build-inputs|devShell|gnugrep|gnused|coreutils' flake.nix

Repository: rainlanguage/rainix

Length of output: 20622


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the mkTask definition and nearby build-input list definitions.
rg -n -A40 -B20 'mkTask\s*=' flake.nix
printf '\n==== BUILD INPUT LISTS ====\\n'
rg -n -A20 -B5 'sol-build-inputs|node-build-inputs' flake.nix

Repository: rainlanguage/rainix

Length of output: 13819


Add GNU grep/sed to default-shell-test. test/bats/task/check-rainix-flake-pin.test.bats exercises lib/check-rainix-flake-pin.sh, but default-shell-test only adds [ pkgs.bats ] ++ sol-build-inputs ++ node-build-inputs. Add pkgs.gnugrep and pkgs.gnused there too so the macOS CI leg parses RAINIX_SHA consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@flake.nix` around lines 291 - 303, Add GNU grep and GNU sed to the
default-shell-test input set, since check-rainix-flake-pin is exercised by
test/bats/task/check-rainix-flake-pin.test.bats through
lib/check-rainix-flake-pin.sh and currently only pkgs.bats plus the existing
build inputs are included; update the default-shell-test definition so it also
includes pkgs.gnugrep and pkgs.gnused, matching the tooling used by
rainix-check-flake-pin and keeping RAINIX_SHA parsing consistent on macOS CI.

@thedavidmeister

Copy link
Copy Markdown
Contributor Author

Producer note: HAND-OFF on red rainix-check-shell (both OS). State change: the previous yamlfmt cause is RESOLVED (merged main d9d0960; .github/actions now match main). The remaining failure is this PR's own new checker: nix run .#rainix-check-flake-pin exits 1 with 'check-rainix-flake-pin: no rainix-.yaml files found under .github/workflows' when run inside the rainix repo itself (run 28727937039). The checker needs a decision: treat zero rainix-.yaml consumer files as PASS (rainix hosts the reusables, it does not consume them via rainix-*.yaml callers), or point the glob at the files it should actually validate here. A 3b attempt for this check already exists (2026-07-04), so per one-attempt-per-check back-off I am not pushing again.

@thedavidmeister

Copy link
Copy Markdown
Contributor Author

🤖 ai:producer
Producer note: HAND-OFF on rainix-check-shell — still red after fix attempt 71f7f3e [3b-attempt]. Current failures (run 28727937039): two bundled-prettier bats tests ("formats Svelte files with TS enums", "reformats to rainix canon") plus the PR's own nix run .#rainix-check-flake-pin step exiting 1. main's check-shell went green again 2026-07-05T02:56Z after failing 2026-07-04 — a merge-from-main may clear the bats reds, but the flake-pin step failure is this PR's own feature and needs investigation.

@thedavidmeister thedavidmeister added the ai:reject AI vetter: needs rework (code issue) label Jul 6, 2026
Three defects made rainix-check-flake-pin fail (or silently die) when run
via mkTask, whose scripts execute under nixpkgs' non-interactive bash with
set -euo pipefail:

- compgen is not a builtin in that bash, so the existence probe always
  reported 'no rainix-*.yaml files found'; the glob itself (with an -e
  guard per entry) is now the existence check.
- Aggregator workflows (rainix-sol.yaml, rainix-rs.yaml) and workflows
  with no nix flake refs (rainix-vercel.yaml) have nothing to pin;
  RAINIX_SHA is now only required in files referencing the rainix flake.
- Both helper pipelines returned grep's no-match status under pipefail,
  aborting the caller before any diagnostic; they now end in || true.

Validated: nix run .#rainix-check-flake-pin exits 0 on the repo root, and
under set -euo pipefail the checker still fails correctly on an empty dir,
a mismatched sha, a flake-ref file missing RAINIX_SHA, and a bare unpinned
ref.

Co-Authored-By: Claude <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
Contributor Author

🤖 ai:producer
Producer note: CORRECTION + fix pushed (bb0c548). My 2026-07-05 hand-off note misdiagnosed the red — run 28727937039's only failing step was the PR's own rainix-check-flake-pin, not bats/prettier. Root cause reproduced locally: mkTask scripts run under nixpkgs' non-interactive bash, where (1) compgen doesn't exist so the existence probe always claimed 'no rainix-*.yaml files found', (2) set -euo pipefail silently killed the helper pipelines on grep's healthy no-match status, and (3) the checker wrongly demanded RAINIX_SHA in aggregator/no-flake-ref workflows. All three fixed; nix run .#rainix-check-flake-pin now exits 0 on the repo root and still fails correctly on mismatch/missing-sha/bare-ref/empty-dir mutations. This is a new failure mode, not a re-push of the earlier additionalBuildInputs attempt — if this check comes back red again it is a hard hand-off.

@thedavidmeister

thedavidmeister commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

🤖 ai:vetter
Reviewed bb0c548: reject — missing/false QA evidence: still no QA-GUIDE section-8 block in body or comments after fix push bb0c
cost 317 — shell checker lib, bats suite, nix wiring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:reject AI vetter: needs rework (code issue)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: single-source the rainix flake-pin sha instead of repeating it across reusables

1 participant