1+ name : Deploy React to S3 + CloudFront
2+
3+ on :
4+ push :
5+ branches :
6+ - develop
7+ workflow_dispatch : {}
8+
9+ env :
10+ AWS_REGION : ap-northeast-2
11+ S3_BUCKET : kickytime-bucket
12+ CF_DIST_ID : ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }}
13+ BUILD_DIR : build
14+
15+ jobs :
16+ deploy :
17+ runs-on : ubuntu-latest
18+ permissions :
19+ id-token : write
20+ contents : read
21+ steps :
22+ - name : Checkout
23+ uses : actions/checkout@v4
24+
25+ - name : Setup Node
26+ uses : actions/setup-node@v4
27+ with :
28+ node-version : 20
29+ cache : npm
30+
31+ - name : Install & Build
32+ run : |
33+ npm ci
34+ npm run build
35+
36+ - name : Detect build output dir
37+ id : detect
38+ run : |
39+ set -e
40+ echo "Repository root:"
41+ ls -la
42+ for d in build dist out; do
43+ if [ -d "$d" ]; then
44+ echo "Detected build dir: $d"
45+ echo "BUILD_DIR=$d" >> "$GITHUB_ENV"
46+ exit 0
47+ fi
48+ done
49+ echo "::error::No build output directory found (expected one of: build, dist, out)."
50+ exit 1
51+
52+ - name : Verify build dir
53+ run : |
54+ echo "Using BUILD_DIR=$BUILD_DIR"
55+ ls -la "$BUILD_DIR"
56+
57+ - name : Configure AWS credentials (OIDC)
58+ uses : aws-actions/configure-aws-credentials@v4
59+ with :
60+ role-to-assume : ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
61+ aws-region : ${{ env.AWS_REGION }}
62+
63+ - name : Upload hashed assets
64+ run : |
65+ aws s3 sync "$BUILD_DIR" "s3://$S3_BUCKET" \
66+ --delete \
67+ --exclude "index.html" \
68+ --cache-control "public,max-age=31536000,immutable"
69+
70+ - name : Upload index.html
71+ run : |
72+ aws s3 cp "$BUILD_DIR/index.html" "s3://$S3_BUCKET/index.html" \
73+ --cache-control "no-cache" \
74+ --content-type "text/html; charset=utf-8"
75+
76+ - name : Invalidate index.html
77+ run : |
78+ aws cloudfront create-invalidation \
79+ --distribution-id "$CF_DIST_ID" \
80+ --paths "/index.html"
0 commit comments