Setting Up CI/CD for Node.js with GitHub Actions

Basanta Sapkota - Nov 6 - - Dev Community

Setting up CI/CD for your Node.js app using GitHub Actions can save time and reduce errors by automating repetitive deployment tasks. In this guide, you’ll learn to configure a workflow that pulls code, installs dependencies, manages SSH securely, and deploys with PM2.

What You’ll Need

  • GitHub Repository: For hosting your Node.js code.
  • VPS: A server with SSH access to deploy your app.
  • Secrets Setup: Add credentials (SSH key, IP, user, and environment variables) in GitHub Secrets for secure access.

GitHub Actions Workflow

Here’s a full YAML configuration with each step explained:

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # 1. Checkout Code
      - name: Checkout code
        uses: actions/checkout@v3

      # 2. Set Up Node.js
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      # 3. Install Dependencies
      - name: Install dependencies
        run: npm ci

      # 4. Set Up SSH for Deployment
      - name: Set up SSH key
        uses: webfactory/ssh-agent@v0.8.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      # 5. Add VPS to Known Hosts
      - name: Add VPS to known hosts
        run: |
          mkdir -p ~/.ssh
          ssh-keyscan -H "${{ secrets.VPS_IP }}" >> ~/.ssh/known_hosts

      # 6. Deploy Files to VPS
      - name: Deploy to temporary directory on VPS
        env:
          VPS_USER: ${{ secrets.VPS_USER }}
        run: |
          rsync -avz --delete ./ ${VPS_USER}@${{ secrets.VPS_IP }}:/tmp/node-hello/

      # 7. Move Files to Final Directory on VPS
      - name: Move files to /root/node-hello
        env:
          VPS_USER: ${{ secrets.VPS_USER }}
        run: |
          ssh ${VPS_USER}@${{ secrets.VPS_IP }} "
            sudo rsync -avz /tmp/node-hello/ /root/node-hello/
          "

      # 8. Set Up Environment and Manage PM2
      - name: Configure environment and manage PM2
        env:
          VPS_USER: ${{ secrets.VPS_USER }}
          MONGO_URI: ${{ secrets.MONGO_URI }}
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
          BCRYPT_SALT_ROUNDS: ${{ secrets.BCRYPT_SALT_ROUNDS }}
          PORT: ${{ secrets.PORT }}
          NODE_ENV: 'production'
        run: |
          ssh ${VPS_USER}@${{ secrets.VPS_IP }} "
            sudo bash -c '
            cd /root/node-hello

            # Write environment variables to .env
            cat > .env <<EOL
            MONGO_URI=${MONGO_URI}
            JWT_SECRET=${JWT_SECRET}
            BCRYPT_SALT_ROUNDS=${BCRYPT_SALT_ROUNDS}
            NODE_ENV=${NODE_ENV}
            PORT=${PORT}
            EOL

            # Check for PM2 and start app
            if ! command -v pm2 &> /dev/null; then
              npm install -g pm2
            fi
            pm2 startOrRestart server.js --name \"server\" --update-env
            '
          "

      # 9. Clean Up Known Hosts
      - name: Clean up known hosts
        run: |
          ssh-keygen -R "${{ secrets.VPS_IP }}"
Enter fullscreen mode Exit fullscreen mode

Workflow Breakdown

  1. Checkout Code: Pulls your latest code from the main branch.
  2. Node.js Setup: Sets up Node.js (version 18 or higher) for compatibility with modern libraries.
  3. Install Dependencies: npm ci is preferred over npm install for faster installs and consistency with package-lock.json.
  4. SSH Key Setup: Uses webfactory/ssh-agent to securely handle SSH. This action adds your SSH key to the agent without saving it locally.
  5. Add VPS to Known Hosts: Adds your server’s IP to the SSH known hosts list, avoiding interactive prompts during SSH.
  6. Deploy Files to VPS: Uses rsync to deploy files to a temporary directory on the VPS, ensuring only the latest files are uploaded.
  7. Move Files to Final Directory: Moves files from the temporary to the final directory, requiring root privileges to write to /root/node-hello.
  8. Set Environment and PM2: Writes environment variables to a .env file on the server, then starts or restarts the app using PM2. The startOrRestart command is efficient and reduces downtime.
  9. Clean Up Known Hosts: Removes the VPS IP from known hosts after deployment. This step prevents clutter and mitigates risks from SSH fingerprint changes.

Warning! This is a beginner setup and may not cover all scenarios. We’re open to suggestions and feedback to improve this guide, so feel free to share any ideas or tips you have.

. . .
Terabox Video Player