Building a CI/CD Pipeline with GitHub Actions: Node.js Example

Building a CI/CD Pipeline with GitHub Actions: Node.js Example

Manual testing and deployment processes are both slow and error-prone. GitHub Actions is a free CI/CD platform that automatically runs test, build, and deploy steps when code is pushed. This guide builds a complete pipeline for a Node.js application including testing, Docker image building, security

E

Elif Demir

Cloud Solutions Architect

March 21, 202613 min read0

Manual testing and deployment processes are both slow and error-prone. GitHub Actions is a free CI/CD platform that automatically runs test, build, and deploy steps when code is pushed. This guide builds a complete pipeline for a Node.js application including testing, Docker image building, security scanning, and Kubernetes deployment.

GitHub Actions Basics

GitHub Actions are defined by YAML files in the .github/workflows/ directory of your repository. Each workflow contains one or more jobs, and each job consists of steps. Workflows can be triggered by push, pull request, schedule, or manual dispatch.

Concept Description Example
Workflow Automated process definition ci.yml file
Job Work unit running in parallel or sequence test, build, deploy
Step A single command or action within a job npm test, docker build
Action Reusable step package actions/checkout@v4

Test and Lint Pipeline

As a first step, let's create a workflow that automatically runs tests and linting on every push and pull request.

.github/workflows/ci.yml
name: CI Pipeline
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    - run: npm ci
    - run: npm run lint
    - run: npm test -- --coverage
    - uses: actions/upload-artifact@v4
      with:
        name: coverage-${{ matrix.node-version }}
        path: coverage/

Docker Build and Deploy Pipeline

After tests pass, here is the full pipeline that builds a Docker image, pushes it to a registry, and deploys to Kubernetes:

.github/workflows/deploy.yml
name: Build & Deploy
on:
  push:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
    - uses: actions/checkout@v4

    - uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: |
          ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
          ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
        cache-from: type=gha
        cache-to: type=gha,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: azure/k8s-set-context@v4
      with:
        kubeconfig: ${{ secrets.KUBE_CONFIG }}
    - run: |
        kubectl set image deployment/web-app \
          web-app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
          -n production

💡 Tip: cache-from: type=gha uses GitHub Actions cache to significantly reduce Docker build times. After the first build, unchanged layers are served from cache.

Pipeline Security Steps

  • Store Secrets in Repository Settings Store API keys, kubeconfig, and registry credentials in GitHub Secrets. Never write them as plain text in workflow files.
  • Pin Action Versions Use actions/[email protected] or commit SHA instead of actions/checkout@v4. This protects against supply chain attacks.
  • Add Image Security Scanning Scan images with Trivy after build. Stop the pipeline if critical vulnerabilities are found: trivy image --exit-code 1 --severity CRITICAL
  • Apply the Principle of Least Privilege Use the permissions block to grant each job only the permissions it needs. By default, all permissions are open.

For Docker image optimization, check our Multi-Stage Build guide. For container security, see our Container Security guide. For a GitOps approach, explore our ArgoCD guide. The GitHub Actions documentation and Actions Marketplace are valuable additional resources.

Frequently Asked Questions

Is GitHub Actions free?

It is completely free for public repositories. Private repositories get 2,000 free minutes per month on the Free plan. Additional minutes are charged. You can reduce costs to zero by using self-hosted runners.

What is the difference between GitHub Actions and Jenkins?

GitHub Actions is cloud-based and natively integrated with GitHub, requiring no server management. Jenkins is self-hosted, more flexible but requires setup and maintenance. GitHub Actions suits small-to-medium teams, while Jenkins may be better for complex enterprise pipelines.

What does matrix strategy do?

Matrix strategy runs the same job in parallel with different parameters. For example, you can test simultaneously on Node.js 18, 20, and 22. This helps you catch compatibility issues early.

When should I use a self-hosted runner?

Use self-hosted runners when you need special hardware (GPU, ARM), network restrictions (private network access), or cost optimization. For security, run your runners in an isolated environment and update them regularly.

Conclusion

By automating test, build, and deploy processes with GitHub Actions, you can increase development speed and reduce error rates. Use matrix strategy for multi-version testing, Docker cache to shorten build times, security scanning to catch vulnerabilities early, and proper secret management to keep credentials safe.

Powerful Infrastructure for Your CI/CD Pipeline

Deploy your applications fast and securely with Hosted Cloud servers.

Explore Cloud Server Plans →
E

Elif Demir

Cloud Solutions Architect

Specializing in enterprise cloud migration projects and hybrid infrastructure design with 8 years of experience in AWS, Azure, and private cloud environments.

Comments coming soon