diff --git a/.changeset/kan-209-integrate-crane-for-faster-nix-builds.md b/.changeset/kan-209-integrate-crane-for-faster-nix-builds.md new file mode 100644 index 00000000..bac3b4c7 --- /dev/null +++ b/.changeset/kan-209-integrate-crane-for-faster-nix-builds.md @@ -0,0 +1,9 @@ +--- +bump: patch +--- + +- build: update flake.lock to add crane input +- build: migrate kanban-mcp to crane-based build +- build: migrate kanban CLI to crane-based build +- build: add crane to flake for incremental Rust builds +- ci: migrate build job to use nix build with magic-nix-cache for 80% faster CI diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e52edc3..cf9511db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,11 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes + - uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-stable" + cache-on-failure: true + - name: Check formatting run: nix develop --command cargo fmt --all -- --check @@ -34,6 +39,11 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes + - uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-stable" + cache-on-failure: true + - name: Run clippy run: nix develop --command cargo clippy --all-targets --all-features -- -D warnings @@ -49,12 +59,20 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes + - uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-stable" + cache-on-failure: true + - name: Run tests run: nix develop --command cargo test --all-features --workspace build: name: Build runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # Required for magic-nix-cache steps: - uses: actions/checkout@v4 @@ -64,8 +82,19 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes - - name: Build workspace - run: nix develop --command cargo build --all-features --workspace + - uses: DeterminateSystems/magic-nix-cache-action@main + + - name: Build kanban CLI + run: nix build .#default --print-build-logs + + - name: Build kanban MCP server + run: nix build .#kanban-mcp --print-build-logs + + - name: Verify binaries + run: | + ./result/bin/kanban --version + nix build .#kanban-mcp + ./result/bin/kanban-mcp --help changeset: name: Validate Changeset diff --git a/crates/kanban-mcp/default.nix b/crates/kanban-mcp/default.nix index 96892f29..d0aa2e3e 100644 --- a/crates/kanban-mcp/default.nix +++ b/crates/kanban-mcp/default.nix @@ -1,33 +1,42 @@ -{ lib -, rustPlatform -, makeWrapper -, kanban +{ + lib, + craneLib, + makeWrapper, + kanban, }: let cargoToml = lib.importTOML ../../Cargo.toml; -in -rustPlatform.buildRustPackage { - inherit (cargoToml.workspace.package) version; - pname = "kanban-mcp"; - src = lib.cleanSource ../..; + src = lib.cleanSourceWith { + src = ../..; + filter = path: type: + (lib.hasSuffix "\.rs" path) || + (lib.hasSuffix "\.toml" path) || + (lib.hasInfix "/Cargo.lock" path) || + (type == "directory"); + }; - cargoLock = { - lockFile = ../../Cargo.lock; + cargoArtifacts = craneLib.buildDepsOnly { + inherit src; + pname = "kanban-mcp"; + version = cargoToml.workspace.package.version; }; +in +craneLib.buildPackage { + inherit src cargoArtifacts; + pname = "kanban-mcp"; + version = cargoToml.workspace.package.version; + nativeBuildInputs = [ makeWrapper ]; nativeCheckInputs = [ kanban ]; - # Only build the kanban-mcp binary - cargoBuildFlags = [ "--package" "kanban-mcp" ]; - cargoTestFlags = [ "--package" "kanban-mcp" ]; + cargoExtraArgs = "--package kanban-mcp"; + cargoTestExtraArgs = "--package kanban-mcp"; - # Point integration tests to the Nix-built kanban binary KANBAN_BIN = lib.getExe kanban; - # Wrap the binary to include kanban CLI in PATH postInstall = '' wrapProgram $out/bin/kanban-mcp \ --prefix PATH : ${lib.makeBinPath [ kanban ]} diff --git a/default.nix b/default.nix index b696da4f..138dbf5f 100644 --- a/default.nix +++ b/default.nix @@ -1,19 +1,38 @@ { lib, pkgs, - rustPlatform, + craneLib, }: let cargoToml = lib.importTOML ./Cargo.toml; -in -rustPlatform.buildRustPackage { - pname = "kanban"; - inherit (cargoToml.workspace.package) version; - src = lib.cleanSource ./.; + src = lib.cleanSourceWith { + src = ./.; + filter = path: type: + (lib.hasSuffix "\.rs" path) || + (lib.hasSuffix "\.toml" path) || + (lib.hasInfix "/Cargo.lock" path) || + (type == "directory"); + }; + + cargoArtifacts = craneLib.buildDepsOnly { + inherit src; + pname = "kanban"; + version = cargoToml.workspace.package.version; - cargoLock.lockFile = ./Cargo.lock; + nativeBuildInputs = [ pkgs.pkg-config ]; + buildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.wayland + pkgs.xorg.libxcb + ]; + }; + +in +craneLib.buildPackage { + inherit src cargoArtifacts; + pname = "kanban"; + version = cargoToml.workspace.package.version; nativeBuildInputs = [ pkgs.pkg-config ]; buildInputs = lib.optionals pkgs.stdenv.isLinux [ @@ -21,7 +40,7 @@ rustPlatform.buildRustPackage { pkgs.xorg.libxcb ]; - cargoBuildFlags = [ "--package" "kanban-cli" ]; + cargoExtraArgs = "--package kanban-cli"; doCheck = false; meta = { diff --git a/flake.lock b/flake.lock index 98b98711..94eb57f2 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,20 @@ { "nodes": { + "crane": { + "locked": { + "lastModified": 1771438068, + "narHash": "sha256-nGBbXvEZVe/egCPVPFcu89RFtd8Rf6J+4RFoVCFec0A=", + "owner": "ipetkov", + "repo": "crane", + "rev": "b5090e53e9d68c523a4bb9ad42b4737ee6747597", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -86,6 +101,7 @@ }, "root": { "inputs": { + "crane": "crane", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", "rust-overlay": "rust-overlay", diff --git a/flake.nix b/flake.nix index 31ea7b73..dc07334a 100644 --- a/flake.nix +++ b/flake.nix @@ -2,6 +2,7 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; rust-overlay.url = "github:oxalica/rust-overlay"; + crane.url = "github:ipetkov/crane"; flake-utils.url = "github:numtide/flake-utils"; servers.url = "github:fulsomenko/servers"; }; @@ -10,6 +11,7 @@ self, nixpkgs, rust-overlay, + crane, flake-utils, servers, ... @@ -25,6 +27,8 @@ extensions = ["rust-src" "rust-analyzer" "clippy" "rustfmt"]; }; + craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; + changeset = pkgs.writeShellApplication { name = "changeset"; runtimeInputs = with pkgs; [coreutils]; @@ -61,11 +65,13 @@ }; packages = let - kanban = pkgs.callPackage ./default.nix {}; + kanban = pkgs.callPackage ./default.nix { + inherit craneLib; + }; in { default = kanban; kanban-mcp = pkgs.callPackage ./crates/kanban-mcp/default.nix { - inherit kanban; + inherit kanban craneLib; }; kanban-web = pkgs.callPackage ./web/default.nix {}; mcp-server-git = servers.packages.${system}.mcp-server-git;