55 branches : [main]
66 paths :
77 - ' website/**'
8+ - ' blog/**'
89 - ' infra/terraform/website/**'
910 - ' .github/workflows/deploy-website.yml'
1011 workflow_dispatch :
@@ -50,13 +51,20 @@ jobs:
5051 - name : Generate llms.txt and AGENTS.md
5152 run : pnpm --filter iii-website build
5253
54+ - name : Build blog (Astro → blog/dist/)
55+ run : pnpm --filter iii-blog build
56+
5357 - name : Configure AWS credentials (GitHub OIDC)
5458 uses : aws-actions/configure-aws-credentials@v4
5559 with :
5660 role-to-assume : ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
5761 aws-region : ${{ env.AWS_REGION }}
5862
59- - name : Sync static assets (long cache, immutable)
63+ # Blog and website share the bucket; the blog lives under the /blog/
64+ # prefix and is wiped + repopulated by its own sync below. The website
65+ # sync therefore must exclude blog/* so its --delete doesn't wipe blog
66+ # output between the two steps.
67+ - name : Sync website static assets (long cache, immutable)
6068 run : |
6169 aws s3 sync website/ "s3://${{ vars.S3_BUCKET }}/" \
6270 --delete \
@@ -70,17 +78,39 @@ jobs:
7078 --exclude "pnpm-lock.yaml" \
7179 --exclude ".gitignore" \
7280 --exclude "README.md" \
73- --exclude "vercel.json"
81+ --exclude "vercel.json" \
82+ --exclude "blog/*"
7483
75- - name : Sync HTML and AI snapshot (no cache, must revalidate)
84+ - name : Sync website HTML and AI snapshot (no cache, must revalidate)
7685 run : |
7786 aws s3 sync website/ "s3://${{ vars.S3_BUCKET }}/" \
7887 --delete \
7988 --cache-control "public,max-age=0,must-revalidate" \
8089 --exclude "*" \
8190 --include "*.html" \
8291 --include "llms.txt" \
83- --include "AGENTS.md"
92+ --include "AGENTS.md" \
93+ --exclude "blog/*"
94+
95+ # Blog assets under _astro/ are content-hashed by Astro, so they're
96+ # safe to mark immutable. HTML and rss.xml must revalidate so new posts
97+ # surface immediately after the CloudFront invalidation.
98+ - name : Sync blog static assets (long cache, immutable)
99+ run : |
100+ aws s3 sync blog/dist/ "s3://${{ vars.S3_BUCKET }}/blog/" \
101+ --delete \
102+ --cache-control "public,max-age=31536000,immutable" \
103+ --exclude "*.html" \
104+ --exclude "*.xml"
105+
106+ - name : Sync blog HTML and RSS (no cache, must revalidate)
107+ run : |
108+ aws s3 sync blog/dist/ "s3://${{ vars.S3_BUCKET }}/blog/" \
109+ --delete \
110+ --cache-control "public,max-age=0,must-revalidate" \
111+ --exclude "*" \
112+ --include "*.html" \
113+ --include "*.xml"
84114
85115 - name : Create CloudFront invalidation
86116 id : invalidation
0 commit comments