This repository was archived by the owner on Feb 24, 2026. It is now read-only.
forked from ever-co/ever-gauzy
-
Notifications
You must be signed in to change notification settings - Fork 0
318 lines (281 loc) · 12.7 KB
/
Copy pathaws-deploy-api.yml
File metadata and controls
318 lines (281 loc) · 12.7 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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
name: Deploy API to AWS
on:
push:
branches: [dev-dspot]
tags:
- 'v*'
paths:
- 'apps/api/**/*.*'
- 'packages/auth/**/*.*'
- 'packages/common/**/*.*'
- 'packages/config/**/*.*'
- 'packages/contracts/**/*.*'
- 'packages/core/**/*.*'
- 'packages/desktop-lib/**/*.*'
- 'packages/plugin/**/*.*'
- 'packages/utils/**/*.*'
- 'packages/plugins/changelog/**/*.*'
- 'packages/plugins/integration-ai/**/*.*'
- 'packages/plugins/integration-github/**/*.*'
- 'packages/plugins/integration-hubstaff/**/*.*'
- 'packages/plugins/integration-jira/**/*.*'
- 'packages/plugins/integration-upwork/**/*.*'
- 'packages/plugins/integration-wakatime/**/*.*'
- 'packages/plugins/jitsu-analytics/**/*.*'
- 'packages/plugins/job-proposal/**/*.*'
- 'packages/plugins/job-search/**/*.*'
- 'packages/plugins/knowledge-base/**/*.*'
- 'packages/plugins/product-reviews/**/*.*'
- 'packages/plugins/sentry-tracing/**/*.*'
- 'packages/plugins/videos/**/*.*'
- '.deploy/api/**/*'
- '.github/workflows/aws-deploy-api.yml'
- '.github/workflows/api-dependencies.yml'
- 'package.json'
- 'yarn.lock'
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
type: choice
required: true
default: 'staging'
options:
- staging
- production
jobs:
check-dependencies:
name: Check and Build Dependencies
uses: ./.github/workflows/api-dependencies.yml
secrets: inherit
sync-infrastructure-config:
name: Sync Infrastructure Configuration
runs-on: ubuntu-latest
environment: ${{ startsWith(github.ref, 'refs/tags/v') && 'production' || 'staging' }}
permissions:
contents: read
id-token: write
outputs:
# Database outputs
db_host: ${{ steps.get-iac-outputs.outputs.db_host }}
db_port: ${{ steps.get-iac-outputs.outputs.db_port }}
db_name: ${{ steps.get-iac-outputs.outputs.db_name }}
db_user: ${{ steps.get-iac-outputs.outputs.db_user }}
# ECS outputs
ecs_cluster: ${{ steps.get-iac-outputs.outputs.ecs_cluster }}
ecs_service_api: ${{ steps.get-iac-outputs.outputs.ecs_service_api }}
ecs_service_webapp: ${{ steps.get-iac-outputs.outputs.ecs_service_webapp }}
ecr_repository_api: ${{ steps.get-iac-outputs.outputs.ecr_repository_api }}
ecr_repository_webapp: ${{ steps.get-iac-outputs.outputs.ecr_repository_webapp }}
ecr_repository_dependencies: ${{ steps.get-iac-outputs.outputs.ecr_repository_dependencies }}
# SSM Parameter paths
db_pass_parameter: ${{ steps.get-iac-outputs.outputs.db_pass_parameter }}
env:
AWS_REGION: ${{ vars.AWS_REGION }}
TERRAFORM_BACKEND_BUCKET: ${{ vars.OPENTOFU_BACKEND_BUCKET }}
TERRAFORM_BACKEND_REGION: ${{ vars.OPENTOFU_BACKEND_REGION }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: "~1.9"
tofu_wrapper: false
- name: Retrieve All Infrastructure Configuration from OpenTofu State
id: get-iac-outputs
run: |
# Determine environment-specific backend configuration
ENVIRONMENT="${{ startsWith(github.ref, 'refs/tags/v') && 'production' || 'staging' }}"
TERRAFORM_BACKEND_KEY="hubstaff_to_gauzy_migration/$ENVIRONMENT/terraform.tfstate"
echo "🔧 Initializing OpenTofu for $ENVIRONMENT environment..."
echo "Backend bucket: ${{ env.TERRAFORM_BACKEND_BUCKET }}"
echo "Backend key: $TERRAFORM_BACKEND_KEY"
echo "Backend region: ${{ env.TERRAFORM_BACKEND_REGION }}"
# Create minimal OpenTofu configuration for remote state access
mkdir -p /tmp/tofu-config
cd /tmp/tofu-config
cat > backend.tf << EOF
terraform {
backend "s3" {
bucket = "${{ env.TERRAFORM_BACKEND_BUCKET }}"
key = "$TERRAFORM_BACKEND_KEY"
region = "${{ env.TERRAFORM_BACKEND_REGION }}"
}
}
EOF
# Initialize OpenTofu with remote backend
tofu init
echo "📋 Retrieving all infrastructure outputs..."
# Database configuration
DB_HOST=$(tofu output -raw db_instance_address 2>/dev/null || echo "")
DB_PORT=$(tofu output -raw db_instance_port 2>/dev/null || echo "5432")
DB_NAME=$(tofu output -raw db_instance_name 2>/dev/null || echo "")
DB_USER=$(tofu output -raw db_instance_username 2>/dev/null || echo "")
# ECS configuration
ECS_CLUSTER=$(tofu output -raw ecs_cluster_name 2>/dev/null || echo "")
ECS_SERVICE_API=$(tofu output -raw ecs_backend_service_name 2>/dev/null || echo "")
ECS_SERVICE_WEBAPP=$(tofu output -raw ecs_frontend_service_name 2>/dev/null || echo "")
# ECR repository names (direct from OpenTofu outputs)
ECR_REPOSITORY_API=$(tofu output -raw ecr_api_repository_name 2>/dev/null || echo "")
ECR_REPOSITORY_WEBAPP=$(tofu output -raw ecr_webapp_repository_name 2>/dev/null || echo "")
ECR_REPOSITORY_DEPENDENCIES=$(tofu output -raw ecr_dependency_repository_name 2>/dev/null || echo "")
# SSM Parameter Store paths
DB_PASS_PARAMETER="/hubstaff_to_gauzy_migration/$ENVIRONMENT/db_password"
# Validate critical outputs
if [ -z "$DB_HOST" ] || [ -z "$ECS_CLUSTER" ] || [ -z "$ECR_REPOSITORY_API" ]; then
echo "❌ Critical infrastructure outputs are missing!"
echo "DB_HOST: '$DB_HOST'"
echo "ECS_CLUSTER: '$ECS_CLUSTER'"
echo "ECR_REPOSITORY_API: '$ECR_REPOSITORY_API'"
exit 1
fi
# Set outputs for other jobs
echo "db_host=$DB_HOST" >> $GITHUB_OUTPUT
echo "db_port=$DB_PORT" >> $GITHUB_OUTPUT
echo "db_name=$DB_NAME" >> $GITHUB_OUTPUT
echo "db_user=$DB_USER" >> $GITHUB_OUTPUT
echo "ecs_cluster=$ECS_CLUSTER" >> $GITHUB_OUTPUT
echo "ecs_service_api=$ECS_SERVICE_API" >> $GITHUB_OUTPUT
echo "ecs_service_webapp=$ECS_SERVICE_WEBAPP" >> $GITHUB_OUTPUT
echo "ecr_repository_api=$ECR_REPOSITORY_API" >> $GITHUB_OUTPUT
echo "ecr_repository_webapp=$ECR_REPOSITORY_WEBAPP" >> $GITHUB_OUTPUT
echo "ecr_repository_dependencies=$ECR_REPOSITORY_DEPENDENCIES" >> $GITHUB_OUTPUT
echo "db_pass_parameter=$DB_PASS_PARAMETER" >> $GITHUB_OUTPUT
# Log retrieved configuration (without sensitive data)
echo "✅ Successfully retrieved infrastructure configuration:"
echo "Environment: $ENVIRONMENT"
echo "Database Host: $DB_HOST"
echo "Database Port: $DB_PORT"
echo "Database Name: $DB_NAME"
echo "Database User: $DB_USER"
echo "ECS Cluster: $ECS_CLUSTER"
echo "ECS API Service: $ECS_SERVICE_API"
echo "ECS WebApp Service: $ECS_SERVICE_WEBAPP"
echo "ECR API Repository: $ECR_REPOSITORY_API"
echo "ECR WebApp Repository: $ECR_REPOSITORY_WEBAPP"
echo "ECR Dependencies Repository: $ECR_REPOSITORY_DEPENDENCIES"
# Cleanup
cd /
rm -rf /tmp/tofu-config
run-migrations:
name: Run Database Migrations
needs: [check-dependencies, sync-infrastructure-config]
runs-on: ubuntu-latest
environment: ${{ startsWith(github.ref, 'refs/tags/v') && 'production' || 'staging' }}
permissions:
contents: read
id-token: write
env:
# Static configuration
DB_TYPE: postgres
NODE_ENV: production
DB_SSL_MODE: true
DB_POOL_SIZE: 10
AWS_REGION: ${{ vars.AWS_REGION }}
DB_HOST: ${{ needs.sync-infrastructure-config.outputs.db_host }}
DB_PORT: ${{ needs.sync-infrastructure-config.outputs.db_port }}
DB_NAME: ${{ needs.sync-infrastructure-config.outputs.db_name }}
DB_USER: ${{ needs.sync-infrastructure-config.outputs.db_user }}
DB_PASS_PARAMETER: ${{ needs.sync-infrastructure-config.outputs.db_pass_parameter }}
ECR_REGISTRY: ${{ vars.ECR_REGISTRY }}
ECR_REPOSITORY_DEPENDENCIES: ${{ needs.sync-infrastructure-config.outputs.ecr_repository_dependencies }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Retrieve Database Password from Parameter Store
id: get-db-password
run: |
echo "🔐 Retrieving database password from Parameter Store..."
DB_PASS=$(aws ssm get-parameter --name "${{ env.DB_PASS_PARAMETER }}" --with-decryption --query 'Parameter.Value' --output text)
echo "::add-mask::$DB_PASS"
echo "DB_PASS=$DB_PASS" >> $GITHUB_ENV
- name: Run Database Migrations using Dependencies Image
run: |
echo "🚀 Running database migrations..."
docker run --rm \
-e DB_TYPE="${{ env.DB_TYPE }}" \
-e DB_HOST="${{ env.DB_HOST }}" \
-e DB_PORT="${{ env.DB_PORT }}" \
-e DB_NAME="${{ env.DB_NAME }}" \
-e DB_USER="${{ env.DB_USER }}" \
-e DB_PASS="${{ env.DB_PASS }}" \
-e DB_SSL_MODE="${{ env.DB_SSL_MODE }}" \
-e DB_POOL_SIZE="${{ env.DB_POOL_SIZE }}" \
-e NODE_ENV="${{ env.NODE_ENV }}" \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_DEPENDENCIES }}:latest-api-dev \
sh -c "yarn migration:run"
deploy-api:
name: Deploy API to AWS
needs: [check-dependencies, sync-infrastructure-config, run-migrations]
runs-on: ubuntu-latest
environment: ${{ startsWith(github.ref, 'refs/tags/v') && 'production' || 'staging' }}
permissions:
contents: read
id-token: write
env:
AWS_REGION: ${{ vars.AWS_REGION }}
ECR_REGISTRY: ${{ vars.ECR_REGISTRY }}
ECR_REPOSITORY_API: ${{ needs.sync-infrastructure-config.outputs.ecr_repository_api }}
ECR_REPOSITORY_DEPENDENCIES: ${{ needs.sync-infrastructure-config.outputs.ecr_repository_dependencies }}
ECS_CLUSTER: ${{ needs.sync-infrastructure-config.outputs.ecs_cluster }}
ECS_SERVICE_API: ${{ needs.sync-infrastructure-config.outputs.ecs_service_api }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build and tag API image
env:
IMAGE_TAG: ${{ github.sha }}
run: |
echo "🔨 Building API Docker image..."
docker build \
--build-arg GIT_HASH="${{ github.sha }}" \
--build-arg DEPENDENCIES_IMAGE="${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_DEPENDENCIES }}" \
-t ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_API }}:$IMAGE_TAG \
-t ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_API }}:latest \
-f .deploy/api/Dockerfile \
.
- name: Push API image to Amazon ECR
env:
IMAGE_TAG: ${{ github.sha }}
run: |
echo "📤 Pushing API image to ECR..."
docker push ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_API }} --all-tags
echo "api_image=${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY_API }}:$IMAGE_TAG" >> $GITHUB_ENV
- name: Update API ECS service
run: |
echo "🚀 Deploying API to ECS..."
echo "Cluster: ${{ env.ECS_CLUSTER }}"
echo "Service: ${{ env.ECS_SERVICE_API }}"
aws ecs update-service \
--cluster ${{ env.ECS_CLUSTER }} \
--service ${{ env.ECS_SERVICE_API }} \
--force-new-deployment
echo "⏳ Waiting for deployment to stabilize..."
aws ecs wait services-stable \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE_API }}
echo "✅ API deployment completed successfully!"