ci: speed up nix container build with crane dependency caching

Replace rustPlatform.buildRustPackage with crane to split the Rust
compilation into a deps-only derivation (keyed on Cargo.lock) and a
source derivation. The deps derivation is cached in the Nix store
between CI runs, avoiding full recompilation on every deploy.
This commit is contained in:
Jon Seager 2026-02-15 11:58:29 +00:00
parent 1075986554
commit bfe4f7d67d
No known key found for this signature in database
2 changed files with 74 additions and 31 deletions

View file

@ -1,5 +1,20 @@
{
"nodes": {
"crane": {
"locked": {
"lastModified": 1771121070,
"narHash": "sha256-aIlv7FRXF9q70DNJPI237dEDAznSKaXmL5lfK/Id/bI=",
"owner": "ipetkov",
"repo": "crane",
"rev": "a2812c19f1ed2e5ed5ce2ef7109798b575c180e1",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
@ -110,6 +125,7 @@
},
"root": {
"inputs": {
"crane": "crane",
"flake-parts": "flake-parts",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs",

View file

@ -6,6 +6,7 @@
rust-overlay.url = "github:oxalica/rust-overlay";
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
flake-parts.url = "github:hercules-ci/flake-parts";
crane.url = "github:ipetkov/crane";
treefmt-nix.url = "github:numtide/treefmt-nix";
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
@ -38,7 +39,7 @@
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
inherit (pkgs) lib rustPlatform;
inherit (pkgs) lib;
rust = pkgs.rust-bin.stable.latest.default.override {
extensions = [
@ -49,6 +50,22 @@
];
};
craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rust;
# Source filtered to only Cargo-relevant files (for dependency caching)
cargoSource = craneLib.cleanCargoSource ./.;
# Full source including templates, static assets, and migrations
src = lib.cleanSourceWith {
src = lib.cleanSource ./.;
filter =
path: type:
(craneLib.filterCargoSources path type)
|| (lib.hasInfix "/templates" path)
|| (lib.hasInfix "/static" path)
|| (lib.hasInfix "/migrations" path);
};
prettierWithJinja = pkgs.writeShellScriptBin "prettier" ''
export NODE_PATH="${pkgs.prettier}/lib/node_modules"
exec ${pkgs.prettier}/bin/prettier "$@"
@ -56,16 +73,10 @@
cargoToml = lib.trivial.importTOML ./Cargo.toml;
version = cargoToml.package.version;
in
{
packages = {
default = self.packages.${system}.brewlog;
brewlog = rustPlatform.buildRustPackage {
commonArgs = {
pname = "brewlog";
inherit version;
src = lib.cleanSource ./.;
cargoLock.lockFile = ./Cargo.lock;
nativeBuildInputs = with pkgs; [
autoPatchelfHook
@ -80,8 +91,23 @@
stdenv.cc.cc.lib
];
env.GIT_HASH = self.shortRev or self.dirtyShortRev or "dev";
env.LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.openssl ];
};
# Pre-compiled dependencies — only rebuilds when Cargo.lock changes
cargoArtifacts = craneLib.buildDepsOnly (commonArgs // { src = cargoSource; });
in
{
packages = {
default = self.packages.${system}.brewlog;
brewlog = craneLib.buildPackage (
commonArgs
// {
inherit src cargoArtifacts;
env = commonArgs.env // {
GIT_HASH = self.shortRev or self.dirtyShortRev or "dev";
};
meta = {
description = "Log your favourite roasters, roasts, brews and cafes";
@ -91,7 +117,8 @@
platforms = lib.platforms.unix;
maintainers = with lib.maintainers; [ jnsgruk ];
};
};
}
);
brewlog-container = pkgs.dockerTools.buildImage {
name = "brewlog";