Skip to content

Commit b73d22a

Browse files
committed
ci: add CI/CD pipeline via OpsTools
1 parent 211fedb commit b73d22a

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

.github/workflows/ci-cd.yml

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
name: Node.js API CI/CD Pipeline
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+
ECS_TASK_DEFINITION: node-api-task
19+
20+
jobs:
21+
lint-test:
22+
name: Lint and Test
23+
runs-on: ubuntu-22.04
24+
strategy:
25+
matrix:
26+
node-version: [18.x, 20.x]
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
30+
31+
- name: Setup Node.js ${{ matrix.node-version }}
32+
uses: actions/setup-node@60edb5dd545a775178fac7f3a11ecda6e5a4f69f # v4.0.2
33+
with:
34+
node-version: ${{ matrix.node-version }}
35+
cache: npm
36+
37+
- name: Install dependencies
38+
run: npm ci
39+
40+
- name: Run linter
41+
run: npm run lint --if-present
42+
43+
- name: Run tests
44+
run: npm test --if-present
45+
46+
- name: Generate coverage report
47+
run: npm run coverage --if-present
48+
continue-on-error: true
49+
50+
- name: Upload coverage to Codecov
51+
uses: codecov/codecov-action@125fc84a3e5e4183e5e9c34b23b9ef1d16cbf484 # v3.1.6
52+
if: always()
53+
with:
54+
files: ./coverage/coverage-final.json
55+
fail_ci_if_error: false
56+
57+
security-scan:
58+
name: Security Scan
59+
runs-on: ubuntu-22.04
60+
steps:
61+
- name: Checkout code
62+
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
63+
64+
- name: Run Trivy vulnerability scanner
65+
uses: aquasecurity/trivy-action@6e7b7d1fd3e4692731fcf9cdff0f8244cfad8103 # v0.24.0
66+
with:
67+
scan-type: fs
68+
scan-ref: .
69+
format: sarif
70+
output: trivy-results.sarif
71+
72+
- name: Upload Trivy results to GitHub Security tab
73+
uses: github/codeql-action/upload-sarif@cf7e9f23492505046de19cd2d8569798fc6f4eac # v3.25.4
74+
with:
75+
sarif_file: trivy-results.sarif
76+
77+
build-image:
78+
name: Build and Push Docker Image
79+
runs-on: ubuntu-22.04
80+
needs: [lint-test, security-scan]
81+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
82+
permissions:
83+
id-token: write
84+
contents: read
85+
outputs:
86+
image-uri: ${{ steps.image.outputs.image-uri }}
87+
steps:
88+
- name: Checkout code
89+
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
90+
91+
- name: Configure AWS credentials via OIDC
92+
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e93febb1 # v4.0.2
93+
with:
94+
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
95+
aws-region: ${{ env.AWS_REGION }}
96+
97+
- name: Login to Amazon ECR
98+
id: login-ecr
99+
uses: aws-actions/amazon-ecr-login@062b18b96a7aff0 # v2.0.1
100+
101+
- name: Set up Docker Buildx
102+
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16eca30d26365 # v3.0.0
103+
104+
- name: Build and push Docker image
105+
id: docker-build
106+
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
107+
with:
108+
context: .
109+
push: true
110+
tags: |
111+
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
112+
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
113+
cache-from: type=gha
114+
cache-to: type=gha,mode=max
115+
build-args: |
116+
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
117+
VCS_REF=${{ github.sha }}
118+
119+
- name: Output image URI
120+
id: image
121+
run: |
122+
echo "image-uri=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}" >> $GITHUB_OUTPUT
123+
124+
terraform-plan:
125+
name: Terraform Plan
126+
runs-on: ubuntu-22.04
127+
needs: build-image
128+
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
129+
permissions:
130+
id-token: write
131+
contents: read
132+
pull-requests: write
133+
steps:
134+
- name: Checkout code
135+
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
136+
137+
- name: Configure AWS credentials via OIDC
138+
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e93febb1 # v4.0.2
139+
with:
140+
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
141+
aws-region: ${{ env.AWS_REGION }}
142+
143+
- name: Setup Terraform
144+
uses: hashicorp/setup-terraform@v2.0.3
145+
with:
146+
terraform_version: 1.7.0
147+
148+
- name: Terraform Format Check
149+
run: terraform fmt -check -recursive ./terraform
150+
151+
- name: Terraform Init
152+
run: cd terraform && terraform init -backend-config="bucket=${{ secrets.TERRAFORM_STATE_BUCKET }}" -backend-config="key=prod/terraform.tfstate" -backend-config="region=${{ env.AWS_REGION }}"
153+
154+
- name: Terraform Validate
155+
run: cd terraform && terraform validate
156+
157+
- name: Terraform Plan
158+
id: plan
159+
run: |
160+
cd terraform && terraform plan \
161+
-var="image_uri=${{ needs.build-image.outputs.image-uri }}" \
162+
-var="environment=staging" \
163+
-out=tfplan
164+
continue-on-error: true
165+
166+
- name: Comment Terraform Plan on PR
167+
if: github.event_name == 'pull_request'
168+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
169+
with:
170+
script: |
171+
const fs = require('fs');
172+
const plan = fs.readFileSync('terraform/tfplan', 'utf8');
173+
github.rest.issues.createComment({
174+
issue_number: context.issue.number,
175+
owner: context.repo.owner,
176+
repo: context.repo.repo,
177+
body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\``
178+
});
179+
180+
deploy-staging:
181+
name: Deploy to Staging
182+
runs-on: ubuntu-22.04
183+
needs: [build-image, terraform-plan]
184+
if: github.event_name == '

0 commit comments

Comments
 (0)