-
Notifications
You must be signed in to change notification settings - Fork 1
/
nixos-rebuild.py
executable file
·104 lines (98 loc) · 3.23 KB
/
nixos-rebuild.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env python3
# because nixos-rebuild --target-host is too flaky
import json
import os
import subprocess
import sys
with open(os.path.expanduser("~/var/addresses.json"), "rt") as f:
opts = json.loads(f.read())
def main():
args = sys.argv
cfg = args[1]
if "@" in cfg:
cfg, addr = cfg.split("@")
else:
addr = opts["addresses"][cfg]
build_host = opts["build_host"].get(cfg)
act = args[2]
assert act in ["boot", "switch", "test", "build"]
args = args[3:]
args.extend(
[
"--option",
"extra-builtins-file",
os.path.dirname(__file__) + "/extra-builtins.nix",
]
)
attr_path = f".#nixosConfigurations.{cfg}.config.system.build.toplevel"
copy_args = []
do_copy = True
if build_host is not None:
build_host = addr if cfg == build_host else opts["addresses"][build_host]
cmd = ["nix", "eval", "--json", attr_path + ".drvPath"] + args
ret = subprocess.run(cmd, check=True, encoding="utf-8", stdout=subprocess.PIPE)
drv = json.loads(ret.stdout)
print('copying', drv, 'to build host')
cmd = [
"nix",
"copy",
drv,
"--derivation",
"--to",
"ssh-ng://root@" + build_host,
] + args
subprocess.run(cmd, check=True)
print('building', drv)
cmd = ["nix", "build", f"'{drv}^*'", "--no-link", "--json"] + args
ret = subprocess.run(
["ssh", "root@" + build_host],
input=" ".join(cmd) + "\n",
check=True,
encoding="utf-8",
stdout=subprocess.PIPE,
)
if cfg == build_host:
do_copy = False
else:
copy_args.extend(["--from", "ssh-ng://root@" + build_host])
else:
print('building', attr_path)
cmd = ["nix", "build", attr_path, "--no-link", "--json"] + args
ret = subprocess.run(cmd, check=True, encoding="utf-8", stdout=subprocess.PIPE)
ret = json.loads(ret.stdout)[0]["outputs"]["out"]
print('output', ret)
cmds = []
if act in ["build"]:
return
if act in ["boot", "switch"]:
cmds.append(["nix-env", "-p", "/nix/var/nix/profiles/system", "--set", ret])
cmds.append(
["env", "NIXOS_INSTALL_BOOTLOADER=", ret + "/bin/switch-to-configuration", act]
)
if addr is None:
for cmd in cmds:
print('running', *cmd)
cmd = ["sudo", "-A"] + cmd
subprocess.run(cmd, check=True)
else:
if do_copy:
print('copying', ret, 'to', addr)
print(*(["nix", "copy", ret, "--no-check-sigs", "--to", "ssh-ng://root@" + addr] + copy_args + args))
subprocess.run(
["nix", "copy", ret, "--no-check-sigs", "--to", "ssh-ng://root@" + addr]
+ copy_args
+ args,
check=True,
)
print('running', *cmd)
subprocess.run(
["ssh", "root@" + addr],
input="\n".join(" ".join(cmd) for cmd in cmds) + "\n",
check=True,
encoding="utf-8",
)
if __name__ == "__main__":
try:
main()
except subprocess.CalledProcessError:
sys.exit(1)