site-publish: honor site.yaml excludes during S3 sync
site.yaml can now declare excludes: [paths/patterns] that are passed to `aws s3 sync` and `aws s3 cp` as --exclude flags, so the listed objects are neither uploaded from the build dir nor deleted from the bucket. Escape hatch for assets managed out-of-band (e.g. large PDFs uploaded via aws-cli) that would otherwise be wiped by --delete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-4
@@ -2,6 +2,7 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
@@ -30,7 +31,7 @@ GARAGE_ADMIN_ENDPOINT = os.environ.get(
|
||||
CACHE_CONTROL = "public, max-age=0, must-revalidate"
|
||||
|
||||
|
||||
def s3_sync(site_name, site_dir):
|
||||
def s3_sync(site_name, site_dir, excludes=None):
|
||||
endpoint = os.environ.get("GARAGE_S3_ENDPOINT", DEFAULT_S3_ENDPOINT)
|
||||
html_dir = site_dir / "build" / "html"
|
||||
if not html_dir.exists():
|
||||
@@ -38,6 +39,12 @@ def s3_sync(site_name, site_dir):
|
||||
env("AWS_ACCESS_KEY_ID")
|
||||
env("AWS_SECRET_ACCESS_KEY")
|
||||
os.environ.setdefault("AWS_DEFAULT_REGION", "sjc001")
|
||||
# `excludes` are patterns (site.yaml `excludes:` list) that should never
|
||||
# be uploaded *and* should never be deleted from the bucket — escape hatch
|
||||
# for assets managed out-of-band (e.g. large PDFs uploaded via aws-cli).
|
||||
exclude_flags = " ".join(f"--exclude {shlex.quote(p)}" for p in (excludes or []))
|
||||
if excludes:
|
||||
print(f"Excluding patterns: {excludes}")
|
||||
print(f"Syncing {html_dir} → s3://{site_name} via {endpoint}")
|
||||
# `sync --delete` handles new/changed/orphaned files. `cp --recursive`
|
||||
# then re-uploads everything to refresh metadata (cache-control,
|
||||
@@ -49,13 +56,15 @@ def s3_sync(site_name, site_dir):
|
||||
run(
|
||||
f"aws --endpoint-url {endpoint} s3 sync {html_dir}/ s3://{site_name}/ "
|
||||
f"--delete --only-show-errors "
|
||||
f"--cache-control '{CACHE_CONTROL}'"
|
||||
f"--cache-control '{CACHE_CONTROL}' "
|
||||
f"{exclude_flags}".rstrip()
|
||||
)
|
||||
print("Re-stamping metadata on all objects...")
|
||||
run(
|
||||
f"aws --endpoint-url {endpoint} s3 cp {html_dir}/ s3://{site_name}/ "
|
||||
f"--recursive --only-show-errors "
|
||||
f"--cache-control '{CACHE_CONTROL}'"
|
||||
f"--cache-control '{CACHE_CONTROL}' "
|
||||
f"{exclude_flags}".rstrip()
|
||||
)
|
||||
|
||||
|
||||
@@ -122,7 +131,7 @@ def render_site_manifests(site_name, action_dir, app_dir, manifests_dir, cfg):
|
||||
|
||||
|
||||
def deploy_static(site_name, site_dir, action_dir, token, cfg):
|
||||
s3_sync(site_name, site_dir)
|
||||
s3_sync(site_name, site_dir, excludes=cfg.get("excludes"))
|
||||
ensure_bucket_aliases(site_name, cfg["aliases"], os.environ.get("GARAGE_ADMIN_TOKEN"))
|
||||
|
||||
apps_dir = clone_apps(token)
|
||||
|
||||
Reference in New Issue
Block a user