Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 208 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
name: CI/CD Pipeline for Node.js REST API

on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop

env:
AWS_REGION: us-east-1
ECR_REPOSITORY: nodejs-rest-api
ECS_SERVICE: nodejs-rest-api-service
ECS_CLUSTER: nodejs-rest-api-cluster
ECS_TASK_DEFINITION: nodejs-rest-api-task

permissions:
id-token: write
contents: read

jobs:
lint:
name: Lint Code
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3ce8f4f8db2c5c91e
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run ESLint
run: npm run lint --if-present

- name: Run Prettier check
run: npm run format:check --if-present

test:
name: Run Tests
runs-on: ubuntu-22.04
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3ce8f4f8db2c5c91e
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run unit tests
run: npm run test --if-present

- name: Run integration tests
run: npm run test:integration --if-present

- name: Generate coverage report
run: npm run test:coverage --if-present

- name: Upload coverage to Codecov
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f87a6204de0b3bbce7
with:
files: ./coverage/coverage-final.json
flags: unittests
fail_ci_if_error: false

security-scan:
name: Security Scan
runs-on: ubuntu-22.04
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3ce8f4f8db2c5c91e
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run npm audit
run: npm audit --production || true

- name: Run Snyk scan
uses: snyk/actions/node@b98d528857969a2c7d1d62a8e6a469e0521d658d
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
continue-on-error: true

build:
name: Build Application
runs-on: ubuntu-22.04
needs: [lint, test]
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3ce8f4f8db2c5c91e
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build application
run: npm run build --if-present

- name: Upload build artifacts
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35165aff7ee4d3e0
with:
name: build-artifacts
path: dist/
retention-days: 1

build-and-push-image:
name: Build and Push Docker Image
runs-on: ubuntu-22.04
needs: [build, security-scan]
if: github.event_name == 'push'
outputs:
image-uri: ${{ steps.image.outputs.image-uri }}
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Download build artifacts
uses: actions/download-artifact@65a9edc5881444af0b9a21b5bd54bp4562bebdf7
with:
name: build-artifacts
path: dist/

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e3a5de7a
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@2fc7aceee023b451c3dd37ef7147e18b74f7ac565

- name: Build, tag, and push image to Amazon ECR
id: image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
echo "image-uri=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595324a9b052078dec94873e36ab3f8ef055adff1
with:
image-ref: ${{ steps.image.outputs.image-uri }}
format: 'sarif'
output: 'trivy-results.sarif'

- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@4dd8ab6fcee4130fa2422af25490ec3f58fe9534
with:
sarif_file: 'trivy-results.sarif'

deploy-to-ecs:
name: Deploy to AWS ECS
runs-on: ubuntu-22.04
needs: build-and-push-image
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment:
name: production
url: https://api.example.com
steps:
- name: Checkout code
uses: actions/checkout@a5ac7e51b41094c7467393582ac550c2ba79612f

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e3a5de7a
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}

- name: Get task definition
run: |
aws ecs describe-task-definition \
--task-definition $ECS_TASK_DEFINITION \
--region $
Loading