Skip to content

feat: flake-parts#4

Merged
0xgleb merged 2 commits into
feat/libfrom
feat/flake-parts
Mar 22, 2026
Merged

feat: flake-parts#4
0xgleb merged 2 commits into
feat/libfrom
feat/flake-parts

Conversation

@0xgleb
Copy link
Copy Markdown
Member

@0xgleb 0xgleb commented Mar 21, 2026

Summary by CodeRabbit

  • New Features

    • Migrate build to flake-parts and add Nushell-based CLI scripts for bootstrap, deploy, and terraform flows.
    • Add example configurations (minimal, single-service, full) and an examples validator check.
  • Documentation

    • Nushell style guide and workflow policies added; README, ROADMAP, and CHANGELOG updated.
  • Chores

    • Replace various shell wrappers with unified Nushell wrappers and expose a Nushell script helper.
    • Switch to a modern formatter and adjust developer shell behavior.
  • Tests

    • Add Nushell unit tests for scripts and example validation.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 21, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4424ea98-5203-48a6-81f1-9c29aaa14c36

📥 Commits

Reviewing files that changed from the base of the PR and between 3ddacde and dc76a53.

📒 Files selected for processing (25)
  • AGENTS.md
  • CHANGELOG.md
  • README.md
  • ROADMAP.md
  • examples/full/config/api.toml
  • examples/full/config/staging-api.toml
  • examples/full/config/worker.toml
  • examples/full/os.nix
  • examples/minimal/os.nix
  • examples/single-service/config/api.toml
  • examples/single-service/os.nix
  • flake.nix
  • lib/bootstrap.nix
  • lib/deploy.nix
  • lib/shell.nix
  • lib/terraform.nix
  • modules/base.nix
  • modules/storage.nix
  • scripts/bootstrap.nu
  • scripts/bootstrap.test.nu
  • scripts/common.nu
  • scripts/common.test.nu
  • scripts/deploy.nu
  • scripts/terraform.nu
  • scripts/validate-examples.nu

Walkthrough

Migrates the flake from flake-utils to flake-parts, restructures outputs and per-system exports, replaces many bash wrappers with a Nushell-based scripting framework (shared mkNuScript + scripts/*.nu), adds example configs/tests/validation, updates docs/agents/roadmap, and removes an unused module parameter.

Changes

Cohort / File(s) Summary
Flake refactor & outputs
flake.nix
Replace flake-utils.lib.eachDefaultSystem with flake-parts.lib.mkFlake; introduce explicit systems list; move top-level exports into flake = { ... }; add nixosConfigurations examples via mkExample; convert per-system exports into perSystem = { pkgs, system, ... }: and add checks.examples plus formatter and adjusted devShells.
Shell wrapper → Nushell infrastructure
lib/shell.nix, lib/bootstrap.nix, lib/deploy.nix, lib/terraform.nix
Remove many inlined pkgs.writeShellApplication wrappers; add mkNuScript (exported from lib/shell.nix) and reimplement bootstrap/deploy/terraform wrappers to call scripts/*.nu; adjust runtimeInputs/extraArgs usage and exported helper set.
Nushell scripts & tests
scripts/*.nu, scripts/*.test.nu, scripts/validate-examples.nu
Add scripts/common.nu, terraform.nu, deploy.nu, bootstrap.nu, validate-examples.nu and corresponding *.test.nu files; centralize state/vars encryption/decryption, resolve-ip, deploy/terraform operations, and add tests and an examples validator.
Examples: new example configurations
examples/minimal/os.nix, examples/single-service/..., examples/full/..., examples/*/config/*.toml
Add three example NixOS configurations (minimal, single-service, full) and accompanying config/*.toml files used by the new examples/testing flows.
Module changes & assertions
modules/static-sites.nix, modules/storage.nix, modules/base.nix
Remove unused pkgs parameter from modules/static-sites.nix; add omnix.storage.volumeName assertion pattern; replace activationScript mkdir with systemd.tmpfiles.rules for per-service profiles.
Deploy/dev tooling changes
lib/deploy.nix, lib/*
Move deploy inputs/flags into mkNuScript-based wrappers; add pkgs.openssh into shared deployInputs; remove embedded IP-resolution/preamble logic.
Docs & project metadata
AGENTS.md, ROADMAP.md, README.md, CHANGELOG.md
Document Nushell-first scripting policy and style guide; add migration notes and roadmap updates; add changelog entries describing the refactor and new modules/outputs.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: flake-parts' is vague and uses a generic term without clearly describing what the feature entails or the main change. Provide a more descriptive title that explains the specific purpose, such as 'refactor: migrate flake outputs to flake-parts' or 'feat: add flake-parts-based configuration system'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/flake-parts

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 and usage tips.

Copy link
Copy Markdown
Member Author

0xgleb commented Mar 21, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@0xgleb 0xgleb self-assigned this Mar 21, 2026
@0xgleb 0xgleb marked this pull request as ready for review March 21, 2026 06:56
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@flake.nix`:
- Around line 97-99: The ragenix package lookup lacks a fallback error unlike
disko, which leads to unclear failures on unsupported systems; update the
ragenix assignment (ragenix = ragenix.packages.${system}.default) to mirror
disko by adding an explicit fallback throw (e.g., ragenix =
ragenix.packages.${system}.default or (throw "ragenix package not available for
${system}")) so that unsupported-system resolution fails with a clear,
actionable message.
- Around line 90-110: The devShells.default currently inherits shellHook from
self.checks.${system}, which can cause evaluation-order recursion; change it to
reference the same-system output via the per-system config argument instead: use
config.checks.git-hooks (the checks.git-hooks output) to inherit shellHook in
devShells.default. Locate the perSystem block and replace the
self.checks.${system}.git-hooks reference with config.checks.git-hooks when
inheriting shellHook so the devShells.default uses the config module output
rather than self to prevent evaluation risks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c2d98ae6-60f1-4e3d-b45c-a17720621eb2

📥 Commits

Reviewing files that changed from the base of the PR and between e0879c4 and 3ddacde.

⛔ Files ignored due to path filters (1)
  • flake.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • flake.nix
  • modules/static-sites.nix
💤 Files with no reviewable changes (1)
  • modules/static-sites.nix
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Graphite / mergeability_check
🧰 Additional context used
📓 Path-based instructions (1)
*

⚙️ CodeRabbit configuration file

Focus on providing constructive criticism. Whenever you see a suboptimal approach, suggest more idiomatic or robust alternative(s). Flag potential footguns. Suggest FP alternatives to mutable/imperative code. Point out architectural flaws like leaky abstractions, tight coupling, wrong level of abstraction, poor type modeling, over-abstraction, unclear domain boundaries. Code should generally be organized based on business concerns rather than technical aspects - suggest improvements if you find violations. Point out gaps in test coverage but suggest tests that are not too coupled to the implementation and actually test domain invariants and business logic

Files:

  • flake.nix
🔇 Additional comments (1)
flake.nix (1)

36-88: Clean flake-parts migration and output reshaping.

This keeps module/lib/template exports readable and preserves the prior composition intent well.

Comment thread flake.nix Outdated
Comment on lines +90 to +110
perSystem =
{ pkgs, system, ... }:
let
hooks = self.lib.mkGitHooks { };
in
{
packages = {
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default;
};

checks.git-hooks = git-hooks.lib.${system}.run {
inherit hooks;
src = self;
};

formatter = pkgs.nixfmt;
formatter = pkgs.nixfmt;

devShells.default = pkgs.mkShell {
inherit (self.checks.${system}.git-hooks) shellHook;
packages = [
pkgs.nixfmt
pkgs.deadnix
pkgs.taplo
];
devShells.default = pkgs.mkShell {
inherit (self.checks.${system}.git-hooks) shellHook;
packages = [
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🌐 Web query:

In flake-parts perSystem, is referencing config.checks.preferred overself.checks.${system}.for same-system outputs, and are there evaluation pitfalls withself self-references?

💡 Result:

In flake-parts perSystem, both config.checks. and self'.checks. are valid ways to reference locally defined checks for the current system, with no explicit preference stated in the official documentation for same-system outputs. The cheat sheet presents config.packages.hello as "conceptually simpler" and self'.packages.hello as potentially benefiting from future evaluation caching [3,5]. self.checks.${system}. is not a standard perSystem module argument; self refers to the top-level flake, while self' is the pre-selected system version provided in perSystem [5,25]. Using raw self in perSystem risks evaluation order issues or infinite recursion, as seen in flake self-references during imports or outPath access [14,16]. No specific pitfalls are documented for self self-references within perSystem beyond general Nix flake recursion risks when accessing unevaluated attributes [13,14,16]. Prefer module arguments like config or self' to avoid them.

Citations:


Use config.checks.git-hooks instead of self.checks.${system} to avoid evaluation risks.

Using self.checks.${system} in perSystem risks evaluation order issues and infinite recursion. The idiomatic approach in flake-parts is to reference same-system outputs via the config module argument.

♻️ Proposed refactor
-      perSystem =
-        { pkgs, system, ... }:
+      perSystem =
+        { config, pkgs, system, ... }:
         let
           hooks = self.lib.mkGitHooks { };
         in
         {
@@
           devShells.default = pkgs.mkShell {
-            inherit (self.checks.${system}.git-hooks) shellHook;
+            inherit (config.checks.git-hooks) shellHook;
             packages = [
               pkgs.nixfmt
               pkgs.deadnix
               pkgs.taplo
             ];
           };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
perSystem =
{ pkgs, system, ... }:
let
hooks = self.lib.mkGitHooks { };
in
{
packages = {
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default;
};
checks.git-hooks = git-hooks.lib.${system}.run {
inherit hooks;
src = self;
};
formatter = pkgs.nixfmt;
formatter = pkgs.nixfmt;
devShells.default = pkgs.mkShell {
inherit (self.checks.${system}.git-hooks) shellHook;
packages = [
pkgs.nixfmt
pkgs.deadnix
pkgs.taplo
];
devShells.default = pkgs.mkShell {
inherit (self.checks.${system}.git-hooks) shellHook;
packages = [
perSystem =
{ config, pkgs, system, ... }:
let
hooks = self.lib.mkGitHooks { };
in
{
packages = {
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default;
};
checks.git-hooks = git-hooks.lib.${system}.run {
inherit hooks;
src = self;
};
formatter = pkgs.nixfmt;
devShells.default = pkgs.mkShell {
inherit (config.checks.git-hooks) shellHook;
packages = [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@flake.nix` around lines 90 - 110, The devShells.default currently inherits
shellHook from self.checks.${system}, which can cause evaluation-order
recursion; change it to reference the same-system output via the per-system
config argument instead: use config.checks.git-hooks (the checks.git-hooks
output) to inherit shellHook in devShells.default. Locate the perSystem block
and replace the self.checks.${system}.git-hooks reference with
config.checks.git-hooks when inheriting shellHook so the devShells.default uses
the config module output rather than self to prevent evaluation risks.

Comment thread flake.nix
Comment on lines +97 to +99
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Make ragenix package lookup failure explicit like disko.

disko has a clear fallback error, but ragenix does not. Aligning both gives a more actionable failure on unsupported systems.

🛡️ Proposed robustness tweak
           packages = {
             disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
-            ragenix = ragenix.packages.${system}.default;
+            ragenix = ragenix.packages.${system}.default or (throw "ragenix package not available for ${system}");
           };

As per coding guidelines, "Whenever you see a suboptimal approach, suggest more idiomatic or robust alternative(s)."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default;
};
disko = disko.packages.${system}.default or (throw "disko package not available for ${system}");
ragenix = ragenix.packages.${system}.default or (throw "ragenix package not available for ${system}");
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@flake.nix` around lines 97 - 99, The ragenix package lookup lacks a fallback
error unlike disko, which leads to unclear failures on unsupported systems;
update the ragenix assignment (ragenix = ragenix.packages.${system}.default) to
mirror disko by adding an explicit fallback throw (e.g., ragenix =
ragenix.packages.${system}.default or (throw "ragenix package not available for
${system}")) so that unsupported-system resolution fails with a clear,
actionable message.

@0xgleb 0xgleb marked this pull request as draft March 21, 2026 07:42
@0xgleb 0xgleb marked this pull request as ready for review March 22, 2026 04:29
@0xgleb 0xgleb merged commit 23d503f into feat/lib Mar 22, 2026
1 of 3 checks passed
@0xgleb 0xgleb deleted the feat/flake-parts branch March 22, 2026 04:30
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.

1 participant