"""tools/conventions/lint.py (NK-WP-0058-T07): each rule on synthetic lines, and this repository is clean.""" import importlib.util from pathlib import Path import pytest import yaml REPO = Path(__file__).resolve().parents[3] spec = importlib.util.spec_from_file_location('conventions_lint', REPO / 'tools/conventions/lint.py') lint = importlib.util.module_from_spec(spec) spec.loader.exec_module(lint) def rules(rel, line, owned=frozenset()): return [rule for _, _, rule in lint.check_file(rel, line + '\n', owned)] @pytest.mark.parametrize('line, found', [ ('kubectl apply -f deployment.yaml', ['server-side-apply']), ('$K apply --dry-run=server -f x.yaml && $K apply -f x.yaml', ['server-side-apply']), ('$(KUBECTL) apply -f manifests/rbac.yaml', ['server-side-apply']), ('kubectl apply --server-side -f deployment.yaml', []), ('kubectl get pods # apply nothing', []), ]) def test_server_side_apply(line, found): assert rules('runbooks/x.md', line) == found def test_one_wait_condition(): assert rules('x.sh', 'kubectl wait --for=condition=complete --for=condition=failed job/x') == [ 'one-wait-condition'] assert rules('x.sh', 'kubectl wait --for=condition=available deploy/x') == [] @pytest.mark.parametrize('line, found', [ ("args = ['kubectl', '--kubeconfig', '/home/worsch/.kube/config-hosteurope']", True), ("args = ['kubectl', '--server', 'https://127.0.0.1:16444']", True), ("KUBE = '/etc/rancher/k3s/k3s.yaml'", True), ("KUBECONFIG = os.environ.get('NK_KUBECONFIG', os.path.expanduser('~/.kube/config-railiance01'))", False), ]) def test_one_cluster_route(line, found): assert ('one-cluster-route' in rules('tools/x.py', line)) is found assert rules('tools/tests/test_x.py', line) == [] # tests may build synthetic routes def test_tool_numbered_receipts(): assert rules('runbooks/x.md', 'python3 lane.py setup --receipt "$E/01-setup.json"') == ['tool-numbered-receipts'] assert rules('runbooks/x.md', 'python3 bx.py run') == [] def test_managing_controller(tmp_path): app = tmp_path / 'railiance-platform/argocd/apps/x.yaml' app.parent.mkdir(parents=True) app.write_text(yaml.safe_dump({'kind': 'Application', 'spec': {'source': { 'repoURL': 'https://forgejo.coulomb.social/coulomb/informed-decision.git', 'path': 'deploy/lifecycle'}}})) owned = lint.argo_paths(tmp_path / 'railiance-platform') assert owned == {('informed-decision', 'deploy/lifecycle')} line = 'kubectl apply --server-side -f ~/informed-decision/deploy/lifecycle/review-groups.yaml' assert rules('runbooks/x.md', line, owned) == ['managing-controller'] assert rules('runbooks/x.md', 'kubectl apply --server-side -f ~/approval-engine/deploy/np.yaml', owned) == [] def test_records_and_exceptions_are_not_findings(): assert lint.RECORDS.search('docs/evidence/2026-11-05-x/README.md') assert rules('sso-mfa/WORKPLAN.md', 'kubectl apply -f a.yaml') == [] # a listed exception with its reason assert all(reason for reason in lint.EXCEPTIONS.values()) def test_this_repository_is_clean(): findings = lint.lint(REPO, lint.argo_paths(REPO.parent / 'railiance-platform')) assert findings == [], findings