NextJS Setup CI/CD using Github Action & AWS Codedeploy

NextJS Setup CI/CD using Github Action & AWS Codedeploy

Create IAM Role

Create Role for EC2

  1. Click on Create Role

  2. Select EC2

  3. Click Next

  4. Add AmazonS3ReadOnlyAccess Permissions

  5. Enter RoleName\=MyEC2Role

Create Role for Codedeploy

  • Click on Create Role

  • Click on next

  • Click next

  • RoleName:- My-codedeployeRole

  • Click on create

Create S3 Bucket

  • Click on Create bucket

  • Bucket name:- myfrontendbuild

    Note:- Bucket name is globally unique so in your case, this should be different

  • click on create bucket

Create Server

Name and tags: TestServer
Application and OS Images: Ubuntu
Key Pair: Create Key pair file :- TestServerNew.pem for the Login
Network Setting

  • Create security group

  • Allow SSH traffic from : Anywhere

  • Allow HTTP traffic

  • Allow HTTPS traffic

Advanced details

  • IAM instance profile: MyEC2Role

  • User data

      #!/bin/bash
      sudo apt-get update
      sudo apt-get install -y ruby
      sudo apt-get install -y wget
      cd /home/ubuntu
      wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/latest/install
      chmod +x ./install
      sudo ./install auto
    

    Note:- Here we are installing AWS codedeploy agent

  • Click on Launch Instant

  • Wait Once EC2 Instant start

Create Deployment

Create application

  • Click on Create an application

  • Application name:- frontend

  • Compute platform:- EC2

  • Click on Create

Create deployment group

  • Click on create Deployment group

Create IAM User

Creating IAM User for GitHub codedeploy

  • Go to IAM

  • Click on Policies

  • Click on Create Policies

  • Click on JSON

  • Copy the below JSON & Replace the Resource URL

    Note:- Here Resource URL you will get from

    -> 1st Resource ARN get from s3 bucket bucket -> click on Properties

    -> 2nd Resource ARN get from Codedeploy -> click on Applications -> click on frontend App -> click on deployment group Dev

  •   {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "s3:Get*",
              "s3:List*",
              "s3:PutObject",
              "s3:ListMultipartUploadParts",
              "s3:AbortMultipartUpload"
            ],
            "Resource": ["arn:aws:s3:::myfrontendbuild/*"]
          },
          {
            "Action": [
              "codedeploy:Batch*",
              "codedeploy:Get*",
              "codedeploy:List*",
              "codedeploy:RegisterApplicationRevision",
              "codedeploy:CreateDeployment"
            ],
            "Effect": "Allow",
            "Resource": ["arn:aws:iam::321448195788:role/My-codedeployeRole"]
          }
        ]
      }
    
  • Click next

  • Policy name:- MyGithubCodedeplyPolicy

  • Click on create policy

  • Click on Create user

  • UserName:- githubCodedeploy

  • Click on Attach policies directly

  • Add MyGithubCodedeplyPolicy

  • Click Next Create User

  • Click on githubCodedeploy User

  • Go to Tab Security credentials

  • Click on Create access-key

  • Click Command Line Interface (CLI)

  • Click next

  • Copy Access key & Access secret Details This we will add in Github variables

Github

Setup Environment

  • Here we can add environment variable which we will user in .env file

Workflow

  • .github/workflows/node.js.yml

      name: DEV Node.js CI
    
      on:
        push:
          branches: ["main"]
    
      jobs:
        build:
          name: Build
          runs-on: ubuntu-latest
          strategy:
            matrix:
              node-version: [16.x]
          steps:
            - uses: actions/checkout@v3
    
            - name: Use Node.js ${{ matrix.node-version }}
              uses: actions/setup-node@v3
              with:
                node-version: ${{ matrix.node-version }}
    
            - name: Create .env file
              uses: ozaytsev86/create-env-file@v1
              with:
                ENV_API_URL: ${{ vars.API_URL }}
    
            - name: "Build project"
              run: |
                yarn install
                yarn build
                rm -r node_modules
    
            - name: AWS CodeDeploy
              uses: sourcetoad/aws-codedeploy-action@v1
              with:
                aws_access_key: ${{ secrets.AWS_SECRET_ID }}
                aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
                aws_region: ap-south-1
                codedeploy_name: frontend
                codedeploy_group: Dev
                codedeploy_register_only: false
                s3_bucket: myfrontendbuild
                s3_folder: dev
                max_polling_iterations: 0
                directory: ./
    
  • Here we are doing a build of NextJS & Deploying to AWS using Codedeploy Service

  • appspec.yml

      version: 0.0
      os: linux
      files:
        - source: /
          destination: /var/frontend/
          overwrite: true
      file_exists_behavior: OVERWRITE
    
      hooks:
        BeforeInstall:
          - location: scripts/before-install.sh
            timeout: 300
            runas: root
        AfterInstall:
          - location: scripts/after-install.sh
            timeout: 300
            runas: root
        ApplicationStart:
          - location: scripts/application-start.sh
            timeout: 300
            runas: root
    
  • scripts/before-install.sh

    Here we are installing node, yarn & pm2

      #!/bin/bash
      curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
      export NVM_DIR="$HOME/.nvm"
      [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
      [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
      nvm install 16.14.2
      npm install --global yarn
      npm install pm2 -g
    
      ln -sf $(which npm) /usr/local/bin/npm
      ln -sf $(which node) /usr/local/bin/node
      ln -sf $(which yarn) /usr/local/bin/yarn
      ln -sf $(which pm2) /usr/local/bin/pm2
    
  • scripts/after-install.sh

    Installing packages

      #!/bin/bash
      cd /var/frontend/
      rm -r node_modules/
      yarn install
    
  • scripts/application-start.sh

    pm2 restart if pm2 already exist else start pm2 service

      #!/bin/bash
      pm2 describe app > /dev/null
      RUNNING=$?
    
      if [ "${RUNNING}" -ne 0 ]; then
        pm2 start yarn --name app -- start
      else
        pm2 reload app
      fi;
    
  • Once you commit code in GitHub. Workflow will start building project and transfer that build Zip to S3 & AWS Codedeploy will start

  • After codedeploy succeed you can check the Website by
    http://<Public IPv4 address\>:4000/