nix: update checks

This takes inspiration from the `heartwood/flake.nix`[^1] file.

It runs checks at the MSRV but uses a rust-toolchain to allow for
newer development.

To obtain the latest 1.90 toolchain, the NixOS release was update to
the latest 25.11.

[^1]: https://rosa.radicle.xyz/raw/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/4a5a51e6e550456c75d1a2182b0eafb9c3033ec0/flake.nix
This commit is contained in:
Fintan Halpenny
2025-12-08 15:11:21 +00:00
parent abcb05a2bd
commit 320f316674
3 changed files with 246 additions and 143 deletions
Generated
+82 -22
View File
@@ -3,11 +3,11 @@
"advisory-db": {
"flake": false,
"locked": {
"lastModified": 1739168963,
"narHash": "sha256-Pi7XjqacMBPEsCQf2GqPb2JfPB0Qkbi2xYrYtjoy7OE=",
"lastModified": 1765194944,
"narHash": "sha256-/vOedVUVYyZugEqJ9PPOmjjaMX215geoAY3yCsxHtI8=",
"owner": "rustsec",
"repo": "advisory-db",
"rev": "110cb7a5c98b088f131096c936ca2f540de717d8",
"rev": "3cb5be8c9c1af51e6e27236234c44b3b87b1b125",
"type": "github"
},
"original": {
@@ -18,11 +18,11 @@
},
"crane": {
"locked": {
"lastModified": 1739053031,
"narHash": "sha256-LrMDRuwAlRFD2T4MgBSRd1s2VtOE+Vl1oMCNu3RpPE0=",
"lastModified": 1765145449,
"narHash": "sha256-aBVHGWWRzSpfL++LubA0CwOOQ64WNLegrYHwsVuVN7A=",
"owner": "ipetkov",
"repo": "crane",
"rev": "112e6591b2d6313b1bd05a80a754a8ee42432a7e",
"rev": "69f538cdce5955fcd47abfed4395dc6d5194c1c5",
"type": "github"
},
"original": {
@@ -37,11 +37,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1739169164,
"narHash": "sha256-2+/6/2rHsMjlrulkrjZbwthCQiQpeW2pukRFaaUMLy8=",
"lastModified": 1765003156,
"narHash": "sha256-k4YrPUhRj7Ciq385vREU57RHiDFycY5RaJwdCOmsLhU=",
"owner": "nix-community",
"repo": "fenix",
"rev": "d7616af878cd0cb7f940b470440347920395be0c",
"rev": "e8361cc010853d17740a63aae00385061ac9de51",
"type": "github"
},
"original": {
@@ -49,6 +49,22 @@
"type": "indirect"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1761588595,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
@@ -67,13 +83,56 @@
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1765016596,
"narHash": "sha256-rhSqPNxDVow7OQKi4qS5H8Au0P4S3AYbawBSmJNUtBQ=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "548fc44fca28a5e81c5d6b846e555e6b9c2a5a3c",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1739020877,
"narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
"lastModified": 1764667669,
"narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
"rev": "418468ac9527e799809c900eda37cbff999199b6",
"type": "github"
},
"original": {
@@ -85,16 +144,16 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1739188370,
"narHash": "sha256-2h/5uQaKwQeRXIgpOJpzgeO3qe93AonbJFk0CxTSygY=",
"lastModified": 1765190540,
"narHash": "sha256-kE8LyaA5TsFILJrnKI9Zb2Vow0eycYuSaB1qmYmXaes=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8ae4ee7978617d3af98721a62f14f25befc0beef",
"rev": "78c294509cf24e3ece22d00c02cca20f377a9c45",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.11",
"ref": "release-25.11",
"repo": "nixpkgs",
"type": "github"
}
@@ -105,6 +164,7 @@
"crane": "crane",
"fenix": "fenix",
"flake-utils": "flake-utils",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
}
@@ -112,11 +172,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1739099919,
"narHash": "sha256-YUdM2yZzQIbakgc2LdVmkgJMYTqeTu3YdWGgFfiZiTg=",
"lastModified": 1764925941,
"narHash": "sha256-zldc1SrUIhGMdQp+0woSqvBS51Mi8PW6JukONBQXZBY=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "35181e167efb94d5090df588e6af9f93250421f3",
"rev": "2cbf3587d36dfc7b701ebb744d3dd5064355d04f",
"type": "github"
},
"original": {
@@ -133,11 +193,11 @@
]
},
"locked": {
"lastModified": 1739154531,
"narHash": "sha256-QGeN6e0nMJlNLzm3Y2A7P6riXhQXMeCXLZ7yajZYFQM=",
"lastModified": 1765161692,
"narHash": "sha256-XdY9AFzmgRPYIhP4N+WiCHMNxPoifP5/Ld+orMYBD8c=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "035dac86ab7ce5c1e8a4d59dfe85e6911a3526ea",
"rev": "7ed7e8c74be95906275805db68201e74e9904f07",
"type": "github"
},
"original": {
+160 -121
View File
@@ -2,12 +2,17 @@
description = "Improved types and functionality for using Git in Radicle";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/release-24.11";
nixpkgs.url = "github:NixOS/nixpkgs/release-25.11";
crane = {
url = "github:ipetkov/crane";
};
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs = {
@@ -36,7 +41,7 @@
advisory-db,
rust-overlay,
...
}:
} @ inputs:
flake-utils.lib.eachDefaultSystem (system: let
pname = "radicle-git";
pkgs = import nixpkgs {
@@ -46,150 +51,184 @@
inherit (pkgs) lib;
rustToolChain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain;
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolChain;
msrv = let
msrv = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.rust-version;
in rec {
toolchain = pkgs.rust-bin.stable.${msrv}.default;
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
commonArgs = mkCommonArgs craneLib;
};
rustup = rec {
toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
commonArgs = mkCommonArgs craneLib;
};
srcFilters = path: type:
# Allow data/git-platinum.tgz
(lib.hasSuffix "\.tgz" path)
||
# Default filter from crane (allow .rs files)
(craneLib.filterCargoSources path type);
(rustup.craneLib.filterCargoSources path type);
src = lib.cleanSourceWith {
src = ./.;
filter = srcFilters;
};
# Common arguments can be set here to avoid repeating them later
commonArgs = {
inherit pname;
basicArgs = {
inherit src;
pname = "radicle-git";
version = "0.1.0";
strictDeps = true;
buildInputs =
[
pkgs.git
# Add additional build inputs here
]
++ lib.optionals pkgs.stdenv.isDarwin [
# Additional darwin specific inputs can be set here
pkgs.libiconv
];
};
# Build *just* the cargo dependencies, so we can reuse
# all of that work (e.g. via cachix) when running in CI
cargoArtifacts =
craneLib.buildDepsOnly commonArgs;
# Common arguments can be set here to avoid repeating them later
mkCommonArgs = craneLib:
basicArgs
// {
# Build *just* the cargo dependencies, so we can reuse
# all of that work (e.g. via cachix) when running in CI
cargoArtifacts = craneLib.buildDepsOnly basicArgs;
# Build the actual crate itself, reusing the dependency
# artifacts from above.
nativeBuildInputs = with pkgs; [
git
];
buildInputs = lib.optionals pkgs.stdenv.buildPlatform.isDarwin (with pkgs; [
darwin.apple_sdk.frameworks.Security
libiconv
]);
};
radicle-git-ext = craneLib.buildPackage (commonArgs
// {
inherit (craneLib.crateNameFromCargoToml {cargoToml = ./radicle-git-ext/Cargo.toml;});
doCheck = false;
inherit cargoArtifacts;
});
radicle-std-ext = craneLib.buildPackage (commonArgs
// {
inherit (craneLib.crateNameFromCargoToml {cargoToml = ./radicle-std-ext/Cargo.toml;});
doCheck = false;
inherit cargoArtifacts;
});
radicle-surf = craneLib.buildPackage (commonArgs
// {
inherit (craneLib.crateNameFromCargoToml {cargoToml = ./radicle-surf/Cargo.toml;});
inherit cargoArtifacts;
doCheck = false;
});
# Test crates
radicle-git-ext-test = craneLib.buildPackage (commonArgs
// {
inherit (craneLib.crateNameFromCargoToml {cargoToml = ./radicle-git-ext/t/Cargo.toml;});
inherit cargoArtifacts;
doCheck = false;
});
radicle-surf-test = craneLib.buildPackage (commonArgs
// {
inherit (craneLib.crateNameFromCargoToml {cargoToml = ./radicle-surf/t/Cargo.toml;});
inherit cargoArtifacts;
doCheck = false;
});
buildCrate = rust: name: let
# Test crates live under `{crate}/t` but are called `{crate}-t`.
# Check if it is a test crate, and safely remove the suffix and build the Cargo.toml path.
isTest = lib.hasSuffix "-test" name;
pname = lib.removeSuffix "-test" name;
cargoToml = src + "/${pname}${lib.optionalString isTest "/t"}/Cargo.toml";
in
rust.craneLib.buildPackage (rust.commonArgs
// {
inherit (rust.craneLib.crateNameFromCargoToml {inherit cargoToml;}) pname version;
cargoExtraArgs = "-p ${pname}";
doCheck = false;
});
buildCrates = {
rust ? rustup,
prefix ? "",
}:
builtins.listToAttrs (map
(name: lib.nameValuePair (prefix + name) (buildCrate rust name))
[
"radicle-std-ext"
"radicle-git-ext"
"radicle-git-ext-test"
"radicle-surf"
"radicle-surf-test"
]);
in {
# Formatter
formatter = pkgs.alejandra;
# Set of checks that are run: `nix flake check`
checks = {
# Build the crate as part of `nix flake check` for convenience
inherit radicle-git-ext;
inherit radicle-surf;
inherit radicle-git-ext-test;
inherit radicle-surf-test;
# Run clippy (and deny all warnings) on the crate source,
# again, reusing the dependency artifacts from above.
#
# Note that this is done as a separate derivation so that
# we can block the CI if there are issues here, but not
# prevent downstream consumers from building our crate by itself.
clippy = craneLib.cargoClippy (commonArgs
// {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
});
doc = craneLib.cargoDoc (commonArgs
// {
inherit cargoArtifacts;
});
# Check formatting
fmt = craneLib.cargoFmt {
inherit pname;
inherit src;
};
# Audit dependencies
audit = craneLib.cargoAudit {
inherit src advisory-db;
};
# Audit licenses
deny = craneLib.cargoDeny {
inherit pname;
inherit src;
};
# Run tests with cargo-nextest
nextest = craneLib.cargoNextest (commonArgs
// {
inherit cargoArtifacts;
partitions = 1;
partitionType = "count";
nativeBuildInputs = [
# git is required so the sandbox can access it.
pkgs.git
checks =
(buildCrates {
rust = msrv;
prefix = "msrv-";
})
// {
pre-commit-check = inputs.git-hooks.lib.${system}.run {
src = ./.;
settings.rust.check.cargoDeps = pkgs.rustPlatform.importCargoLock {lockFile = ./Cargo.lock;};
default_stages = [
"pre-commit"
"pre-push"
];
# Ensure dev is used since we rely on env variables being
# set in tests.
buildPhase = ''
export CARGO_PROFILE=dev;
'';
});
};
hooks = {
alejandra.enable = true;
codespell = {
enable = true;
entry = "${lib.getExe pkgs.codespell} -w";
types = ["text"];
};
rustfmt = {
enable = true;
fail_fast = true;
packageOverrides.rustfmt = rustup.toolchain;
};
cargo-check = {
enable = true;
name = "cargo check";
after = ["rustfmt"];
fail_fast = true;
};
cargo-doc = let
# We wrap `cargo` in order to set an environment variable that
# gives us a non-zero exit on warning.
command =
pkgs.writeShellScript
"cargo"
"RUSTDOCFLAGS='--deny warnings' ${lib.getExe' rustup.toolchain "cargo"} $@";
in {
enable = true;
name = "cargo doc";
after = ["rustfmt"];
fail_fast = true;
entry = "${command} doc --workspace --all-features --no-deps";
files = "\\.rs$";
pass_filenames = false;
};
clippy = {
enable = true;
name = "cargo clippy";
stages = ["pre-push"]; # Only pre-push, because it takes a while.
settings = {
allFeatures = true;
denyWarnings = true;
};
packageOverrides = {
cargo = rustup.toolchain;
clippy = rustup.toolchain;
};
};
shellcheck.enable = true;
};
};
packages = {
inherit radicle-git-ext;
inherit radicle-surf;
inherit radicle-git-ext-test;
inherit radicle-surf-test;
};
# Run clippy (and deny all warnings) on the crate source,
# again, reusing the dependency artifacts from above.
#
# Note that this is done as a separate derivation so that
# we can block the CI if there are issues here, but not
# prevent downstream consumers from building our crate by itself.
doc = rustup.craneLib.cargoDoc rustup.commonArgs;
deny = rustup.craneLib.cargoDeny rustup.commonArgs;
fmt = rustup.craneLib.cargoFmt basicArgs;
devShells.default = craneLib.devShell {
audit = rustup.craneLib.cargoAudit {
inherit src advisory-db;
};
# Run tests with cargo-nextest
nextest = rustup.craneLib.cargoNextest (rustup.commonArgs
// {
partitions = 1;
partitionType = "count";
nativeBuildInputs = [
# git is required so the sandbox can access it.
pkgs.git
];
# Ensure dev is used since we rely on env variables being
# set in tests.
buildPhase = ''
export CARGO_PROFILE=dev;
'';
});
};
packages = buildCrates {};
devShells.default = rustup.craneLib.devShell {
# Extra inputs can be added here; cargo and rustc are provided by default.
packages = [
pkgs.cargo-deny
+4
View File
@@ -0,0 +1,4 @@
[toolchain]
channel = "1.90"
profile = "default"
components = [ "rust-src" ]