Skip to content

Commit 0406970

Browse files
committed
test(ci): enforce cache writer step ordering
Preserve action order and multiplicity when checking the credential-bearing cache writer. Require immutable action revisions and cover candidate checkout/restore and reordered-step regressions. Signed-off-by: Adrien Langou <alangou@nvidia.com>
1 parent ada8b57 commit 0406970

1 file changed

Lines changed: 57 additions & 10 deletions

File tree

‎tasks/scripts/check_cachix_isolation_test.py‎

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
"""Guard the checked-in credential boundary; GitHub environment rules are external."""
55

66
import os
7+
import re
78
import subprocess
89
from pathlib import Path
910

11+
import pytest
1012
import yaml
1113

1214
REPO_ROOT = Path(__file__).resolve().parents[2]
@@ -42,8 +44,7 @@ def test_shared_nix_setup_only_reads_the_cache():
4244
assert "cachix-auth-token" not in setup.get("inputs", {})
4345

4446

45-
def test_cache_writer_uses_only_the_main_push_revision():
46-
writer = load_yaml(WRITER)
47+
def check_cache_writer(writer: dict) -> None:
4748
assert writer["on"] == {"push": {"branches": ["main"]}}
4849
assert writer["permissions"] == {"contents": "read"}
4950
assert set(writer["jobs"]) == {"populate"}
@@ -59,25 +60,71 @@ def test_cache_writer_uses_only_the_main_push_revision():
5960
{"system": "aarch64-linux", "runner": "ubuntu-24.04-arm"},
6061
{"system": "aarch64-darwin", "runner": "macos-15-xlarge"},
6162
]
62-
# No PR artifacts, local actions or caller-supplied source enter this job.
63-
actions = {
64-
step["uses"].split("@")[0]: step for step in job["steps"] if "uses" in step
65-
}
66-
assert set(actions) == {
63+
# Review any new step in this credential-bearing job. Preserve order and
64+
# duplicates: a later main checkout must not hide an earlier candidate build.
65+
steps = job["steps"]
66+
assert [step.get("uses", "run").split("@")[0] for step in steps] == [
67+
"run",
6768
"actions/checkout",
6869
"cachix/install-nix-action",
6970
"cachix/cachix-action",
70-
}
71-
assert actions["actions/checkout"]["with"] == {
71+
"run",
72+
]
73+
credential, checkout, install_nix, cache, build = steps
74+
assert "run" in credential and "run" in build
75+
for step in (checkout, install_nix, cache):
76+
assert re.fullmatch(r"[0-9a-f]{40}", step["uses"].partition("@")[2])
77+
assert checkout["with"] == {
7278
"persist-credentials": "false",
7379
"ref": "${{ github.sha }}",
7480
}
75-
assert actions["cachix/cachix-action"]["with"] == {
81+
assert cache["with"] == {
7682
"name": "openshell",
7783
"authToken": "${{ secrets.CACHIX_WRITE_TOKEN }}",
7884
}
7985

8086

87+
def test_cache_writer_uses_only_the_main_push_revision():
88+
check_cache_writer(load_yaml(WRITER))
89+
90+
91+
def test_cache_writer_rejects_candidate_checkout_followed_by_main_restore():
92+
writer = load_yaml(WRITER)
93+
steps = writer["jobs"]["populate"]["steps"]
94+
checkout = steps[1]
95+
candidate_checkout = {
96+
**checkout,
97+
"with": {**checkout["with"], "ref": "refs/pull/123/head"},
98+
}
99+
steps.insert(-1, candidate_checkout)
100+
steps.append(checkout)
101+
102+
with pytest.raises(AssertionError):
103+
check_cache_writer(writer)
104+
105+
106+
@pytest.mark.parametrize(
107+
("source", "destination"),
108+
[(1, 4), (4, 1)],
109+
ids=["checkout-after-build", "build-before-checkout"],
110+
)
111+
def test_cache_writer_rejects_reordered_steps(source: int, destination: int):
112+
writer = load_yaml(WRITER)
113+
steps = writer["jobs"]["populate"]["steps"]
114+
steps.insert(destination, steps.pop(source))
115+
116+
with pytest.raises(AssertionError):
117+
check_cache_writer(writer)
118+
119+
120+
def test_cache_writer_rejects_mutable_action_refs():
121+
writer = load_yaml(WRITER)
122+
writer["jobs"]["populate"]["steps"][1]["uses"] = "actions/checkout@main"
123+
124+
with pytest.raises(AssertionError):
125+
check_cache_writer(writer)
126+
127+
81128
def test_cache_writer_requires_its_environment_credential():
82129
step = load_yaml(WRITER)["jobs"]["populate"]["steps"][0]
83130
assert step["env"] == {"CACHIX_WRITE_TOKEN": "${{ secrets.CACHIX_WRITE_TOKEN }}"}

0 commit comments

Comments
 (0)