Skip to content

Commit a5c360e

Browse files
committed
ci: Add basic NixOS tests
1 parent cc13388 commit a5c360e

3 files changed

Lines changed: 271 additions & 17 deletions

File tree

.github/workflows/ci.yml

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ jobs:
44
nix_parsing:
55
runs-on: ubuntu-latest
66
steps:
7-
- uses: actions/checkout@v2
8-
- uses: cachix/install-nix-action@v12
7+
- uses: actions/checkout@v4
8+
- uses: cachix/install-nix-action@v31
99
- name: Check Nix parsing
1010
run: |
1111
find . -name "*.nix" -exec nix-instantiate --parse --quiet {} >/dev/null +
1212
nix_formatting:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- uses: actions/checkout@v2
16-
- uses: cachix/install-nix-action@v12
15+
- uses: actions/checkout@v4
16+
- uses: cachix/install-nix-action@v31
1717
with:
1818
nix_path: nixpkgs=channel:nixos-unstable
1919
- name: Check Nix formatting
@@ -22,8 +22,8 @@ jobs:
2222
shell_formatting:
2323
runs-on: ubuntu-latest
2424
steps:
25-
- uses: actions/checkout@v2
26-
- uses: cachix/install-nix-action@v12
25+
- uses: actions/checkout@v4
26+
- uses: cachix/install-nix-action@v31
2727
with:
2828
nix_path: nixpkgs=channel:nixos-unstable
2929
- name: Check shell script formatting
@@ -32,10 +32,22 @@ jobs:
3232
shell_error_checking:
3333
runs-on: ubuntu-latest
3434
steps:
35-
- uses: actions/checkout@v2
36-
- uses: cachix/install-nix-action@v12
35+
- uses: actions/checkout@v4
36+
- uses: cachix/install-nix-action@v31
3737
with:
3838
nix_path: nixpkgs=channel:nixos-unstable
3939
- name: Check for shell script errors
4040
run: |
4141
find . -name "*.*sh" -exec nix-shell -p shellcheck --run "shellcheck {}" \;
42+
tests:
43+
runs-on: ubuntu-latest
44+
steps:
45+
- uses: actions/checkout@v4
46+
- uses: cachix/install-nix-action@v31
47+
with:
48+
enable_kvm: true
49+
extra_nix_config: "system-features = nixos-test benchmark big-parallel kvm"
50+
github_access_token: ${{ secrets.GITHUB_TOKEN }}
51+
- name: Flake checks, NixOS tests
52+
run: |
53+
nix flake check -L

flake.lock

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 203 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,207 @@
11
{
2-
outputs = { self }: {
3-
nixosModules.default = self.nixosModules.impermanence;
4-
nixosModules.impermanence = import ./nixos.nix;
2+
inputs = {
3+
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
4+
home-manager.url = "github:nix-community/home-manager";
5+
home-manager.inputs.nixpkgs.follows = "nixpkgs";
6+
};
57

6-
homeManagerModules.default = self.homeManagerModules.impermanence;
7-
homeManagerModules.impermanence = import ./home-manager.nix;
8+
outputs = { self, nixpkgs, home-manager }:
9+
let
10+
inherit (nixpkgs) lib;
11+
forAllSystems = lib.genAttrs lib.systems.flakeExposed;
12+
in
13+
{
14+
lib = import ./lib.nix { inherit lib; };
815

9-
# Deprecated
10-
nixosModule = self.nixosModules.impermanence;
11-
nixosModules.home-manager.impermanence = self.homeManagerModules.impermanence;
12-
};
16+
nixosModules.default = self.nixosModules.impermanence;
17+
nixosModules.impermanence = import ./nixos.nix;
18+
19+
homeManagerModules.default = self.homeManagerModules.impermanence;
20+
homeManagerModules.impermanence = import ./home-manager.nix;
21+
22+
# Deprecated
23+
nixosModule = self.nixosModules.impermanence;
24+
nixosModules.home-manager.impermanence = self.homeManagerModules.impermanence;
25+
26+
devShells = forAllSystems
27+
(system:
28+
let
29+
pkgs = nixpkgs.legacyPackages.${system};
30+
in
31+
{
32+
default =
33+
pkgs.mkShell {
34+
packages = [
35+
pkgs.nixpkgs-fmt
36+
];
37+
};
38+
}
39+
);
40+
41+
checks = forAllSystems
42+
(system:
43+
let
44+
pkgs = nixpkgs.legacyPackages.${system};
45+
mkTest = { name, configuration }:
46+
pkgs.nixosTest {
47+
inherit name;
48+
nodes = {
49+
persistence =
50+
{ config, ... }:
51+
{
52+
virtualisation.diskImage = "./persistent.qcow2";
53+
virtualisation.graphics = false;
54+
55+
boot.initrd.verbose = true;
56+
57+
imports = [
58+
self.nixosModule
59+
configuration
60+
];
61+
62+
services.openssh.enable = true;
63+
64+
users.users.bird = {
65+
isNormalUser = true;
66+
uid = 1000;
67+
};
68+
69+
virtualisation.fileSystems = {
70+
"/" = {
71+
fsType = lib.mkForce "tmpfs";
72+
device = lib.mkForce "none";
73+
neededForBoot = true;
74+
};
75+
"/persistent" = {
76+
device = "/dev/vda";
77+
fsType = "ext4";
78+
neededForBoot = true;
79+
};
80+
};
81+
82+
environment.persistence.main = {
83+
persistentStoragePath = "/persistent";
84+
enableDebugging = true;
85+
files = [
86+
"/etc/machine-id"
87+
"/etc/ssh/ssh_host_ed25519_key"
88+
{ file = "/etc/ssh/ssh_host_ed25519_key.pub"; method = "symlink"; }
89+
"/etc/ssh/ssh_host_rsa_key"
90+
"/etc/ssh/ssh_host_rsa_key.pub"
91+
];
92+
directories = [
93+
{ directory = "/etc/nixos"; mode = "0700"; user = "root"; group = "root"; }
94+
"/var/log"
95+
"/var/lib/bluetooth"
96+
"/var/lib/nixos"
97+
"/var/lib/systemd/coredump"
98+
"/etc/NetworkManager/system-connections"
99+
];
100+
};
101+
};
102+
};
103+
104+
testScript = { nodes, ... }:
105+
let
106+
nixos = nodes.persistence.environment.persistence.main;
107+
nixos-users = nodes.persistence.environment.persistence.main.users.bird or { };
108+
home-manager = nodes.persistence.home-manager.users.bird.home.persistence.main or { };
109+
main = lib.zipAttrsWith (_name: lib.flatten) [ nixos nixos-users home-manager ];
110+
in
111+
''
112+
persistence.start(allow_reboot=True)
113+
114+
persistence.wait_for_unit("sshd.service")
115+
116+
persistence.succeed("echo potato > '/home/bird/.config/persistence_test'")
117+
118+
${lib.concatMapStrings (file:
119+
let
120+
targetFile = self.lib.concatPaths [ file.persistentStoragePath file.filePath ];
121+
in ''
122+
persistence.wait_for_file("${targetFile}", 1)
123+
persistence.succeed("diff ${targetFile} ${file.filePath}")
124+
'')
125+
main.files}
126+
127+
${lib.concatMapStrings (dir:
128+
let
129+
targetDir = self.lib.concatPaths [ dir.persistentStoragePath dir.dirPath ];
130+
in ''
131+
persistence.wait_for_file("${targetDir}", 1)
132+
persistence.succeed("diff <(stat -c '%Hd %Ld %i' ${targetDir}) <(stat -c '%Hd %Ld %i' ${dir.dirPath})")
133+
'')
134+
main.directories}
135+
136+
persistence.reboot()
137+
138+
persistence.wait_for_console_text("reviving user .* with UID")
139+
140+
${lib.concatMapStrings (file:
141+
let
142+
targetFile = self.lib.concatPaths [ file.persistentStoragePath file.filePath ];
143+
in ''
144+
persistence.wait_for_file("${targetFile}", 1)
145+
${if file.method == "auto" then ''
146+
persistence.succeed("diff <(stat -c '%Hd %Ld %i' ${targetFile}) <(stat -c '%Hd %Ld %i' ${file.filePath})")
147+
'' else ''
148+
persistence.succeed("test '${targetFile}' = $(readlink -f ${file.filePath})")
149+
''}
150+
persistence.succeed("diff ${targetFile} ${file.filePath}")
151+
'')
152+
main.files}
153+
'';
154+
};
155+
in
156+
{
157+
nixos = mkTest {
158+
name = "nixos-persistence";
159+
configuration = {
160+
boot.initrd.systemd.enable = true;
161+
162+
environment.persistence.main.users.bird = {
163+
directories = [
164+
"Downloads"
165+
"Music"
166+
"Pictures"
167+
"Documents"
168+
"Videos"
169+
];
170+
files = [
171+
".config/persistence_test"
172+
];
173+
};
174+
};
175+
};
176+
home-manager = mkTest {
177+
name = "hm-persistence";
178+
configuration = { config, ... }:
179+
{
180+
home-manager.users.bird.home.stateVersion = config.system.stateVersion;
181+
182+
imports = [
183+
home-manager.nixosModules.home-manager
184+
];
185+
186+
home-manager.users.bird = {
187+
imports = [ ./home-manager.nix ];
188+
home.persistence.main = {
189+
persistentStoragePath = "/persistent";
190+
directories = [
191+
"Downloads"
192+
"Music"
193+
"Pictures"
194+
"Documents"
195+
"Videos"
196+
];
197+
files = [
198+
".config/persistence_test"
199+
];
200+
};
201+
};
202+
};
203+
};
204+
}
205+
);
206+
};
13207
}

0 commit comments

Comments
 (0)