3"""Two-way trust boundary between native HIL and shared compiler caches."""
5from __future__
import annotations
7from pathlib
import Path
9HIL_RUNNER_TASKS =
"infra/ansible/roles/dev_box/tasks/hil_runner_transaction.yml"
10HIL_RUNNER_SERVICE =
"infra/ansible/roles/dev_box/templates/ra8-hil-runner.service.j2"
11SHARED_CACHE_TASKS =
"infra/ansible/roles/dev_box/tasks/transaction.yml"
12SHARED_CACHE_ROOT =
"/var/cache/ccache-ra8"
13HIL_CACHE_ROOT =
"/var/cache/ccache-ra8-hil"
16def check_texts(hil_tasks: str, hil_service: str, shared_tasks: str) -> list[str]:
17 """Keep the private HIL and shared interactive cache domains disjoint."""
19 for relative, text
in ((HIL_RUNNER_TASKS, hil_tasks), (HIL_RUNNER_SERVICE, hil_service)):
20 if SHARED_CACHE_ROOT
in text
or "dev_box_ccache_dir" in text:
21 problems.append(f
"{relative}: HIL surface references the shared compiler cache")
22 if HIL_CACHE_ROOT
in shared_tasks
or "dev_box_hil_ccache_dir" in shared_tasks:
23 problems.append(f
"{SHARED_CACHE_TASKS}: shared cache surface references the HIL cache")
26 'Environment="CCACHE_DIR={{ dev_box_hil_ccache_dir }}"',
27 'Environment="RA8_CCACHE_DIR={{ dev_box_hil_ccache_dir }}"',
29 actual_service = tuple(line
for line
in hil_service.splitlines()
if "CCACHE_DIR=" in line)
30 if actual_service != expected_service:
31 problems.append(f
"{HIL_RUNNER_SERVICE}: cache environment is not exactly HIL-private")
33 required_hil_fragments = (
34 'path: "{{ dev_box_hil_ccache_dir }}"',
35 'dest: "{{ dev_box_hil_ccache_dir }}/ccache.conf"',
36 'owner: "{{ dev_box_hil_runner_user }}"',
37 'group: "{{ dev_box_hil_runner_group }}"',
39 "when: not ansible_check_mode",
40 "ansible.builtin.tempfile:",
42 if any(fragment
not in hil_tasks
for fragment
in required_hil_fragments):
43 problems.append(f
"{HIL_RUNNER_TASKS}: private cache converge/probe contract is incomplete")
44 if "ansible.posix.acl" in hil_tasks:
45 problems.append(f
"{HIL_RUNNER_TASKS}: HIL cache must not use shared-access ACLs")
49def check(repo_root: Path) -> list[str]:
50 """Read and validate the two disjoint full-role cache surfaces."""
53 (repo_root / HIL_RUNNER_TASKS).read_text(encoding=
"utf-8"),
54 (repo_root / HIL_RUNNER_SERVICE).read_text(encoding=
"utf-8"),
55 (repo_root / SHARED_CACHE_TASKS).read_text(encoding=
"utf-8"),
57 except (OSError, UnicodeError)
as exc:
58 return [f
"HIL/shared compiler-cache isolation cannot be read: {exc}"]
61def selftest() -> list[str]:
62 """Prove shared and HIL cache references cannot cross either way."""
63 hil_tasks =
"""path: "{{ dev_box_hil_ccache_dir }}"
64dest: "{{ dev_box_hil_ccache_dir }}/ccache.conf"
65owner: "{{ dev_box_hil_runner_user }}"
66group: "{{ dev_box_hil_runner_group }}"
68when: not ansible_check_mode
69ansible.builtin.tempfile:
71 hil_service =
"""Environment="CCACHE_DIR={{ dev_box_hil_ccache_dir }}"
72Environment="RA8_CCACHE_DIR={{ dev_box_hil_ccache_dir }}"
74 shared_tasks =
'path: "{{ dev_box_ccache_dir }}"\n'
76 if check_texts(hil_tasks, hil_service, shared_tasks):
77 failures.append(
" approved private/shared cache split was rejected")
79 "HIL task shared variable": (hil_tasks +
"\ndev_box_ccache_dir", hil_service, shared_tasks),
80 "HIL task shared literal": (
81 hil_tasks + f
"\n{SHARED_CACHE_ROOT}",
85 "HIL service shared variable": (
87 hil_service.replace(
"dev_box_hil_ccache_dir",
"dev_box_ccache_dir"),
90 "shared task HIL variable": (
93 shared_tasks +
"\ndev_box_hil_ccache_dir",
95 "shared task HIL literal": (hil_tasks, hil_service, shared_tasks + f
"\n{HIL_CACHE_ROOT}"),
96 "HIL ACL restored": (hil_tasks +
"\nansible.posix.acl:", hil_service, shared_tasks),
99 f
" cache trust-boundary crossing was accepted: {name}"
100 for name, texts
in mutations.items()
101 if not check_texts(*texts)