Deployment Nuxt3 Project in AWS EC2 with AWS CodeDeploy and Github Action - Code part

Server

Language :

Hi, I’m Lovefield.

This article describes how to deploy Nuxt3 project using Github Action and AWS CodeDeploy, following “Deployment Nuxt3 Project in AWS EC2 with AWS CodeDeploy and Github Action - Setting part

1.Install AWS CodeDeploy Agent

First install the AWS CodeDeploy Agent on the instance where you want to run the deployment. Enter the following command to proceed with the installation.

shell

sudo apt update
sudo apt install ruby-full
sudo apt install wget
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto

Note that it is recommended to do so after giving the IAM settings to the instance. If you gave an IAM role to an instance after the Code Deploy Agent was installed, the role does not apply and you must restart the CodeDeploy Agent. In that case, please restart using the command sudo service codedeploy-agent restart.

Use the following commands to verify that the Code Deploy Agent is installed and running.

shell

sudo service codedeploy-agent status
> codedeploy-agent.service - LSB: AWS CodeDeploy Host Agent
> Loaded: loaded (/etc/init.d/codedeploy-agent; generated)
> Active: active (running) since Tue 2023-11-07 10:20:04 KST; 5h 39min ago

2. Create Github Action

Create the file .github/workflows/deploy.yml to set up Github action.

yml

name: Deploy

on:
   pull_request:
       branches:
           - stage
       types: [closed]

The "on" part is the part that specifies the trigger. Triggered when "pull_request" occurred. Properties add when PR is directed to stage and when PR is closed. PR recognizes merged as closed.

yml

jobs:
   buildAndDeploy:
       if: github.event.pull_request.merged == true
       runs-on: ubuntu-latest
       permissions:
           contents: read
           packages: write

The "jobs" part is actually the space where you write the command statement. You have created a task called "buildAndDeploay" and attach conditions to the bottom of it. The statement "if" determines whether the PR is actually merged. The buildAndDeploy entry runs only when merged.

Github Action allows you to use Ubuntu, MacOS, and Windows as virtual machines. Among them, we designated them to use the familiar ubuntu. Permissions is a permission-related setting. I give you read and write permissions because you need to build.

yml

       steps:
           - uses: actions/checkout@v3

           - uses: actions/setup-node@v3
             with:
                 node-version: "18.x"
                 registry-url: https://npm.pkg.github.com
                 scope: "@octocat"

           - uses: szenius/set-timezone@v1.2
             with:
                 timezoneLinux: "Asia/Seoul"

           - name: Check version
             run: node -v

           - name: Get current date
             id: date
             run: echo "date=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT

The "steps" section is a list of commands that are executed sequentially on the virtual machine in Github Action. First, run the items that you need by default.

The actions/checkout@v3 section is a command that allows the branch of the current store to be used. It's a must-have part of creating Action.

actions/setup-node@v3 specifies the version of the node to use because Node.js must be used.

The time on the computer where Github Action runs is the UTC time zone by default. We're going to use the Korean time zone, so we'll designate it as "Asia/Seoul".

Save the time zone when the action ran because you wanted to use a timestamp in the Build file. You will use the following command to name the file.

yml

           - name: Install
             run: yarn install --frozen-lockfile

           - name: Create env file
             run: echo "$ENV_VALUE" >> .env
             env:
                 ENV_VALUE: ${{ secrets.STAGE_BUILD_ENV }}

           - name: Build
             run: yarn run build

           - name: Get file name
             id: file
             run: echo "filename=front-end-${{ steps.date.outputs.date }}.zip" >> $GITHUB_OUTPUT

           - name: Create ZIP file
             run: zip -qq -r ./${{ steps.file.outputs.filename }} .

           - name: Configure AWS credentials
             uses: aws-actions/configure-aws-credentials@v3
             with:
                 aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
                 aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
                 aws-region: ap-northeast-2

           - name: Upload Build file
             run: aws s3 cp --region ap-northeast-2 ./${{ steps.file.outputs.filename }} s3://deploy/${{ steps.file.outputs.filename }}

           - name: Create AWS codedeploy
             run: aws deploy create-deployment
                 --application-name Git-action-stag
                 --deployment-config-name CodeDeployDefault.AllAtOnce
                 --deployment-group-name git-action-stage-group
                 --s3-location bucket=deploy,key=${{ steps.file.outputs.filename }},bundleType=zip

The "Install" part is familiar to you. Install the necessary modules before you build.

The "Create env file" part is the process of making the settings registered in secrets into a .env file. Due to the nature of the project, I used the .env file, so I wrote it because I needed it.

The "Build" part is the syntax for finally executing Build.

Specify the file name to use in the "Get file name" section. Combined with the date specified above, a file name in the form of "front-end-YYYYYMMDD-HHMMSS.zip" is configured.

In the "Create Zip file" section, create a zip file using the file name declared earlier.

In the "Configure AWS Credentials" section, set permissions to access AWS.

In the "Upload Build file" section, upload the compressed Build file to the S3 bucket.

In the "Create AWS Codeddeploy" section, specify the file location you uploaded to S3, the application you set up in AWS "CodeDeploy", and send a deployment request.

3. Create appspec.yml

apspec.yml is a file that you refer to when AWS Code Deploy runs.

Create the file "appspec.yml" at the top of the repository.

yml

version: 0.0
os: linux

files:
   - source: /
     destination: /home/deploy/action
     overwrite: yes

permissions:
   - object: /
     pattern: "**"

hooks:
   ApplicationStart:
       - location: deploy.sh
         timeout: 60
         runas: root

The "files" section determines where files uploaded to S3 will be released. The source part is not the path of the EC2 instance; it is the path of the compressed file. The "destination" part is the actual path of the EC2 instance.

The "permission" part is the user's permission to execute the current command.

"hooks" can specify which scripts to run during the deployment process. There are many points in time, but we used ApplicationStart.

4. Create deploy.sh

The hook file specified in apspec.yml.

Create deploy.sh  at the top of the repository.

shell

#!/usr/bin/env bash

cd /home/deploy/action

TIMESTAMP=`date +%Y%m%d`

echo ">>> 프론트 재시작 스크립트 - $(date +%Y-%m-%d\ %H\:%M\:%S) <<<" >> "/home/deploy/log/$TIMESTAMP.log"

echo ">>> pid 확인" >> "/home/deploy/log/$TIMESTAMP.log"
PID=$(pgrep -f ".output/server/index.mjs")

if [ -z $PID ]
then
   echo ">>> pid 없습니다" >> "/home/deploy/log/$TIMESTAMP.log"
else
   echo ">>> $PID 번 pid 종료" >> "/home/deploy/log/$TIMESTAMP.log"
   kill -9 $PID
fi


nohup node /home/deploy/action/.output/server/index.mjs 1>> /home/deploy/log/$TIMESTAMP.log 2>&1 &

echo ">>> 프론트 배포 $(date +%Y-%m-%d\ %H\:%M\:%S) <<<" >> "/home/deploy/log/$TIMESTAMP.log"

If you plan to use pm2, you can use the pm2 command. No particular reason but I didn't use pm2. The above script is described as follows.

1. Go to the folder you want to work with.

2. Create timestamp

3. Verify running pid

4. Exit if pid is present

5. Run applications using nohup

Lovefield

Web Front-End developer

하고싶은게 많고, 나만의 서비스를 만들고 싶은 변태스러운 개발자입니다.