Post

Setting Up a CI/CD Pipeline with GitHub Actions Self-Hosted Runner for Node.js Servers

Learn how to establish a robust CI/CD pipeline using GitHub Actions and a self-hosted runner to enhance your Node.js application's development and deployment process.

In the fast-paced world of modern software development, Continuous Integration and Continuous Deployment (CI/CD) practices have become essential for maintaining high-quality, reliable applications. For Node.js developers, implementing a robust CI/CD pipeline can significantly streamline the development process, catch bugs early, and ensure smooth deployments.

This blog post will guide you through setting up a CI/CD pipeline using GitHub Actions with a self-hosted runner, specifically tailored for Node.js applications. By the end, you’ll have a powerful, customizable pipeline that can automatically test, build, and deploy your Node.js projects.

2. Prerequisites

Before we dive into the setup, make sure you have the following:

  • Basic understanding of Node.js and npm
  • A GitHub account with a repository for your Node.js project
  • A server or machine to host your self-hosted runner (this could be a cloud instance, a local server, or even a Raspberry Pi)
  • SSH access to your server
  • Administrative access to your GitHub repository

3. Setting Up the Self-Hosted Runner

GitHub Actions runners are the agents that execute your CI/CD workflows. While GitHub provides hosted runners, using a self-hosted runner gives you more control over the environment and can be more cost-effective for larger projects.

Step 1: Prepare Your Server

  1. SSH into your server
  2. Ensure you have a non-root user with sudo privileges
  3. Update your system:
    1
    
    sudo apt update && sudo apt upgrade -y
    

Step 2: Download and Configure the GitHub Actions Runner

  1. In your GitHub repository, go to Settings > Actions > Runners
  2. Click on “New self-hosted runner”
  3. Select your operating system and architecture
  4. Follow the provided instructions to download and configure the runner. It will look something like this:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # Create a folder
    mkdir actions-runner && cd actions-runner
    
    # Download the latest runner package
    curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
    
    # Extract the installer
    tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz
    

Step 3: Configure and Start the Runner

  1. Run the configuration script:
    1
    
    ./config.sh --url https://github.com/YOUR_USERNAME/YOUR_REPO --token YOUR_TOKEN
    
  2. Follow the prompts to name your runner and add any labels
  3. Start the runner:
    1
    
    ./run.sh
    

Congratulations! Your self-hosted runner is now registered and connected to your GitHub repository.

4. Configuring the GitHub Actions Workflow

Now that our runner is set up, let’s create a workflow to automate our Node.js CI/CD process.

Step 1: Create the Workflow File

  1. In your repository, create a .github/workflows directory
  2. Inside this directory, create a file named nodejs.yml

Step 2: Define the Workflow

Here’s a sample workflow for a Node.js application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
name: Node.js CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: self-hosted

    strategy:
      matrix:
        node-version: [14.x, 16.x, 18.x]

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js $
      uses: actions/setup-node@v3
      with:
        node-version: $
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

This workflow does the following:

  • Triggers on pushes and pull requests to the main branch
  • Runs on our self-hosted runner
  • Tests against multiple Node.js versions
  • Checks out the code, installs dependencies, builds the project, and runs tests

5. Deploying with GitHub Actions

To add deployment to our workflow, we’ll need to modify our nodejs.yml file. Here’s an example that includes a deployment step:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
name: Node.js CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: self-hosted
    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18.x'
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

  deploy:
    needs: build
    runs-on: self-hosted
    if: github.ref == 'refs/heads/main'
    steps:
    - name: Deploy to production
      env:
        DEPLOY_KEY: $
      run: |
        echo "$DEPLOY_KEY" > deploy_key
        chmod 600 deploy_key
        ssh -i deploy_key user@your-server.com "cd /path/to/your/app && git pull origin main && npm install && pm2 restart your-app"

This workflow adds a deploy job that runs after the build job succeeds. It uses an SSH key stored in GitHub Secrets to securely connect to your production server and update the application.

To set up secrets:

  1. Go to your repository settings
  2. Navigate to Secrets and Variables > Actions
  3. Click “New repository secret”
  4. Add your DEPLOY_KEY and any other necessary secrets

6. Monitoring and Maintenance

To keep your CI/CD pipeline running smoothly:

  1. Regularly update your self-hosted runner:
    1
    2
    
    cd actions-runner
    ./config.sh --check
    
  2. Monitor your workflows in the GitHub Actions tab of your repository

  3. Set up notifications for failed workflows

  4. Periodically review and update your workflow files to ensure they align with your project’s evolving needs

  5. Keep your Node.js versions up to date in your workflow file

  6. Regularly audit and rotate any secrets used in your workflows

7. Conclusion

Setting up a CI/CD pipeline with GitHub Actions and a self-hosted runner for your Node.js applications can greatly improve your development workflow. It automates testing and deployment, ensures consistency across different environments, and helps catch issues early in the development process.

By following this guide, you’ve created a powerful, customizable pipeline that can grow with your project. Remember, CI/CD is an iterative process – continually refine your workflows to best suit your team’s needs.

We’d love to hear about your experiences setting up CI/CD for Node.js! Leave a comment below or reach out with any questions or suggestions.

8. Further Resources

Happy coding, and may your deployments be ever smooth!

This post is licensed under CC BY 4.0 by the author.