test(site-publish): prove immutable failure ordering
Test / contract (pull_request) Successful in 7s

Authored-By: OpenAI (GPT-5) <noreply@openai.com>
This commit is contained in:
Dave Kowalski
2026-08-29 22:17:24 +00:00
parent 5c2630b972
commit 5261b9b99f
2 changed files with 27 additions and 0 deletions
+4
View File
@@ -128,6 +128,10 @@ cache policy, content type, and bytes. That content address makes concurrent
writes identical even though Garage v2.2.0 has no conditional destination writes identical even though Garage v2.2.0 has no conditional destination
write. An identical retry converges; a changed object, missing digest metadata, write. An identical retry converges; a changed object, missing digest metadata,
wrong address, or nested policy under that immutable prefix fails publication. wrong address, or nested policy under that immutable prefix fails publication.
Every immutable target is validated and published before mutable objects change.
Mutable default and override partitions receive their final cache policy before
the matching prefix-scoped stale deletion, so publication never exposes a
provisional cache policy or a pointer to a missing immutable target.
Artifact input directories must be pairwise disjoint after filesystem Artifact input directories must be pairwise disjoint after filesystem
resolution. Publication stops before build or upload if one contains another or resolution. Publication stops before build or upload if one contains another or
+23
View File
@@ -417,6 +417,29 @@ class PublishingTests(unittest.TestCase):
immutable_publish.call_args.args[2]["cache_control"], immutable_publish.call_args.args[2]["cache_control"],
) )
def test_immutable_failure_stops_before_mutable_publication(self):
cfg = normalize_site_config(fixture("split-site.yaml"), "baseline.fritzlab.net")
artifact = next(item for item in cfg["artifacts"] if item["name"] == "distributions")
route = next(item for item in cfg["routes"] if item["artifact"] == "distributions")
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
html = root / artifact["build_dir"]
(html / "releases").mkdir(parents=True)
(html / "channels").mkdir()
(html / "releases" / "1.0.js").write_text("release")
(html / "channels" / "stable.json").write_text("channel")
with patch.dict(os.environ, {
"DIST_S3_ACCESS_KEY": "dist-key", "DIST_S3_SECRET_KEY": "dist-secret"
}, clear=False), patch.object(
deploy, "publish_immutable_rule", side_effect=RuntimeError("immutable failed")
), patch.object(deploy, "run") as mutable_run, self.assertRaisesRegex(
RuntimeError, "immutable failed"
):
deploy.s3_sync(artifact, route, root)
mutable_run.assert_not_called()
def test_absent_artifact_is_detected_before_publish(self): def test_absent_artifact_is_detected_before_publish(self):
cfg = normalize_site_config(fixture("split-site.yaml"), "baseline.fritzlab.net") cfg = normalize_site_config(fixture("split-site.yaml"), "baseline.fritzlab.net")