mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +00:00
Resolves 68 conflicted files. The governing rule was our structure with their
network semantics: the tor boolean becomes a network mode (clearnet | tor |
multi) throughout the variant layer, while this branch's architecture and mesh
axes, its extracted modules and its i18n content stay.
Where the two sides covered different ground, both are kept rather than one
picked:
- ca_injected answers a ca_client on the deployment's TLS mode OR on an SSO
issuer that resolves self-signed. 3a3e9ed2c9 records why: an issuer is not
an object store, so keeping only one side drops the other's coverage.
- get_merged_domains keeps the loud refusal when svc-net-tor is deployed
without a provisioned node, now gated on their tor_serves_host; their
node_onion_of returns an empty string there, which would have served every
onion-exclusive app on clearnet in silence.
- sso_cookie_domains stays the single source for oauth2-proxy's cookie scope.
Their per-network branch omitted the issuer domain on the onion arm, which
breaks the callback leg.
- The clearnet CSP batch carries --clearnet-timeout again; their batch dict
hardcoded zero while the role still passes the flag.
- The dashboard keeps its i18n content dir, image, version and design
resolution; their side reduced the logo sources to the bare service
provider values.
Their side wins where it is measurably better: the onion mirror rewrite is
gated per vhost rather than per app, the Playwright onion decision reads the
pass's own domain instead of the role's canonical one, and the matomo
reinjection and dashboard config render per network sibling.
Eight files were broken by the merge without ever carrying a conflict marker,
because git marks only the lines both sides touched:
- utils/cache/domains.py lost the onionize block that sat between two hunks
- roles/sys-front-inj-all/templates/body_filter.lua.j2 called it
- web-app-bluesky, keycloak sso_proxy: the get_entity_name filter was renamed
- trigger/__main__.py, playwright_coverage.py and its test: the deleted tor
module
- cli/administration/deploy/ci/timings.py read Label.tor
- plugins/filter/csp_filters.py called _aligned_url with four of six arguments
- tests/unit/python/utils/cache/test_domains.py referenced a renamed class
- tests/.../sys-ctl-hlth-csp/files/test_script.py mocked a function main no
longer calls
Verified: the variant layer (155 tests, 65 subtests), ca_injected (18),
the CI layer (175), the domains cache including the restored guard (32),
retrigger inputs (9), timings and the CSP health script (53). make
quality-high clears autoformat; its remaining findings are tracked separately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
213 lines
8.1 KiB
Python
213 lines
8.1 KiB
Python
from __future__ import annotations
|
|
|
|
import io
|
|
import unittest
|
|
import unittest.mock as mock
|
|
from contextlib import redirect_stderr, redirect_stdout
|
|
|
|
from cli.meta.ci import validate
|
|
from utils.github.variant import axes, network
|
|
|
|
_ROWS = [
|
|
{"name": "web-app-a", "variant": 0, "test_compose": True, "test_swarm": True},
|
|
{"name": "web-app-a", "variant": 1, "test_compose": True, "test_swarm": False},
|
|
{"name": "web-app-b", "variant": 0, "test_compose": False, "test_swarm": True},
|
|
]
|
|
|
|
_VARIANTS = {
|
|
"web-app-a": [
|
|
{"services": {"tor": {"enabled": True}}},
|
|
{"services": {"tor": {"enabled": False}}},
|
|
],
|
|
"web-app-b": [
|
|
{
|
|
"services": {"tor": {"enabled": True}},
|
|
"networks": {"reachability": {"single_mode": True}},
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
def _problems(
|
|
tokens: str, *, network_input: str = "auto", vpn_mode: str = "auto"
|
|
) -> tuple[list[str], list[str]]:
|
|
with (
|
|
mock.patch.object(validate.query, "discover_rows", return_value=_ROWS),
|
|
mock.patch.object(validate, "get_variants", return_value=_VARIANTS),
|
|
):
|
|
return validate.problems(
|
|
tokens,
|
|
modes=("compose", "swarm", "host"),
|
|
network_input=network_input,
|
|
vpn_mode=vpn_mode,
|
|
distros=axes.DISTROS,
|
|
filesystems=axes.FILESYSTEMS,
|
|
lifecycles="",
|
|
label="priority",
|
|
)
|
|
|
|
|
|
class TestProblems(unittest.TestCase):
|
|
def test_nothing_to_check_is_not_a_problem(self) -> None:
|
|
self.assertEqual(_problems(""), ([], []))
|
|
|
|
def test_a_token_the_branch_can_deploy_passes(self) -> None:
|
|
self.assertEqual(_problems("web-app-a#0@swarm+tor"), ([], []))
|
|
|
|
def test_a_variant_the_role_no_longer_declares_is_an_error(self) -> None:
|
|
errors, warnings = _problems("web-app-a#7@compose+tor")
|
|
self.assertEqual(warnings, [])
|
|
self.assertIn("matches no discovered row", errors[0])
|
|
self.assertIn("2 variant(s)", errors[0])
|
|
|
|
def test_a_bare_role_that_matches_nothing_only_warns(self) -> None:
|
|
errors, warnings = _problems("web-app-gone")
|
|
self.assertEqual(errors, [])
|
|
self.assertIn("web-app-gone", warnings[0])
|
|
|
|
def test_a_pinned_role_the_run_never_discovers_only_warns(self) -> None:
|
|
errors, warnings = _problems("web-app-gone#0,2")
|
|
self.assertEqual(errors, [])
|
|
self.assertIn("web-app-gone", warnings[0])
|
|
|
|
def test_a_bare_role_the_run_discovers_is_silent(self) -> None:
|
|
self.assertEqual(_problems("web-app-a"), ([], []))
|
|
|
|
def test_a_bare_role_is_judged_on_existence_not_on_variant_zero(self) -> None:
|
|
rows = [{"name": "web-app-c", "variant": 4, "test_compose": True}]
|
|
with (
|
|
mock.patch.object(validate.query, "discover_rows", return_value=rows),
|
|
mock.patch.object(
|
|
validate, "get_variants", return_value={"web-app-c": [{"services": {}}]}
|
|
),
|
|
):
|
|
errors, warnings = validate.problems(
|
|
"web-app-c",
|
|
modes=("compose",),
|
|
network_input="auto",
|
|
vpn_mode="auto",
|
|
distros=axes.DISTROS,
|
|
filesystems=axes.FILESYSTEMS,
|
|
lifecycles="",
|
|
label="priority",
|
|
)
|
|
self.assertEqual((errors, warnings), ([], []))
|
|
|
|
def test_a_role_without_a_bond_may_pin_multi_when_its_deploy_pulls_tor(
|
|
self,
|
|
) -> None:
|
|
rows = [
|
|
{
|
|
"name": "web-app-c",
|
|
"variant": 0,
|
|
"test_compose": True,
|
|
"services": [network.tor_provider()],
|
|
}
|
|
]
|
|
with (
|
|
mock.patch.object(validate.query, "discover_rows", return_value=rows),
|
|
mock.patch.object(
|
|
validate, "get_variants", return_value={"web-app-c": [{"services": {}}]}
|
|
),
|
|
):
|
|
problems = validate.problems(
|
|
"web-app-c#0@compose+multi",
|
|
modes=("compose",),
|
|
network_input="auto",
|
|
vpn_mode="auto",
|
|
distros=axes.DISTROS,
|
|
filesystems=axes.FILESYSTEMS,
|
|
lifecycles="",
|
|
label="priority",
|
|
)
|
|
self.assertEqual(problems, ([], []))
|
|
|
|
def test_a_warning_still_separates_a_missing_role_from_a_present_one(self) -> None:
|
|
_errors, warnings = _problems("web-app-a web-app-gone web-app-b")
|
|
self.assertEqual(len(warnings), 1)
|
|
self.assertIn("web-app-gone", warnings[0])
|
|
|
|
def test_a_mode_the_row_does_not_offer_is_an_error(self) -> None:
|
|
errors, _warnings = _problems("web-app-a#1@swarm+clearnet")
|
|
self.assertIn("pinned mode 'swarm' is not available", errors[0])
|
|
|
|
def test_a_network_mode_the_variant_rules_out_is_an_error(self) -> None:
|
|
errors, _warnings = _problems("web-app-a#1@compose+tor")
|
|
self.assertIn("pinned network mode 'tor' is impossible", errors[0])
|
|
|
|
def test_a_network_mode_the_runs_network_axis_rules_out_is_an_error(self) -> None:
|
|
errors, _warnings = _problems(
|
|
"web-app-a#0@compose+clearnet", network_input="tor"
|
|
)
|
|
self.assertIn("pinned network mode 'clearnet' is impossible", errors[0])
|
|
|
|
def test_a_network_mode_the_roles_reachability_rules_out_is_an_error(self) -> None:
|
|
self.assertEqual(_problems("web-app-b#0@swarm+tor"), ([], []))
|
|
errors, _warnings = _problems("web-app-b#0@swarm+multi")
|
|
self.assertIn("pinned network mode 'multi' is impossible", errors[0])
|
|
|
|
def test_a_mesh_state_the_mode_rules_out_is_an_error(self) -> None:
|
|
errors, _warnings = _problems("web-app-a#0@compose+clearnet&vpn")
|
|
self.assertIn("pinned mesh state vpn is impossible", errors[0])
|
|
|
|
def test_a_mesh_state_the_mode_allows_passes(self) -> None:
|
|
self.assertEqual(_problems("web-app-a#0@swarm+clearnet&vpn"), ([], []))
|
|
|
|
def test_every_offender_is_reported_not_just_the_first(self) -> None:
|
|
errors, _warnings = _problems(
|
|
"web-app-a#7@compose+tor web-app-a#1@swarm+tor web-app-b#9@swarm+tor"
|
|
)
|
|
self.assertEqual(len(errors), 3)
|
|
|
|
def test_a_csv_token_is_checked_variant_by_variant(self) -> None:
|
|
errors, _warnings = _problems("web-app-a#0,7@compose+clearnet")
|
|
self.assertEqual(len(errors), 1)
|
|
self.assertIn("matches no discovered row", errors[0])
|
|
|
|
|
|
class TestMain(unittest.TestCase):
|
|
def _main(self, argv: list[str]) -> tuple[int, str, str]:
|
|
out, err = io.StringIO(), io.StringIO()
|
|
with (
|
|
mock.patch.object(validate.query, "discover_rows", return_value=_ROWS),
|
|
mock.patch.object(validate, "get_variants", return_value=_VARIANTS),
|
|
redirect_stdout(out),
|
|
redirect_stderr(err),
|
|
):
|
|
code = validate.main(argv)
|
|
return code, out.getvalue(), err.getvalue()
|
|
|
|
def test_a_valid_selection_exits_zero(self) -> None:
|
|
code, out, _err = self._main(["--priority", "web-app-a#0@swarm+tor"])
|
|
self.assertEqual(code, 0)
|
|
self.assertIn("valid for this branch", out)
|
|
|
|
def test_an_unusable_selection_exits_non_zero(self) -> None:
|
|
code, _out, err = self._main(["--priority", "web-app-a#7"])
|
|
self.assertEqual(code, 1)
|
|
self.assertIn("::error::", err)
|
|
|
|
def test_the_network_flag_is_the_runs_network_axis(self) -> None:
|
|
code, _out, err = self._main(
|
|
["--network", "clearnet", "--priority", "web-app-a#0@swarm+tor"]
|
|
)
|
|
self.assertEqual(code, 1)
|
|
self.assertIn("pinned network mode 'tor' is impossible", err)
|
|
|
|
def test_both_inputs_are_checked_and_named_in_the_message(self) -> None:
|
|
code, _out, err = self._main(
|
|
["--whitelist", "web-app-a#7", "--priority", "web-app-b#9"]
|
|
)
|
|
self.assertEqual(code, 1)
|
|
self.assertIn("whitelist:", err)
|
|
self.assertIn("priority:", err)
|
|
|
|
def test_a_warning_alone_does_not_fail_the_run(self) -> None:
|
|
code, out, _err = self._main(["--whitelist", "web-app-gone"])
|
|
self.assertEqual(code, 0)
|
|
self.assertIn("::warning::", out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|