Skip to content

How to Set Up CI/CD in GitHub Actions

Key idea:

GitHub Actions — built-in CI/CD in GitHub (free 2000 min/month for private repos, unlimited for public). Workflow = YAML file in .github/workflows/. Triggers: push, pull_request, schedule (cron), manual. Runners: ubuntu-latest, macos-latest, windows-latest. Deploy via SSH + rsync, docker push, Vercel/Netlify integrations. Secrets stored in repo settings.

Below: step-by-step, working examples, common pitfalls, FAQ.

Check your site →

Step-by-Step Setup

  1. Create .github/workflows/ci.yml
  2. Define trigger: on: push: branches: [main]
  3. Define jobs with runs-on + steps (checkout, setup-node, npm install, test)
  4. For deploy: secrets (SSH_KEY, DEPLOY_HOST) in repo Settings → Secrets
  5. Deploy step: appleboy/ssh-action or rsync + SSH
  6. Commit + push — workflow runs automatically
  7. Results: Actions tab in GitHub, logs per step, artifacts

Working Examples

ScenarioConfig
Simple Node.js CIname: CI on: push: { branches: [main] } pull_request: jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20' } - run: npm ci - run: npm test
Deploy via SSHdeploy: needs: test runs-on: ubuntu-latest steps: - uses: appleboy/ssh-action@v1 with: host: ${{ secrets.DEPLOY_HOST }} username: deploy key: ${{ secrets.SSH_PRIVATE_KEY }} script: cd /var/www && git pull && npm install --production && pm2 reload all
Matrix build (multi Node version)strategy: matrix: node: [18, 20, 22] steps: - uses: actions/setup-node@v4 with: { node-version: ${{ matrix.node }} }
Docker build + push- uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
Scheduled workflow (cron)on: schedule: - cron: '0 2 * * *' # daily at 2 AM UTC

Common Pitfalls

  • Secrets printed in logs — use ::add-mask:: or sensitive steps with if: env check
  • Free tier — 2000 min for private repos. Build 10 min × 200 runs = limit
  • Cache matters: actions/cache@v4 with proper key — otherwise npm install each time 1 min
  • Ubuntu runners get upgraded — pin specific version (ubuntu-22.04, not ubuntu-latest for prod)
  • Deploy step runs on every push — add if: github.ref == 'refs/heads/main'

TL;DR: Setting Up CI/CD in GitHub Actions

To set up Continuous Integration and Continuous Deployment (CI/CD) in GitHub Actions, create a workflow file in your repository's .github/workflows directory. Define jobs and steps using the YAML syntax, specifying triggers like push or pull_request. Use actions for tasks like building, testing, and deploying your application. For example, use actions/checkout@v2 to check out your code and actions/setup-node@v2 for Node.js applications.

Understanding GitHub Actions Workflow Structure

GitHub Actions provides a powerful automation framework that integrates seamlessly with GitHub repositories. To harness its full potential, you need to understand the fundamental components of a workflow.

Workflow Basics

A workflow is defined in a YAML file located in the .github/workflows directory of your repository. Each workflow can contain multiple jobs, which run in parallel or sequentially. Each job consists of a series of steps that specify the actions to be taken. The basic structure of a workflow file is as follows:

name: CI/CD Workflow

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '14'
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test

In this example, the workflow is triggered on every push to the main branch. It checks out the code, sets up Node.js version 14, installs dependencies, and runs tests.

Triggers

Triggers are the events that initiate the workflow. Common triggers include:

  • push: Triggers when code is pushed to the repository.
  • pull_request: Triggers when a pull request is created or updated.
  • schedule: Triggers workflows at specified intervals, using cron syntax.
  • workflow_dispatch: Allows manual triggering of workflows.

For example, to trigger a workflow every day at 2 AM UTC, you can add the following to your workflow:

on:
  schedule:
    - cron: '0 2 * * *'

Jobs and Steps

Jobs are defined within the jobs key and can run on different operating systems. Each job consists of a series of steps, which can either be actions or shell commands. Here's how you can define multiple jobs:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Build
        run: npm run build

  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to Production
        run: ./deploy.sh

The needs keyword specifies that the deploy job should only run after the build job completes successfully.

Using Actions

GitHub Actions offers a marketplace where you can find pre-built actions to streamline your workflows. Common actions include:

  • actions/checkout: Checks out your repository code.
  • actions/setup-node: Sets up a Node.js environment.
  • docker/build-push-action: Builds and pushes Docker images.

To use an action, simply reference it in your steps. For instance:

- name: Build Docker Image
  uses: docker/build-push-action@v2
  with:
    context: .
    push: true
    tags: user/app:latest

Example: A Complete CI/CD Workflow

Here’s a complete example of a CI/CD workflow for a Node.js application that includes testing and deployment:

name: CI/CD Workflow

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '14'
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test

  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to Production
        run: ./deploy.sh

This workflow checks out the code, installs dependencies, runs tests, and then deploys the application to production if all previous steps are successful. Ensure your deploy.sh script includes all necessary commands for deployment, and consider adding error handling for robustness.

Conclusion

Setting up CI/CD in GitHub Actions enhances your development workflow by automating testing and deployment processes. By leveraging the flexibility of YAML configurations, you can create sophisticated workflows that improve code quality and speed up delivery times.

Learn more

Frequently Asked Questions

Is free tier enough?

For solo project — yes. Team 5+ — sometimes need Teams $4/user/mo or self-hosted runners.

Why self-hosted runners?

For private network access, unlimited minutes, GPU/ARM runners. Downside — maintenance + security (compromised runner = RCE in workflow).

Secrets vs env vars?

Secrets — encrypted, not visible in logs. Env vars — plain, visible. For tokens/passwords — always secrets.

GitHub Actions vs Jenkins/GitLab CI?

GitHub Actions: free for GH repos, huge actions marketplace, YAML. Jenkins: self-host, flexible but maintenance. GitLab CI: tight GitLab integration. For GitHub — Actions default.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.