Establish repository foundation and shared work environment
This commit is contained in:
1 parent
3c022ad2f9
commit
f164d8b76e
15 files changed
+571
-523
No files matched your search
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate current repository files without changing the Git index."""
|
||||
|
||||
from collections import deque
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(ROOT)
|
||||
run_dir = Path(tempfile.mkdtemp(prefix="nixos-validate-", dir="/tmp"))
|
||||
print(f"Logs: {run_dir}", flush=True)
|
||||
|
||||
def run(label, command):
|
||||
log = run_dir / f"{label}.log"
|
||||
print(f"{label} ...", flush=True)
|
||||
with log.open("wb") as output:
|
||||
result = subprocess.run(command, stdout=output, stderr=subprocess.STDOUT)
|
||||
if result.returncode:
|
||||
print(f"{label}: FAILED ({result.returncode}); {log}", flush=True)
|
||||
with log.open(errors="replace") as output:
|
||||
excerpt = "".join(deque(output, maxlen=40))
|
||||
print(excerpt[-12000:])
|
||||
raise SystemExit(result.returncode)
|
||||
print(f"{label}: OK", flush=True)
|
||||
|
||||
# Git supplies selection only: contents always come from the working tree.
|
||||
paths = subprocess.check_output(
|
||||
["git", "ls-files", "--cached", "--others", "--exclude-standard", "-z"]
|
||||
).split(b"\0")
|
||||
files = sorted({os.fsdecode(path) for path in paths if path})
|
||||
files = [name for name in files if os.path.lexists(ROOT / name)]
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="nixos-source-", dir="/tmp") as temp:
|
||||
source = Path(temp) / "source"
|
||||
|
||||
def snapshot():
|
||||
if source.exists():
|
||||
shutil.rmtree(source)
|
||||
source.mkdir()
|
||||
for name in files:
|
||||
original = ROOT / name
|
||||
destination = source / name
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if original.is_symlink():
|
||||
destination.symlink_to(os.readlink(original))
|
||||
elif original.is_file():
|
||||
shutil.copy2(original, destination)
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported source entry: {name}")
|
||||
|
||||
snapshot()
|
||||
flake = f"path:{source}"
|
||||
nix = ["nix", "--quiet"]
|
||||
locked = ["--no-update-lock-file"]
|
||||
# The repository currently exposes only x86_64-linux outputs.
|
||||
nix_files = [str(ROOT / name) for name in files if name.endswith(".nix")]
|
||||
run("format", nix + ["run", *locked, f"{flake}#formatter.x86_64-linux", "--", *nix_files])
|
||||
snapshot()
|
||||
run("check", nix + ["flake", "check", "--no-build", *locked, flake])
|
||||
hosts_file = run_dir / "hosts.json"
|
||||
# Keep machine-readable output separate from Nix diagnostics.
|
||||
with hosts_file.open("wb") as output, (run_dir / "hosts.log").open("wb") as errors:
|
||||
result = subprocess.run(
|
||||
nix + ["eval", *locked, "--json", f"{flake}#nixosConfigurations", "--apply", "builtins.attrNames"],
|
||||
stdout=output, stderr=errors,
|
||||
)
|
||||
if result.returncode:
|
||||
print(f"Host discovery failed; see {run_dir / 'hosts.log'}")
|
||||
raise SystemExit(result.returncode)
|
||||
available = json.loads(hosts_file.read_text())
|
||||
hosts = list(dict.fromkeys(sys.argv[1:])) or available
|
||||
unknown = set(hosts) - set(available)
|
||||
if unknown:
|
||||
raise RuntimeError(f"Unknown hosts: {', '.join(sorted(unknown))}")
|
||||
for host in hosts:
|
||||
run(f"build-{host}", nix + ["build", *locked, "--no-link", f"{flake}#nixosConfigurations.{host}.config.system.build.toplevel"])
|
||||
if not sys.argv[1:]:
|
||||
run("build-workbench", nix + ["build", *locked, "--no-link", f"{flake}#devShells.x86_64-linux.workbench"])
|
||||
print(f"Validation passed: {', '.join(hosts)}. Logs: {run_dir}", flush=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except (OSError, ValueError, RuntimeError, subprocess.CalledProcessError) as error:
|
||||
sys.exit(str(error))
|
||||
Reference in new issue
Block a user