Set up a CI/CD pipeline for Node.js with GitHub Actions. Automate tests, linting, Dependabot updates, and deploy via SSH and Docker.
Continuous Integration and Continuous Deployment (CI/CD) are essential for modern development. In this guide, I'll walk you through setting up a full CI/CD pipeline for a Node.js project using GitHub Actions. We will cover automated testing, linting, Dependabot for dependency updates, and deploying to a VPS using SSH and Docker.
Prerequisites
Before we start, ensure you have:
- A Node.js project hosted on GitHub.
- A VPS with SSH access and Docker installed.
- A GitHub Actions workflow directory (
.github/workflows/
). - A GitHub personal access token for Dependabot.
Step 1: Setting Up Dependabot
Dependabot automates dependency updates. Create a .github/dependabot.yml
file:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 5
Commit and push this file to enable automated dependency updates.
Step 2: Defining the CI Workflow
Create a new workflow file at .github/workflows/ci.yml
:
name: CI Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm install
- name: Run linter
run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
This workflow:
- Runs on every push and pull request to
main
. - Checks out the repository.
- Installs dependencies.
- Runs the linter and tests.
Step 3: Adding Deployment Workflow
Create a new workflow file at .github/workflows/deploy.yml
:
name: Deploy to VPS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build -t my-node-app .
- name: Push Docker image
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
docker tag my-node-app mydockerhubuser/my-node-app:latest
docker push mydockerhubuser/my-node-app:latest
- name: Deploy via SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
docker pull mydockerhubuser/my-node-app:latest
docker stop node-app || true
docker rm node-app || true
docker run -d --name node-app -p 3000:3000 mydockerhubuser/my-node-app:latest
This workflow:
- Runs on pushes to
main
. - Builds a Docker image.
- Pushes it to Docker Hub.
- Connects to the VPS via SSH and deploys the container.
Step 4: Storing Secrets in GitHub
For security, store credentials as GitHub Secrets:
DOCKER_USERNAME
– Your Docker Hub username.DOCKER_PASSWORD
– Your Docker Hub password.VPS_HOST
– Your VPS IP or domain.VPS_USER
– Your SSH username.VPS_SSH_KEY
– Your SSH private key.
Go to Settings > Secrets and Variables > Actions in your GitHub repository and add these values.
Conclusion
With this setup, every push to main
triggers automated tests, linting, and deployment to a VPS. Dependabot keeps dependencies updated, ensuring security. This CI/CD pipeline enhances reliability and automates your workflow effectively.