-
Notifications
You must be signed in to change notification settings - Fork 0
242 lines (203 loc) · 7.72 KB
/
Copy pathdeploy.yml
File metadata and controls
242 lines (203 loc) · 7.72 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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
name: Deploy to S3
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
AWS_REGION: ap-northeast-2
NODE_VERSION: '18'
jobs:
# 빌드 및 테스트
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.GIT_PERSONAL_ACCESS_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
# cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Setup environment
run: |
# 환경 결정 (개발/프로덕션만)
#if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
ENV="production"
#else
# ENV="development"
#fi
# 환경변수 설정
node scripts/setup-env.js $ENV setup
echo "ENVIRONMENT=$ENV" >> $GITHUB_ENV
- name: Validate environment
run: npm run env:validate
- name: Lint code
run: npm run lint
- name: Clean build artifacts and cache
run: |
echo "🧹 Cleaning dist folder..."
rm -rf dist
echo "🧹 Cleaning node_modules cache..."
rm -rf node_modules/.cache
echo "🧹 Cleaning npm cache..."
npm cache clean --force
echo "✅ Cleanup completed!"
- name: Build application
run: |
#if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
# npm run build:prod
npm run build:prod
#else
# npm run build:dev
#fi
# 빌드된 index.html 확인
echo "📋 Checking built index.html..."
echo "JS files referenced:"
grep -o 'src="[^"]*\.js"' dist/index.html || echo "No JS references found"
# 실제 생성된 JS 파일 확인
echo "📋 Actual JS files in dist:"
ls -lh dist/js/*.js || echo "No JS files found"
# 참조와 실제 파일이 일치하는지 검증
JS_REF=$(grep -o 'src="/js/app\.[^"]*\.js"' dist/index.html | sed 's|src="/js/||;s|"||' | head -1)
if [ -n "$JS_REF" ]; then
echo "Checking if referenced file exists: $JS_REF"
if [ -f "dist/js/$JS_REF" ]; then
echo "✅ Referenced file exists: $JS_REF"
else
echo "❌ ERROR: Referenced file NOT found: $JS_REF"
echo "Available files:"
ls -lh dist/js/
exit 1
fi
fi
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 1
# S3 배포
deploy:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.GIT_PERSONAL_ACCESS_TOKEN }}
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Deploy to S3
run: |
# 환경 결정
#if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
ENV="production"
# DEPLOY_PATH="/"
#else
# ENV="development"
# DEPLOY_PATH="/dev/"
#fi
DEPLOY_PATH=""
BUCKET="${{ secrets.S3_BUCKET }}"
echo "Deploying to $ENV environment..."
echo "S3 Bucket: $BUCKET"
echo "Deploy Path: $DEPLOY_PATH"
# S3에 파일 업로드 (경로별 배포)
# 정적 파일들 업로드 (캐시 설정, HTML/JSON 제외)
aws s3 sync dist/ s3://$BUCKET$DEPLOY_PATH \
--cache-control "public, max-age=31536000, immutable" \
--exclude "*.html" --exclude "*.json"
# HTML 파일은 캐시하지 않음
aws s3 cp dist/index.html s3://$BUCKET$DEPLOY_PATH/index.html \
--cache-control "no-cache, no-store, must-revalidate"
# manifest.json 파일이 있으면 업로드
if [ -f "dist/manifest.json" ]; then
aws s3 cp dist/manifest.json s3://$BUCKET$DEPLOY_PATH/manifest.json \
--cache-control "no-cache, no-store, must-revalidate"
fi
# Welcome 페이지 업로드
if [ -f "dist/welcome/index.html" ]; then
aws s3 cp dist/welcome/index.html s3://$BUCKET$DEPLOY_PATH/welcome/index.html \
--cache-control "no-cache, no-store, must-revalidate"
echo "✅ Welcome page uploaded"
else
echo "⚠️ Welcome page not found in dist/welcome/index.html"
fi
echo "Deployment completed successfully!"
echo "Application URL: https://$BUCKET.s3-website.ap-northeast-2.amazonaws.com$DEPLOY_PATH"
- name: CloudFront Invalidation
env:
CLOUD_FRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID}}
run: |
if [ -n "$CLOUD_FRONT_ID" ]; then
echo "Invalidating CloudFront cache..."
# 무효화 요청 생성
INVALIDATION_OUTPUT=$(aws cloudfront create-invalidation \
--distribution-id $CLOUD_FRONT_ID \
--paths "/*")
if [ $? -eq 0 ]; then
# 무효화 ID 추출
INVALIDATION_ID=$(echo "$INVALIDATION_OUTPUT" | grep -oP '"Id"\s*:\s*"\K[^"]+' | head -1)
if [ -n "$INVALIDATION_ID" ]; then
echo "✅ CloudFront cache invalidation initiated: $INVALIDATION_ID"
# 무효화 완료까지 대기 (최대 15분)
echo "Waiting for invalidation to complete (this may take up to 15 minutes)..."
MAX_WAIT_TIME=900 # 15분 (초)
WAIT_INTERVAL=10 # 10초마다 확인
ELAPSED_TIME=0
while [ $ELAPSED_TIME -lt $MAX_WAIT_TIME ]; do
sleep $WAIT_INTERVAL
ELAPSED_TIME=$((ELAPSED_TIME + WAIT_INTERVAL))
STATUS_OUTPUT=$(aws cloudfront get-invalidation \
--distribution-id $CLOUD_FRONT_ID \
--id $INVALIDATION_ID 2>&1)
if [ $? -eq 0 ]; then
STATUS=$(echo "$STATUS_OUTPUT" | grep -oP '"Status"\s*:\s*"\K[^"]+' | head -1)
if [ "$STATUS" == "Completed" ]; then
echo "✅ CloudFront cache invalidation completed!"
break
elif [ "$STATUS" == "InProgress" ]; then
PROGRESS=$((ELAPSED_TIME * 100 / MAX_WAIT_TIME))
echo "Invalidation in progress... (${PROGRESS}% of max wait time elapsed)"
fi
fi
done
if [ $ELAPSED_TIME -ge $MAX_WAIT_TIME ]; then
echo "⚠️ Invalidation is still in progress after maximum wait time. It will continue in the background."
fi
else
echo "⚠️ Failed to extract invalidation ID from response"
fi
else
echo "⚠️ Failed to invalidate CloudFront cache"
fi
else
echo "⚠️ CloudFront ID not configured, skipping invalidation"
fi
- name: Notify deployment
if: always()
run: |
if [[ "${{ job.status }}" == "success" ]]; then
echo "✅ Deployment successful!"
else
echo "❌ Deployment failed!"
fi