5 Commits
Author SHA1 Message Date
Sovran SystemsandGitHub ab4de8da7d Merge pull request #329 from naturallaw777/copilot/fix-nix-build-regression
Fix `sovran-hosts-update` ShellCheck build regression from `writeShellApplication`
2026-07-16 20:40:41 +00:00
copilot-swe-agent[bot]andGitHub 92cf417760 test: harden flake configuration detection 2026-07-16 20:38:48 +00:00
copilot-swe-agent[bot]andGitHub ec4c1c851b test: derive nix helper build attr from flake 2026-07-16 20:37:48 +00:00
copilot-swe-agent[bot]andGitHub 38f49e9161 fix: group sovran hosts append redirection 2026-07-16 20:36:33 +00:00
copilot-swe-agent[bot]andGitHub c853853616 Initial plan 2026-07-16 20:33:53 +00:00
2 changed files with 71 additions and 6 deletions
+64 -1
View File
@@ -16,11 +16,28 @@ Verifies that the sovran-hosts-update helper:
- does NOT rely on environment.systemPackages for the helper's dependencies. - does NOT rely on environment.systemPackages for the helper's dependencies.
""" """
import re
import shutil
import subprocess
import unittest import unittest
from pathlib import Path from pathlib import Path
NIX_STRING_INDENT = 6
REPO_ROOT = Path(__file__).resolve().parents[2]
FLAKE_SOURCE = (REPO_ROOT / "flake.nix").read_text()
PRIMARY_NIXOS_CONFIGURATION_MATCH = re.search(
r"nixosConfigurations\.([A-Za-z0-9_-]+)\s*=",
FLAKE_SOURCE,
)
if PRIMARY_NIXOS_CONFIGURATION_MATCH is None:
raise RuntimeError("Could not determine the primary nixosConfigurations entry from flake.nix")
PRIMARY_NIXOS_CONFIGURATION = PRIMARY_NIXOS_CONFIGURATION_MATCH.group(1)
HELPER_BUILD_ATTR = (
f'.#nixosConfigurations.{PRIMARY_NIXOS_CONFIGURATION}.config.environment.etc.'
'"sovran-hosts-update.sh".source'
)
NIX_FILE = ( NIX_FILE = (
Path(__file__).resolve().parents[2] REPO_ROOT
/ "modules" / "modules"
/ "core" / "core"
/ "local-domain-loopback.nix" / "local-domain-loopback.nix"
@@ -31,6 +48,16 @@ class LocalDomainLoopbackNixStructureTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.source = NIX_FILE.read_text() self.source = NIX_FILE.read_text()
def _helper_script(self) -> str:
start = self.source.index("text = ''") + len("text = ''")
end = self.source.index(" '';", start)
return "\n".join(
line[NIX_STRING_INDENT:]
if line.startswith(" " * NIX_STRING_INDENT)
else line
for line in self.source[start:end].splitlines()
).lstrip("\n")
# ── writeShellApplication and explicit runtimeInputs ──────────────────── # ── writeShellApplication and explicit runtimeInputs ────────────────────
def test_uses_write_shell_application(self): def test_uses_write_shell_application(self):
@@ -120,6 +147,42 @@ class LocalDomainLoopbackNixStructureTests(unittest.TestCase):
self.assertIn("skip=1", self.source) self.assertIn("skip=1", self.source)
self.assertIn("skip=0", self.source) self.assertIn("skip=0", self.source)
def test_managed_block_uses_grouped_append_redirect(self):
self.assertIn('} >> "$TMP"', self.source)
self.assertEqual(self.source.count('>> "$TMP"'), 1)
def test_helper_script_passes_shellcheck(self):
shellcheck = shutil.which("shellcheck")
if shellcheck is None:
self.skipTest("shellcheck is not installed")
proc = subprocess.run(
[shellcheck, "-s", "bash", "-"],
input=self._helper_script(),
text=True,
capture_output=True,
check=False,
)
output = proc.stdout + proc.stderr
self.assertEqual(proc.returncode, 0, output)
def test_helper_derivation_builds_when_nix_available(self):
nix = shutil.which("nix")
if nix is None:
self.skipTest("nix is not installed")
proc = subprocess.run(
[
nix,
"build",
HELPER_BUILD_ATTR,
"--no-link",
],
cwd=REPO_ROOT,
text=True,
capture_output=True,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
# ── Activation script warns on failure rather than silently swallowing ─── # ── Activation script warns on failure rather than silently swallowing ───
def test_activation_script_emits_warning_on_failure(self): def test_activation_script_emits_warning_on_failure(self):
+7 -5
View File
@@ -107,11 +107,13 @@ let
# Step 4: append the Sovran block if there are any entries # Step 4: append the Sovran block if there are any entries
if [ -n "$ENTRIES" ]; then if [ -n "$ENTRIES" ]; then
printf '\n%s\n' "$BEGIN_MARKER" >> "$TMP" {
printf '%s\n' "# These entries route configured service domains to local Caddy." >> "$TMP" printf '\n%s\n' "$BEGIN_MARKER"
printf '%s\n' "# They are managed automatically do not edit this block." >> "$TMP" printf '%s\n' "# These entries route configured service domains to local Caddy."
printf '%s\n' "$ENTRIES" >> "$TMP" printf '%s\n' "# They are managed automatically do not edit this block."
printf '%s\n' "$END_MARKER" >> "$TMP" printf '%s\n' "$ENTRIES"
printf '%s\n' "$END_MARKER"
} >> "$TMP"
fi fi
# Step 5: atomically replace /etc/hosts # Step 5: atomically replace /etc/hosts