-
Notifications
You must be signed in to change notification settings - Fork 5
166 lines (148 loc) Β· 7.28 KB
/
deploy-s3.yml
File metadata and controls
166 lines (148 loc) Β· 7.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
inputs:
force_metadata_update:
description: 'Force metadata update for all files (bypasses size-only check)'
required: false
default: false
type: boolean
permissions:
contents: read
id-token: write
env:
AWS_REGION: "us-east-1"
S3_BUCKET_NAME: "blacktrigram-frontend-us-east-1-172017021075"
CLOUDFRONT_STACK_NAME: "blacktrigram-frontend"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
with:
egress-policy: block
allowed-endpoints: >
github.com:443
api.github.com:443
objects.githubusercontent.com:443
token.actions.githubusercontent.com:443
cloudformation.us-east-1.amazonaws.com:443
cloudfront.amazonaws.com:443
s3.us-east-1.amazonaws.com:443
s3.amazonaws.com:443
blacktrigram-frontend-us-east-1-172017021075.s3.us-east-1.amazonaws.com:443
blacktrigram-frontend-us-east-1-172017021075.s3.amazonaws.com:443
sts.us-east-1.amazonaws.com:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
with:
role-to-assume: arn:aws:iam::172017021075:role/GithubWorkFlowRole
role-session-name: githubworkflowrolesessiont2
aws-region: ${{ env.AWS_REGION }}
- name: Deploy to S3 with minimal API calls
run: |
# Optimized deployment: 6 sync operations instead of 16
# - Hashed/static assets use --size-only (content-addressed, safe to skip by size)
# - HTML and metadata use default sync (size+mtime) to catch same-size content changes
# - Does NOT use --delete to preserve legacy URLs on S3
if [ "${{ github.event.inputs.force_metadata_update }}" = "true" ]; then
# Force mode: use --exact-timestamps to force re-evaluation + metadata replace
HASHED_SYNC_FLAGS="--exact-timestamps --metadata-directive REPLACE"
DOCUMENT_SYNC_FLAGS="--exact-timestamps --metadata-directive REPLACE"
echo "π Force metadata update mode: re-uploading all files with updated metadata"
else
# Efficient mode: --size-only for hashed assets, default (size+mtime) for documents
HASHED_SYNC_FLAGS="--size-only"
DOCUMENT_SYNC_FLAGS=""
echo "π Efficient sync mode: --size-only for hashed assets, size+mtime for documents"
fi
# --- Deploy to root prefix (supports current URLs: blacktrigram.hack23.com/*) ---
# 1. Sync all static/hashed assets (everything except HTML and metadata) with immutable cache
echo "β‘ [root] Syncing static assets with immutable cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/ \
--exclude ".git/*" \
--exclude "*.html" \
--exclude "*.xml" \
--exclude "*.json" \
--exclude "*.txt" \
--cache-control "public, max-age=31536000, immutable" \
$HASHED_SYNC_FLAGS
# 2. Sync HTML files with short cache (must-revalidate, 1 hour)
echo "π [root] Syncing HTML files with revalidation cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/ \
--exclude "*" \
--include "*.html" \
--cache-control "public, max-age=3600, must-revalidate" \
--content-type "text/html; charset=utf-8" \
$DOCUMENT_SYNC_FLAGS
# 3. Sync metadata files (xml, json, txt) with 1-day cache (not content-hashed)
echo "π [root] Syncing metadata files with 1-day cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/ \
--exclude "*" \
--include "*.xml" \
--include "*.json" \
--include "*.txt" \
--cache-control "public, max-age=86400" \
$DOCUMENT_SYNC_FLAGS
# --- Deploy to /docs/ prefix (supports legacy URLs: blacktrigram.hack23.com/docs/*) ---
# 4. Sync all static/hashed assets to /docs/ with immutable cache
echo "β‘ [/docs/] Syncing static assets with immutable cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/docs/ \
--exclude ".git/*" \
--exclude "*.html" \
--exclude "*.xml" \
--exclude "*.json" \
--exclude "*.txt" \
--cache-control "public, max-age=31536000, immutable" \
$HASHED_SYNC_FLAGS
# 5. Sync HTML files to /docs/ with short cache
echo "π [/docs/] Syncing HTML files with revalidation cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/docs/ \
--exclude "*" \
--include "*.html" \
--cache-control "public, max-age=3600, must-revalidate" \
--content-type "text/html; charset=utf-8" \
$DOCUMENT_SYNC_FLAGS
# 6. Sync metadata files to /docs/ with 1-day cache
echo "π [/docs/] Syncing metadata files with 1-day cache..."
aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/docs/ \
--exclude "*" \
--include "*.xml" \
--include "*.json" \
--include "*.txt" \
--cache-control "public, max-age=86400" \
$DOCUMENT_SYNC_FLAGS
echo "β
Deployment completed (6 sync ops instead of 16, ~63% fewer CloudTrail events)"
# Invalidate CloudFront cache to ensure latest content is served
- name: Invalidate CloudFront
run: |
echo "π Discovering CloudFront distribution ID from stack: ${{ env.CLOUDFRONT_STACK_NAME }}"
CloudFrontDistId=$(aws cloudformation describe-stacks \
--stack-name ${{ env.CLOUDFRONT_STACK_NAME }} \
--query "Stacks[0].Outputs[?OutputKey=='CloudFrontDistributionId'].OutputValue" \
--output text 2>/dev/null || echo "")
if [ -z "$CloudFrontDistId" ]; then
echo "β οΈ Warning: CloudFront distribution ID not found in stack outputs"
echo "Attempting to find distribution by S3 origin domain..."
# List all distributions and filter by S3 bucket origin
CloudFrontDistId=$(aws cloudfront list-distributions \
--output json 2>/dev/null | \
jq -r ".DistributionList.Items[] | select(.Origins.Items[].DomainName | contains(\"${{ env.S3_BUCKET_NAME }}\")) | .Id" | \
head -n 1 || echo "")
fi
if [ -z "$CloudFrontDistId" ] || [ "$CloudFrontDistId" = "None" ]; then
echo "β Error: Could not discover CloudFront distribution ID"
exit 1
fi
echo "β
Found CloudFront distribution: $CloudFrontDistId"
echo "π Creating cache invalidation for all paths..."
aws cloudfront create-invalidation \
--distribution-id $CloudFrontDistId \
--paths "/*"
echo "β
CloudFront cache invalidation completed"