Grimmory and MeTube published behind the family gate (controller >= 0.287.0, decisions 63/64), with complete records
gates / gates (push) Successful in 3s
gates / gates (push) Successful in 3s
- family_gate / family_gate_except / min_controller format (README, REUSE); gate family-gate + decoys - templates/grimmory (v3.5.0, exceptions OPDS/Kobo/KOReader/Komga) + onboarding/grimmory.md - templates/metube (2026.09.29, no exceptions; ladder .28 -> .29) + onboarding/metube.md; fixture MeTube - volume-persistence gate: routed port read from the label NAME (R-801, red-proofed); APP_EXERCISE (R-788) - box_walk: family_cookie; no cached "not gated" while an app has no router Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -463,5 +463,21 @@ class TestEnvBuilding(unittest.TestCase):
|
||||
self.assertEqual([f["env_var"] for f in cvp.parse_deploy_fields(felhom)], ["A"])
|
||||
|
||||
|
||||
|
||||
class TestRoutedPorts(unittest.TestCase):
|
||||
def test_routed_ports_reads_the_mapping_form(self):
|
||||
"""R-801: `compose config --format json` gives labels as a mapping; the port is in the KEY."""
|
||||
resolved = {"services": {"metube": {"labels": {
|
||||
"traefik.enable": "true",
|
||||
"traefik.http.services.metube.loadbalancer.server.port": "8081"}}}}
|
||||
self.assertEqual(cvp.routed_ports(resolved), [8081])
|
||||
|
||||
def test_routed_ports_list_form_still_read(self):
|
||||
resolved = {"services": {"a": {"labels": ["traefik.http.services.a.loadbalancer.server.port=3000"]}}}
|
||||
self.assertEqual(cvp.routed_ports(resolved), [3000])
|
||||
|
||||
def test_no_routed_port(self):
|
||||
self.assertEqual(cvp.routed_ports({"services": {"db": {"labels": {"x": "y"}}}}), [])
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user