Skip to content

🚀 Add CI/CD pipeline (via OpsTools) #2

🚀 Add CI/CD pipeline (via OpsTools)

🚀 Add CI/CD pipeline (via OpsTools) #2

Workflow file for this run

name: Node.js API CI/CD Pipeline
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: node-api
ECS_SERVICE: node-api-service
ECS_CLUSTER: production
permissions:
contents: read
id-token: write
jobs:
lint:
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@9bb56186c3b09b1872191b74733305c135a6d0e9
- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3f667f4173c5c7605
with:
node-version: '18.18.0'
cache: npm
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint --if-present
test:
runs-on: ubuntu-22.04
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@9bb56186c3b09b1872191b74733305c135a6d0e9
- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178fac7f3f667f4173c5c7605
with:
node-version: '18.18.0'
cache: npm
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test --if-present
- name: Generate coverage report
run: npm run test:coverage --if-present
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.4
with:
files: ./coverage/coverage-final.json
flags: unittests
fail_ci_if_error: false
build:
runs-on: ubuntu-22.04
needs: test
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
outputs:
image_uri: ${{ steps.image.outputs.uri }}
steps:
- name: Checkout code
uses: actions/checkout@9bb56186c3b09b1872191b74733305c135a6d0e9
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4.0.1
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}
role-duration-seconds: 900
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2.0.1
- name: Build Docker image
id: docker_build
uses: docker/build-push-action@v5.1.0
with:
context: .
push: false
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
cache-from: type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache
cache-to: type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache,mode=max
outputs: type=docker,dest=/tmp/image.tar
- name: Push Docker image to ECR
run: |
docker load --input /tmp/image.tar
docker push ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
docker push ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
- name: Output image URI
id: image
run: echo "uri=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}" >> $GITHUB_OUTPUT
validate-terraform:
runs-on: ubuntu-22.04
needs: test
steps:
- name: Checkout code
uses: actions/checkout@9bb56186c3b09b1872191b74733305c135a6d0e9
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2.1.0
with:
terraform_version: 1.6.0
- name: Terraform Format Check
run: terraform fmt -check -recursive ./terraform
- name: Terraform Init
run: cd terraform && terraform init -backend=false
- name: Terraform Validate
run: cd terraform && terraform validate
- name: TFLint
uses: terraform-linters/setup-tflint@v4.0.0
with:
tflint_version: v0.48.0
- name: Run TFLint
run: cd terraform && tflint --init && tflint
deploy-to-ecs:
runs-on: ubuntu-22.04
needs: [build, validate-terraform]
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Checkout code
uses: actions/checkout@9bb56186c3b09b1872191b74733305c135a6d0e9
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4.0.1
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}
role-duration-seconds: 1800
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2.1.0
with:
terraform_version: 1.6.0
- name: Terraform Init
run: cd terraform && terraform init
- name: Terraform Plan
run: cd terraform && terraform plan -var="image_tag=${{ needs.build.outputs.image_uri }}" -out=tfplan
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: cd terraform && terraform apply -auto-approve tfplan
- name: Update ECS service
run: |
aws ecs update-service \
--cluster ${{ env.ECS_CLUSTER }} \
--service ${{ env.ECS_SERVICE }} \
--force-new-deployment \
--region ${{ env.AWS_REGION }}
- name: Wait for ECS service update
run: |
aws ecs wait services-stable \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE }} \
--region ${{ env.AWS_REGION }}
notify:
runs-on: ubuntu-22.04
needs: [lint, test, build, validate-terraform, deploy-to-ecs]
if: always()
steps:
- name: Slack notification on failure
if: failure()
uses: slackapi/slack-github-action@v1.24.0
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "GitHub Action failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
- name: Slack notification on success
if: success()
uses: slackapi/slack-github-action@v1.24.0
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "GitHub Action succeeded: ${{ github.server_url }}/${{ github.repository }}/