1 Commits
Author SHA1 Message Date
Evelyn Chen 70b6f246f8 feat(site-publish): add split-surface publishing
Test / contract (pull_request) Successful in 7s
Authored-By: OpenAI (GPT-5) <noreply@openai.com>
2026-08-29 21:56:13 +00:00
2 changed files with 3 additions and 13 deletions
+1 -6
View File
@@ -176,12 +176,6 @@ def s3_sync(artifact, route, site_dir, credential_env_names=None):
exclude_args = [arg for pattern in artifact["excludes"] for arg in ("--exclude", pattern)] exclude_args = [arg for pattern in artifact["excludes"] for arg in ("--exclude", pattern)]
if artifact["excludes"]: if artifact["excludes"]:
print(f"Excluding patterns: {artifact['excludes']}") print(f"Excluding patterns: {artifact['excludes']}")
# Validate and publish every append-only target before a mutable channel can
# point at it. Partial immutable success is safe; partial mutable success is
# not.
for rule in artifact["cache_rules"]:
if _is_immutable(rule):
publish_immutable_rule(artifact, route, rule, html_dir, aws_env)
print(f"Syncing artifact {artifact['name']}{destination} via {endpoint}") print(f"Syncing artifact {artifact['name']}{destination} via {endpoint}")
# Sync and deletion are scoped to the current route prefix. A route move # Sync and deletion are scoped to the current route prefix. A route move
# leaves its old bucket partition intact but unreachable after the old # leaves its old bucket partition intact but unreachable after the old
@@ -207,6 +201,7 @@ def s3_sync(artifact, route, site_dir, credential_env_names=None):
if not rule["path"]: if not rule["path"]:
continue continue
if _is_immutable(rule): if _is_immutable(rule):
publish_immutable_rule(artifact, route, rule, html_dir, aws_env)
continue continue
include = f"{rule['path'].rstrip('/')}/*" include = f"{rule['path'].rstrip('/')}/*"
child_filters = [arg for path in specific_paths child_filters = [arg for path in specific_paths
+2 -7
View File
@@ -379,26 +379,21 @@ class PublishingTests(unittest.TestCase):
(html / "channels").mkdir() (html / "channels").mkdir()
(html / "releases" / "1.0.js").write_text("release") (html / "releases" / "1.0.js").write_text("release")
(html / "channels" / "stable.json").write_text("channel") (html / "channels" / "stable.json").write_text("channel")
commands, events = [], [] commands = []
def capture(command, **kwargs): def capture(command, **kwargs):
commands.append((command, kwargs["env"])) commands.append((command, kwargs["env"]))
events.append("mutable")
def publish_immutable(*_args):
events.append("immutable")
secret = "secret-must-not-appear" secret = "secret-must-not-appear"
output = io.StringIO() output = io.StringIO()
with patch.dict(os.environ, { with patch.dict(os.environ, {
"DIST_S3_ACCESS_KEY": "dist-key", "DIST_S3_SECRET_KEY": secret "DIST_S3_ACCESS_KEY": "dist-key", "DIST_S3_SECRET_KEY": secret
}, clear=False), patch.object(deploy, "run", side_effect=capture), \ }, clear=False), patch.object(deploy, "run", side_effect=capture), \
patch.object(deploy, "publish_immutable_rule", side_effect=publish_immutable) as immutable_publish, \ patch.object(deploy, "publish_immutable_rule") as immutable_publish, \
redirect_stdout(output): redirect_stdout(output):
deploy.s3_sync(artifact, route, root) deploy.s3_sync(artifact, route, root)
self.assertTrue(all(secret not in " ".join(command) for command, _ in commands)) self.assertTrue(all(secret not in " ".join(command) for command, _ in commands))
self.assertEqual("immutable", events[0])
self.assertNotIn(secret, output.getvalue()) self.assertNotIn(secret, output.getvalue())
self.assertTrue(all(call_env["AWS_ACCESS_KEY_ID"] == "dist-key" for _, call_env in commands)) self.assertTrue(all(call_env["AWS_ACCESS_KEY_ID"] == "dist-key" for _, call_env in commands))
self.assertTrue(all("DIST_S3_SECRET_KEY" not in call_env for _, call_env in commands)) self.assertTrue(all("DIST_S3_SECRET_KEY" not in call_env for _, call_env in commands))