Split CI into separate flake, test multiple releases

This is so that users won't need to download our pinned
nixpkgs/nix-darwin versions.
This commit is contained in:
Zhaofeng Li
2025-05-25 15:43:00 -06:00
parent bb068c5df0
commit 09c0111fe0
9 changed files with 432 additions and 150 deletions
+24 -29
View File
@@ -5,41 +5,36 @@ on:
pull_request:
jobs:
check:
runs-on: macos-latest
nix-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v3
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- name: Test nuke-homebrew-repository
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v17
- id: set-matrix
name: Generate Nix Matrix
run: |
nix build .#nuke-homebrew-repository.passthru.tests.test-nuke -L
- name: Install some package with Homebrew
run: |
brew install unbound
- name: Add a third-party tap imperatively
run: |
brew tap koekeishiya/formulae
set -Eeu
matrix="$(nix eval --json '.#githubActions.matrix')"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
check:
name: ${{ matrix.name }} (${{ matrix.system }})
needs: nix-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}}
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v17
- name: Set up /run for nix-darwin
run: |
printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf
sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
- name: Migrate existing Homebrew installation (imperative taps)
- name: Run test
run: |
sudo rm /etc/bashrc
./ci/activate-example.sh migrate
- name: Check that we can still use the unbound package
run: $(brew --prefix)/sbin/unbound -V
- name: Check that we can still use the tap that we added imperatively
run: brew install koekeishiya/formulae/yabai
#- name: Migrate to fully-declarative tap management
# run: |
# false
export NIX_HOMEBREW_CI=1
ci_script=$(nix build -L '.#${{ matrix.attr }}' --print-out-paths)
"$ci_script"
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
DIR=$(dirname $0)
if [[ "$#" != "1" ]]; then
>&2 echo "Usage: $0 [example]"
exit 1
fi
example="$1"
system="$(nix eval --raw --impure --expr 'builtins.currentSystem')"
>&2 echo "System: ${system}"
systemProfile="$(nix build "./${DIR}/..#ci.${system}.${example}.system" -L --no-link --print-out-paths)"
>&2 echo "Built $systemProfile"
sudo rm "/etc/nix/nix.conf"
sudo "$systemProfile/activate"
"$systemProfile/activate-user"
# vim: set et ts=2 sw=2:
-23
View File
@@ -1,23 +0,0 @@
# Activates example configurations on CI
{ self, pkgs, nix-darwin, ... }:
let
inherit (pkgs) lib system;
makeProfile = example: nix-darwin.lib.darwinSystem {
inherit system pkgs;
modules = [
self.darwinModules.nix-homebrew
(../examples + "/${example}.nix")
{
documentation.enable = false;
services.nix-daemon.enable = true;
nix-homebrew = {
user = lib.mkForce "runner";
};
}
];
};
in {
migrate = makeProfile "migrate";
}
+11
View File
@@ -0,0 +1,11 @@
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
flakeCompat = import (fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
});
flake = flakeCompat {
src = ./.;
};
in
flake.defaultNix.outputs
Generated
+153
View File
@@ -0,0 +1,153 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"nix-darwin_25_05": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1748044287,
"narHash": "sha256-9bJzyUX5+HXYmI60WMGYXXDdhGbSh1Le6yBM4og3K7E=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "2456ff5c95edfc3b197cb012b947012faed77591",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"ref": "nix-darwin-25.05",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-darwin_unstable": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1748149228,
"narHash": "sha256-mmonYFesFo42UUS49Hd0bcbVJRWX/aHBCDYUkkvylf4=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "a9939228f661df370c4094fe85f683e45d761dbe",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"nixpkgs_unstable"
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1747953325,
"narHash": "sha256-y2ZtlIlNTuVJUZCqzZAhIw5rrKP4DOSklev6c8PyCkQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "55d1f923c480dadce40f5231feb472e81b0bab48",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-25.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1747728033,
"narHash": "sha256-NnXFQu7g4LnvPIPfJmBuZF7LFy/fey2g2+LCzjQhTUk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2f9173bde1d3fbf1ad26ff6d52f952f9e9da52ea",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_25_05": {
"locked": {
"lastModified": 1748162331,
"narHash": "sha256-rqc2RKYTxP3tbjA+PB3VMRQNnjesrT0pEofXQTrMsS8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7c43f080a7f28b2774f3b3f43234ca11661bf334",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_unstable": {
"locked": {
"lastModified": 1748026106,
"narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "063f43f2dbdef86376cc29ad646c45c46e93234c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"nix-darwin_25_05": "nix-darwin_25_05",
"nix-darwin_unstable": "nix-darwin_unstable",
"nix-github-actions": "nix-github-actions",
"nixpkgs_25_05": "nixpkgs_25_05",
"nixpkgs_unstable": "nixpkgs_unstable"
}
}
},
"root": "root",
"version": 7
}
+130
View File
@@ -0,0 +1,130 @@
# Only used for development & CI
{
inputs = {
nixpkgs_unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs_25_05.url = "github:NixOS/nixpkgs/nixos-25.05";
nix-darwin_unstable.url = "github:nix-darwin/nix-darwin";
nix-darwin_25_05.url = "github:nix-darwin/nix-darwin/nix-darwin-25.05";
nix-github-actions = {
url = "github:nix-community/nix-github-actions";
inputs.nixpkgs.follows = "nixpkgs_unstable";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs =
inputs:
let
inherit (inputs.nixpkgs_unstable) lib;
supportedSystems = [
"x86_64-darwin"
"aarch64-darwin"
];
releases = {
"unstable" = {
nixpkgs = inputs.nixpkgs_unstable;
nix-darwin = inputs.nix-darwin_unstable;
};
"25.05" = {
nixpkgs = inputs.nixpkgs_25_05;
nix-darwin = inputs.nix-darwin_25_05;
};
};
githubPlatforms = {
"aarch64-darwin" = "macos-15";
"x86_64-darwin" = "macos-15";
};
matrix =
let
names = {
release = builtins.attrNames releases;
test = builtins.attrNames (
import ./tests.nix {
self = null;
pkgs = null;
nix-darwin = null;
}
);
};
in
lib.pipe names [
lib.cartesianProduct
(map (setup: {
name = "${setup.test}-${setup.release}";
value = setup;
}))
lib.listToAttrs
];
forAllSystems =
f: lib.genAttrs supportedSystems (system: f inputs.nixpkgs_unstable.legacyPackages.${system});
makeCi =
{ self, brew-src }:
let
assembleTest =
{
system,
release,
test,
}:
let
inputs' = releases.${release};
pkgs = inputs'.nixpkgs.legacyPackages.${system};
tests = import ./tests.nix {
inherit self pkgs;
inherit (inputs') nix-darwin;
};
in
tests.${test};
ciTests = lib.genAttrs supportedSystems (
system:
lib.mapAttrs (
name:
{ release, test }:
assembleTest {
inherit system release test;
}
) matrix
);
ciScripts = lib.mapAttrs (
system: tests: lib.mapAttrs (name: test: test.config.system.build.ci-script) tests
) ciTests;
in
{
inherit ciTests;
packages = forAllSystems (
pkgs:
pkgs.callPackages (self + "/pkgs") {
inherit brew-src;
}
);
devShell = forAllSystems (
pkgs:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
nixfmt-rfc-style
];
BREW_SRC = brew-src;
}
);
githubActions = inputs.nix-github-actions.lib.mkGithubMatrix {
checks = ciScripts;
platforms = githubPlatforms;
};
};
in
{
inherit makeCi;
};
}
+107
View File
@@ -0,0 +1,107 @@
{
self,
pkgs,
nix-darwin,
}:
let
inherit (pkgs) lib system;
tools = self.packages.${pkgs.system};
makeTest =
module:
nix-darwin.lib.darwinSystem {
inherit system pkgs;
modules = [
self.darwinModules.nix-homebrew
module
(
{
pkgs,
lib,
config,
...
}:
{
options = {
ci = {
preScript = lib.mkOption {
type = lib.types.lines;
default = "";
};
script = lib.mkOption {
type = lib.types.lines;
default = ''
sudo rm -f /etc/bashrc /etc/nix/nix.conf /etc/nix/nix.custom.conf
sudo "${config.system.build.toplevel}/activate"
export PATH=/run/current-system/sw/bin:$PATH
'';
};
postScript = lib.mkOption {
type = lib.types.lines;
default = "";
};
};
};
config = {
documentation.enable = false;
system.stateVersion = 6;
nix-homebrew = {
user = lib.mkForce "runner";
};
system.build.ci-script = pkgs.writeShellScript "ci-script.sh" ''
set -euo pipefail
if [[ -z "''${NIX_HOMEBREW_CI:-}" ]]; then
>&2 echo "This script can only be run on nix-homebrew CI."
exit 1
fi
set -x
${config.ci.preScript}
${config.ci.script}
${config.ci.postScript}
'';
};
}
)
];
};
in
{
migrate = makeTest (
{ pkgs, ... }:
{
imports = [
(self + "/examples/migrate.nix")
];
nix-homebrew.enableRosetta = lib.mkForce pkgs.stdenv.hostPlatform.isAarch64;
# We only have Apple Silicon instances - Only test the install steps on native
# Apple Silicon for now
ci.preScript = lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 ''
>&2 echo "Installing some package with Homebrew"
brew install unbound
>&2 echo "Adding a third-party tap imperatively"
brew tap koekeishiya/formulae
'';
ci.postScript = ''
>&2 echo "Checking brew"
which brew
'' + lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 ''
>&2 echo "Checking that we can still use the unbound package"
$(brew --prefix)/sbin/unbound -V
>&2 echo "Checking that we can still use the tap we added imperatively"
brew install koekeishiya/formulae/yabai
'';
}
);
nuke-homebrew-repository = makeTest {
ci.script = lib.mkForce ''
cat "${tools.nuke-homebrew-repository.passthru.tests.test-nuke}"
'';
};
}
Generated
+1 -50
View File
@@ -17,58 +17,9 @@
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1716329735,
"narHash": "sha256-ap51w+VqG21vuzyQ04WrhI2YbWHd3UGz0e7dc/QQmoA=",
"owner": "LnL7",
"repo": "nix-darwin",
"rev": "eac4f25028c1975a939c8f8fba95c12f8a25e01c",
"type": "github"
},
"original": {
"owner": "LnL7",
"repo": "nix-darwin",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1687274257,
"narHash": "sha256-TutzPriQcZ8FghDhEolnHcYU2oHIG5XWF+/SUBNnAOE=",
"path": "/nix/store/22qgs3skscd9bmrxv9xv4q5d4wwm5ppx-source",
"rev": "2c9ecd1f0400076a4d6b2193ad468ff0a7e7fdc5",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1746328495,
"narHash": "sha256-uKCfuDs7ZM3QpCE/jnfubTg459CnKnJG/LwqEVEdEiw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "979daf34c8cacebcd917d540070b52a3c2b9b16e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"brew-src": "brew-src",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs_2"
"brew-src": "brew-src"
}
}
},
+6 -26
View File
@@ -2,42 +2,20 @@
description = "Homebrew installation manager for nix-darwin";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nix-darwin.url = "github:LnL7/nix-darwin";
brew-src = {
url = "github:Homebrew/brew/4.5.2";
flake = false;
};
};
outputs = { self, nixpkgs, nix-darwin, brew-src, ... } @ inputs: let
# System types to support.
supportedSystems = [ "x86_64-darwin" "aarch64-darwin" ];
outputs = { self, brew-src }: let
flakeLock = builtins.fromJSON (builtins.readFile ./flake.lock);
brewVersion = flakeLock.nodes.brew-src.original.ref;
forAllSystems =
function:
nixpkgs.lib.genAttrs supportedSystems (
system: function nixpkgs.legacyPackages.${system}
);
ci = (import ./ci/flake-compat.nix).makeCi {
inherit self brew-src;
};
in {
packages = forAllSystems (pkgs: pkgs.callPackage ./pkgs {
inherit (inputs) brew-src;
});
devShell = forAllSystems (pkgs: pkgs.mkShell {
nativeBuildInputs = with pkgs; [
];
BREW_SRC = brew-src;
});
ci = forAllSystems (pkgs: import ./ci (inputs // {
inherit pkgs;
}));
darwinModules = {
nix-homebrew = { lib, ... }: {
imports = [
@@ -49,5 +27,7 @@
});
};
};
inherit (ci) packages devShell ciTests githubActions;
};
}