1+ name : CI/CD Pipeline - Node.js API to AWS ECS
2+
3+ on :
4+ push :
5+ branches :
6+ - main
7+ - develop
8+ pull_request :
9+ branches :
10+ - main
11+ - develop
12+
13+ env :
14+ AWS_REGION : us-east-1
15+ ECR_REPOSITORY : node-api
16+ ECS_SERVICE : node-api-service
17+ ECS_CLUSTER : node-api-cluster
18+
19+ permissions :
20+ id-token : write
21+ contents : read
22+
23+ jobs :
24+ lint :
25+ name : Lint Code
26+ runs-on : ubuntu-22.04
27+ steps :
28+ - name : Checkout code
29+ uses : actions/checkout@b4ffde65f69735febad081b8f525ce356e475d86 # v4.1.1
30+
31+ - name : Setup Node.js
32+ uses : actions/setup-node@60edb5dd545a775178fbb3563ff8483803168bc5 # v4.0.2
33+ with :
34+ node-version : ' 20'
35+ cache : ' npm'
36+
37+ - name : Install dependencies
38+ run : npm ci
39+
40+ - name : Run ESLint
41+ run : npm run lint --if-present
42+
43+ test :
44+ name : Run Tests
45+ runs-on : ubuntu-22.04
46+ steps :
47+ - name : Checkout code
48+ uses : actions/checkout@b4ffde65f69735febad081b8f525ce356e475d86 # v4.1.1
49+
50+ - name : Setup Node.js
51+ uses : actions/setup-node@60edb5dd545a775178fbb3563ff8483803168bc5 # v4.0.2
52+ with :
53+ node-version : ' 20'
54+ cache : ' npm'
55+
56+ - name : Install dependencies
57+ run : npm ci
58+
59+ - name : Run tests
60+ run : npm test
61+
62+ - name : Upload coverage
63+ uses : codecov/codecov-action@5ecb98a3c6b747ed38dc09f64a43ec8d490d8de9 # v3.1.4
64+ if : always()
65+
66+ build-and-push :
67+ name : Build and Push Docker Image
68+ runs-on : ubuntu-22.04
69+ needs : [lint, test]
70+ if : github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
71+ outputs :
72+ image-tag : ${{ steps.image.outputs.tag }}
73+ steps :
74+ - name : Checkout code
75+ uses : actions/checkout@b4ffde65f69735febad081b8f525ce356e475d86 # v4.1.1
76+
77+ - name : Configure AWS credentials with OIDC
78+ uses : aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
79+ with :
80+ role-to-assume : ${{ secrets.AWS_ROLE_TO_ASSUME }}
81+ aws-region : ${{ env.AWS_REGION }}
82+ role-session-name : github-actions-session
83+
84+ - name : Login to Amazon ECR
85+ id : login-ecr
86+ uses : aws-actions/amazon-ecr-login@062b18b96a7aabf0d32092427e2b915fcc71c7de # v2.0.1
87+
88+ - name : Build and tag image
89+ id : image
90+ env :
91+ REGISTRY : ${{ steps.login-ecr.outputs.registry }}
92+ COMMIT_SHA : ${{ github.sha }}
93+ BRANCH_NAME : ${{ github.ref_name }}
94+ run : |
95+ IMAGE_TAG="${BRANCH_NAME}-${COMMIT_SHA::8}"
96+ docker build -t $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
97+ docker tag $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $REGISTRY/$ECR_REPOSITORY:latest
98+ echo "tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
99+ echo "registry=$REGISTRY" >> $GITHUB_OUTPUT
100+
101+ - name : Push image to ECR
102+ env :
103+ REGISTRY : ${{ steps.image.outputs.registry }}
104+ IMAGE_TAG : ${{ steps.image.outputs.tag }}
105+ run : |
106+ docker push $REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
107+ docker push $REGISTRY/$ECR_REPOSITORY:latest
108+
109+ terraform-plan :
110+ name : Terraform Plan
111+ runs-on : ubuntu-22.04
112+ needs : [build-and-push]
113+ if : github.event_name == 'push'
114+ steps :
115+ - name : Checkout code
116+ uses : actions/checkout@b4ffde65f69735febad081b8f525ce356e475d86 # v4.1.1
117+
118+ - name : Configure AWS credentials with OIDC
119+ uses : aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
120+ with :
121+ role-to-assume : ${{ secrets.AWS_ROLE_TO_ASSUME }}
122+ aws-region : ${{ env.AWS_REGION }}
123+ role-session-name : github-actions-session
124+
125+ - name : Setup Terraform
126+ uses : hashicorp/setup-terraform@3523b56c0e4a3f2d19eff39fe629ab42f7c5e2e4 # v2.4.0
127+
128+ - name : Terraform Init
129+ working-directory : terraform
130+ run : terraform init
131+
132+ - name : Terraform Format Check
133+ working-directory : terraform
134+ run : terraform fmt -check
135+
136+ - name : Terraform Validate
137+ working-directory : terraform
138+ run : terraform validate
139+
140+ - name : Terraform Plan
141+ working-directory : terraform
142+ env :
143+ TF_VAR_image_tag : ${{ needs.build-and-push.outputs.image-tag }}
144+ run : terraform plan -out=tfplan
145+
146+ - name : Upload Terraform Plan
147+ uses : actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5d # v4.3.1
148+ with :
149+ name : tfplan
150+ path : terraform/tfplan
151+
152+ deploy :
153+ name : Deploy to AWS ECS
154+ runs-on : ubuntu-22.04
155+ needs : [build-and-push, terraform-plan]
156+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
157+ environment :
158+ name : production
159+ steps :
160+ - name : Checkout code
161+ uses : actions/checkout@b4ffde65f69735febad081b8f525ce356e475d86 # v4.1.1
162+
163+ - name : Configure AWS credentials with OIDC
164+ uses : aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
165+ with :
166+ role-to-assume : ${{ secrets.AWS_ROLE_TO_ASSUME }}
167+ aws-region : ${{ env.AWS_REGION }}
168+ role-session-name : github-actions-session
169+
170+ - name : Download Terraform Plan
171+ uses : actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.1
172+ with :
173+ name : tfplan
174+ path : terraform
175+
176+ - name : Setup Terraform
177+ uses : hashicorp/setup-terraform@3523b56c0e4a3f2d19eff39fe629ab42f7c5e2e4 # v2.4.0
178+
179+ - name : Terraform Init
180+ working-directory : terraform
181+ run : terraform init
182+
183+ - name : Terraform Apply
184+ working-directory : terraform
185+ env :
186+ TF_VAR_image_tag : ${{ needs.build-and-push.outputs.image-tag }}
187+ run : terraform apply -auto-approve tfplan
188+
189+ - name : Update ECS Service
190+ run : |
191+ aws ecs update-service \
192+ --cluster $ECS_CLUSTER \
193+ --service $ECS_SERVICE \
194+ --force-new-deployment \
0 commit comments