Skip to content

chore: switch to crate2nix - #2719

Open
Lymah123 wants to merge 1 commit into
molybdenumsoftware:masterfrom
Lymah123:chore/crane-to-crate2nix
Open

chore: switch to crate2nix#2719
Lymah123 wants to merge 1 commit into
molybdenumsoftware:masterfrom
Lymah123:chore/crane-to-crate2nix

Conversation

@Lymah123

Copy link
Copy Markdown

Switches the statix package build from rustPlatform.buildRustPackage to crate2nix, which builds each crate as a separate Nix derivation enabling more granular caching.

Changes:

  • Adds github:nix-community/crate2nix as a flake = false input
  • Threads inputs through the overlay so crate2nixSrc is available to callPackage
  • Rewrites packages/statix.nix to use tools.generatedCargoNix (IFD). Cargo.nix is generated at build time rather than checked in
  • Removes allow-import-from-derivation = false from nixConfig since IFD is now required

The statix-vim package is unaffected.

@Lymah123
Lymah123 marked this pull request as ready for review July 26, 2026 05:38
@Lymah123

Copy link
Copy Markdown
Author

Hi @mightyiam , this PR is ready for review.

@mightyiam mightyiam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about the experimental crate2nix json api?

Comment thread overlay.nix Outdated
@Lymah123

Copy link
Copy Markdown
Author

What about the experimental crate2nix json api?

Will investigate the experimental JSON output separately and report back in the discussion.

@mightyiam mightyiam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any news on the JSON API?

Comment thread flake-parts/nixpkgs.nix Outdated
Comment thread packages/statix.nix Outdated
Comment thread overlay.nix Outdated
@Lymah123

Lymah123 commented Aug 4, 2026

Copy link
Copy Markdown
Author

Any news on the JSON API?

Still pending, will try it after resolving the current comments. If it simplifies the approach, happy to switch to it entirely.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 0917330 to 1aab0dc Compare August 4, 2026 20:03
@Lymah123
Lymah123 requested a review from mightyiam August 4, 2026 20:10
Comment thread packages/statix.nix Outdated
Comment thread packages/statix.nix Outdated
Comment thread packages/statix.nix Outdated
@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 1aab0dc to 9cc159c Compare August 5, 2026 06:10
@Lymah123
Lymah123 requested a review from mightyiam August 5, 2026 06:27

@mightyiam mightyiam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems that this change results in our dev shell including some rust crate derivations. Can that be avoided?

It seems that this change results in tests not being run during the build. Rust tests | crate2nix.

@Lymah123

Lymah123 commented Aug 6, 2026

Copy link
Copy Markdown
Author

It seems that this change results in our dev shell including some rust crate derivations. Can that be avoided?

inputsFrom = [ pkgs.statix ] previously brought in rustc, cargo etc. from rustPlatform.buildRustPackage. With crate2nix it pulls in individual compiled crate derivations instead, which aren't useful in a dev shell. Will replace it with explicit pkgs.cargo, pkgs.rustc etc.

@Lymah123

Lymah123 commented Aug 6, 2026

Copy link
Copy Markdown
Author

It seems that this change results in tests not being run during the build. Rust tests | crate2nix.

Confirmed, workspaceMembers.statix.build only builds, tests need .override { runTests = true; }. Will add a separate checks.statix-tests using that.

@Lymah123

Lymah123 commented Aug 6, 2026

Copy link
Copy Markdown
Author

Investigated the test failure. The existing integration tests in bin/tests/ call Command::new("cargo").arg("run") inside _utils::test_cli to invoke statix, they shell out to cargo run rather than calling a pre-built binary. This is incompatible with the Nix sandbox where cargo isn't on PATH and the workspace isn't present at test time.

runTests = true only works for tests that compile into the test binary directly. To run these integration tests in a Nix derivation, they'd need to be rewritten to use the built binary path (like walk.rs does with env!("CARGO_BIN_EXE_statix")). That's a separate, non-trivial change.

For now I've removed checks."statix-tests" from this PR, it belongs in a follow-up that also fixes the test infrastructure.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 9cc159c to 08467a6 Compare August 6, 2026 20:02
@Lymah123
Lymah123 requested a review from mightyiam August 6, 2026 20:02
@mightyiam

Copy link
Copy Markdown
Member

For now I've removed checks."statix-tests" from this PR, it belongs in a follow-up that also fixes the test infrastructure.

Does that feel reasonable to you?

@Lymah123

Lymah123 commented Aug 7, 2026

Copy link
Copy Markdown
Author

For now I've removed checks."statix-tests" from this PR, it belongs in a follow-up that also fixes the test infrastructure.

Does that feel reasonable to you?

Yes, that feels reasonable. The test infrastructure issue is real and worth fixing properly in a follow-up, the existing integration tests call cargo run which can't work in the Nix sandbox. When we get to that follow-up, we'd need to rewrite _utils::test_cli to use env!("CARGO_BIN_EXE_statix") like walk.rs does, and then runTests = true should work cleanly.

@mightyiam

Copy link
Copy Markdown
Member

The change you are currently suggesting disables the running of all of the program's cargo tests during nix flake check and therefore from CI checks. Am I right?

@Lymah123

Lymah123 commented Aug 7, 2026

Copy link
Copy Markdown
Author

The change you are currently suggesting disables the running of all of the program's cargo tests during nix flake check and therefore from CI checks. Am I right?

You're right, that is a regression. rustPlatform.buildRustPackage ran cargo test by default, crate2nix doesn't. The test infrastructure issue (tests calling cargo run rather than a built binary) needs to be fixed as part of this PR, not deferred, since shipping without it would mean CI has no Rust test coverage at all.

Two options I can see:

  1. Fix _utils::test_cli to use env!("CARGO_BIN_EXE_statix") and use runTests = true, the correct long-term fix but more work
  2. Revert to rustPlatform.buildRustPackage for now and open a separate PR to switch to crate2nix once the test infrastructure is ready

Which would you prefer?

@mightyiam

Copy link
Copy Markdown
Member

Sorry, I'm not sure what you mean by "once the test infrastructure is ready". What infrastructure is that, please? What is not ready? Something about cargo not being in PATH? cargo can be added to PATH wherever necessary.

@Lymah123

Lymah123 commented Aug 7, 2026

Copy link
Copy Markdown
Author

Sorry, I'm not sure what you mean by "once the test infrastructure is ready". What infrastructure is that, please? What is not ready? Something about cargo not being in PATH? cargo can be added to PATH wherever necessary.

You're right, I overcomplicated it. The tests call cargo run, adding cargo (and rustc) to the test derivation's PATH via testPreRun or nativeBuildInputs should be enough. Will try that.

@Lymah123

Lymah123 commented Aug 8, 2026

Copy link
Copy Markdown
Author

Adding cargo to PATH got 32/56 tests passing. The remaining 24 fail because cargo run tries to recompile statix from source and needs network access (crates.io) which isn't available in the sandbox. A fake cargo wrapper that intercepts cargo run -- and delegates to the pre-built pkgs.statix binary fixes this, would that approach be acceptable, or would you prefer a different direction?

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch 3 times, most recently from 99f6ee9 to 391729a Compare August 9, 2026 06:31
Comment thread flake-parts/rust.nix
Comment thread flake-parts/statix.nix Outdated
@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 570cf68 to 354eb67 Compare August 13, 2026 11:45
@Lymah123
Lymah123 requested a review from mightyiam August 13, 2026 12:34
Comment thread bin/tests/_utils.rs
@@ -1,44 +1,31 @@
use std::{io::Write, process::Command, process::Stdio};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this intentional?

@Lymah123 Lymah123 Aug 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No, no intentional. Will restore it.

Comment thread bin/tests/_utils.rs
let mut child = Command::new("cargo")
.arg("run")
.arg("--")
let mut child = Command::new(env!("CARGO_BIN_EXE_statix"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be made a precursor PR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, will extract the _utils.rs change into a precursor PR, then rebase this one on top of it.

Comment thread flake-parts/statix.nix Outdated
Comment on lines +35 to +45
clippy = pkgs.rustPlatform.buildRustPackage {
pname = "statix-clippy";
version = "0.6.0-git";
inherit src;
cargoLock.lockFile = root + "/Cargo.lock";
RUSTFLAGS = "-D warnings";
nativeBuildInputs = [ pkgs.clippy ];
buildPhase = "cargo clippy --all-targets --all-features";
installPhase = "touch $out";
doCheck = false;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can clippy be based on crate2nix as well?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, will switch clippy to use pkgs.statix-workspace, the workspace already has all crates built, so clippy can run against those derivations without needing a separate buildRustPackage

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Crate2nix doesn't expose a clippy mechanism through its build attributes, it builds crates via rustc derivations with no clippy hook. The rustPlatform.buildRustPackage approach is the right tool for running clippy; I've updated it to use the shared pkgs.statix-src from packages/src.nix so there's no duplication with the crate2nix builds.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't this section demonstrate a useClippy = true? Isn't that what we are looking for?

Comment thread packages/statix.nix Outdated
Comment on lines +7 to +23
cargoNix = crate2nixTools.generatedCargoNix {
name = "statix";
src = lib.fileset.toSource {
root = ../.;
fileset = lib.fileset.unions [
(lib.fileset.fileFilter (
file:
lib.any lib.id [
(file.name == "Cargo.toml")
(file.hasExt "rs")
(file.hasExt "snap")
]
) ../.)
../Cargo.lock
../insta.yaml
];
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems that this expression exists twice. Is that intentional?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, not intentional. Will deduplicate, the fileset can be defined once and referenced in both, probably by moving it into the overlay or having statix-workspace re-export it for statix.nix to use.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 354eb67 to 76de74b Compare August 18, 2026 00:49
@Lymah123
Lymah123 requested a review from mightyiam August 18, 2026 00:56
Comment thread flake-parts/statix.nix Outdated
Comment on lines +35 to +45
clippy = pkgs.rustPlatform.buildRustPackage {
pname = "statix-clippy";
version = "0.6.0-git";
inherit src;
cargoLock.lockFile = root + "/Cargo.lock";
RUSTFLAGS = "-D warnings";
nativeBuildInputs = [ pkgs.clippy ];
buildPhase = "cargo clippy --all-targets --all-features";
installPhase = "touch $out";
doCheck = false;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't this section demonstrate a useClippy = true? Isn't that what we are looking for?

Comment thread packages/statix.nix
Comment on lines -38 to -42
meta = {
mainProgram = "statix";
description = "Lints and suggestions for the Nix programming language";
homepage = "https://github.com/molybdenumsoftware/statix";
license = lib.licenses.mit;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we lose these or are they automatically populated from Cargo.toml?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

They're lost, crate2nix only auto-populates mainProgram. description, homepage, and license need to be added back via overrideAttrs. Will fix.

Comment thread packages/statix.nix
@Lymah123

Copy link
Copy Markdown
Author

Doesn't this section demonstrate a useClippy = true? Isn't that what we are looking for?

You're right, build-rust-crate exposes useClippy which switches the compiler to clippy-driver. We can pass it via crateOverrides. Will replace the rustPlatform.buildRustPackage approach with statixBuild.override { crateOverrides = pkgs.defaultCrateOverrides // { statix = _: { useClippy = true; RUSTFLAGS = "-D warnings"; }; }; }.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 76de74b to f0e5ff2 Compare August 20, 2026 02:50
@Lymah123
Lymah123 requested a review from mightyiam August 20, 2026 03:10

@mightyiam mightyiam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please review thoroughly before submitting.

Comment thread flake-parts/statix.nix Outdated
Comment on lines +17 to +19
testPreRun = ''
export INSTA_SNAPSHOT_DIR=${root}/bin/tests/snapshots
'';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this needed, please?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The integration tests use insta::assert_snapshot! which looks for snapshot files relative to the crate source location. In the Nix build sandbox, the working directory isn't the source tree, so insta can't find the snapshots without being explicitly pointed at them via INSTA_SNAPSHOT_DIR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If

The integration tests use insta::assert_snapshot! which looks for snapshot files relative to the crate source location

it sounds like if that is the case, there should be no problem finding them. Are you sure of that explanation?

Comment thread packages/src.nix Outdated
Comment on lines +1 to +16
{ lib }:
lib.fileset.toSource {
root = ../.;
fileset = lib.fileset.unions [
(lib.fileset.fileFilter (
file:
lib.any lib.id [
(file.name == "Cargo.toml")
(file.hasExt "rs")
(file.hasExt "snap")
]
) ../.)
../Cargo.lock
../insta.yaml
];
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perhaps this should be inlined?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Happy to inline it , though that means accepting the duplication between the two files rather than avoiding it. Is that the preference, or should one file reference the other's src? Asking because the original concern was about the expression appearing twice.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Happy to inline it , though that means accepting the duplication between the two files rather than avoiding it. Is that the preference, or should one file reference the other's src? Asking because the original concern was about the expression appearing twice.

What about this? @mightyiam ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think as soon as the duplicate code is removed, this should be inlined into a single remaining position.

Comment thread packages/statix.nix Outdated
Comment on lines +8 to +10
cargoNix = crate2nixTools.generatedCargoNix {
name = "statix";
src = statix-src;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this a duplicate?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You're right, generatedCargoNix is called identically in both files, generating the same derivation twice. The fix is to expose cargoNix itself via the overlay and have both files use it. Will restructure.

@Lymah123

Copy link
Copy Markdown
Author

@mightyiam , I am waiting for your answers, it changes the structure significantly.

@mightyiam

Copy link
Copy Markdown
Member

I thought I was waiting for you. You wrote this:
#2719 (comment)

@Lymah123

Copy link
Copy Markdown
Author

I thought I was waiting for you. You wrote this: #2719 (comment)

I am waiting for your answers on my responses under your latest feedbacks

@mightyiam

Copy link
Copy Markdown
Member

As is, I see duplicate code. cargoNix is declared in two different files.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from f0e5ff2 to 2ba8532 Compare August 23, 2026 14:27
Comment thread flake-parts/rust.nix Outdated
@@ -1,11 +1,14 @@
{ ... }:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Lymah123 please

Comment thread flake-parts/statix.nix Outdated
Comment on lines +17 to +19
testPreRun = ''
export INSTA_SNAPSHOT_DIR=${root}/bin/tests/snapshots
'';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If

The integration tests use insta::assert_snapshot! which looks for snapshot files relative to the crate source location

it sounds like if that is the case, there should be no problem finding them. Are you sure of that explanation?

Comment thread flake-parts/statix.nix Outdated
Comment on lines +21 to +28
clippy = statixBuild.override {
crateOverrides = pkgs.defaultCrateOverrides // {
statix = _: {
useClippy = true;
RUSTFLAGS = "-D warnings";
};
};
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of having an additional check, can we have only one check, and that is simply the package, itself, in which clippy is used?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Makes sense, will move useClippy = true and RUSTFLAGS = "-D warnings" into the package build via crateOverrides in packages/statix.nix, so checks.statix = pkgs.statix covers clippy automatically. No separate check needed.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 2ba8532 to 69b9bcf Compare August 23, 2026 14:44
@Lymah123
Lymah123 requested a review from mightyiam August 23, 2026 14:50
@Lymah123

Copy link
Copy Markdown
Author

If

The integration tests use insta::assert_snapshot! which looks for snapshot files relative to the crate source location

it sounds like if that is the case, there should be no problem finding them. Are you sure of that explanation

You're right, tested without it and the tests pass. Insta finds the snapshots via CARGO_MANIFEST_DIR which crate2nix sets correctly. Removing INSTA_SNAPSHOT_DIR

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch 2 times, most recently from b7e7db6 to 35e640b Compare August 24, 2026 03:30
Comment thread flake-parts/rust.nix
@@ -1,11 +1,13 @@
{
_: {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please review your changes as best as you can before expecting anyone else to review them. Such trivial mistakes can be avoided.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Understood. I should have caught that before pushing. I'll be more careful.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This unrelated and undesireable change is still present.

Comment thread flake-parts/statix.nix
Comment on lines -1 to 16
{
_: {
perSystem =
{ pkgs, ... }:
let
statixBuild = pkgs.statix-workspace.workspaceMembers.statix.build;
in
{
treefmt.settings.global.excludes = [ "bin/tests/data/*.nix" ];
checks.build = pkgs.statix;
checks = {
inherit (pkgs) statix;
statix-tests = statixBuild.override {
runTests = true;
};
};
};
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this file need to change? Perhaps if the runTests=true is in the one single derivation, this file can remain the same?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

If runTests = true is in the package itself alongside useClippy = true, then checks.build = pkgs.statix covers everything and flake-parts/statix.nix doesn't need to change. Will move runTests = true into packages/statix.nix and revert flake-parts/statix.nix to its pre-PR state.

@Lymah123
Lymah123 force-pushed the chore/crane-to-crate2nix branch from 35e640b to 1d1b084 Compare August 29, 2026 03:26
@Lymah123
Lymah123 requested a review from mightyiam August 29, 2026 03:39

@mightyiam mightyiam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you think that a pull request should be freshly rebased at the time review is requested?

Comment thread flake-parts/rust.nix
@@ -1,11 +1,13 @@
{
_: {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This unrelated and undesireable change is still present.

Comment thread packages/statix.nix
crateOverrides = defaultCrateOverrides // {
statix = _: {
useClippy = true;
RUSTFLAGS = "-D warnings";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be achieved using capLints instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I am not aware capLints as an idiomatic option. I will investigate and switch to it.

Comment thread overlay.nix
Comment on lines +2 to 5
statix-cargo-nix = prev.callPackage ./packages/cargo-nix.nix { };
statix = prev.callPackage ./packages/statix.nix { };
statix-workspace = prev.callPackage ./packages/statix-workspace.nix { };
statix-vim = prev.callPackage ./packages/statix-vim.nix { };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does exposing these two new intermediate packages provide any value to developers or users? Should they exist as local binding in packages/statix.nix instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Neither of these has value outside of being inputs to building statix itself. So, I think they should exist as local binding in packages/statix.nix.
I agreed with you because, these are implementation details that shouldn't leak into the public overlay.

@Lymah123

Lymah123 commented Aug 29, 2026

Copy link
Copy Markdown
Author

Do you think that a pull request should be freshly rebased at the time review is requested?

Yes. It is a good practice. I will take note of that going forward

@Lymah123

Copy link
Copy Markdown
Author

#2719 (comment)

I removed it, I am wondering how it shows again.

@mightyiam

Copy link
Copy Markdown
Member

Is this waiting on me?

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.

2 participants