HomeHow-ToHow to Build a GitHub CI/CD Pipelines: A Step-by-Step Guide

How to Build a GitHub CI/CD Pipelines: A Step-by-Step Guide [With Real Examples]

GitHub Actions came out in 2019, and it made it easier to add CI/CD directly to workflows from your repositories. Since then, GitHub CI/CD pipelines have changed the way developers create, test, and deploy apps. You may find pre-made workflows for practically any development need in the GitHub Marketplace, which has more than 11,000 activities. With Continuous Integration, many developers can combine code changes into a central repository several times a day. With Continuous Delivery, these changes are built, tested, and pushed to staging environments in a set order.

I remember when it took a lot of different tools and complicated setups to set up CI/CD pipelines. GitHub Actions now lets you build strong pipelines right in your GitHub repositories. This integration not only makes the development process easier, but it also speeds up delivery, makes the code better, and makes things more efficient.

The best part? GitHub Actions works with any language, platform, or cloud. These automated methods also make feedback cycles shorter, which helps find problems early and makes the code better. You can even see how each stage is doing with a visual depiction of your pipeline.

In this article, I’ll show you how to make your own GitHub CI/CD pipeline step by step, using examples that you can use right now. Let’s get going!

Why you should use GitHub Actions for CI/CD

GitHub Actions is a powerful way to set up CI/CD workflows right in your GitHub repositories. GitHub Actions is a great alternative for developers who want to make their development processes more efficient because it doesn’t need separate tools and configurations like traditional CI/CD systems do.

Simplified setup and native GitHub integration

The ease with which you may set up GitHub Actions is one of its best features. You don’t require specific skills or resources to make good CI/CD pipelines. You just add workflow files to your repository, and GitHub takes care of the rest. You don’t have to set up webhooks, buy hardware, keep servers running, or manage idle machines with this native integration.

Also, GitHub Actions is fully integrated into the GitHub ecosystem, so your workflows can respond to almost any GitHub event. You may set up your CI/CD pipelines to run automatically when code is pushed, pull requests are made, issues are filed, or even when comments are added. This smooth connection makes it possible for your code, version control, and CI/CD processes to all work together in one place.

You may set up GitHub Actions to run tests automatically every time a pull request is opened. This makes sure that your code is fully tested before it is merged. GitHub can also look at your repository and suggest the best CI workflows for the language and framework you’re using.

Reusable workflows from the GitHub Marketplace

One of the best things about GitHub Actions is that you can use thousands of pre-made workflows and actions. There are more than 11,000 actions accessible on the GitHub Marketplace right now. You may use them right away in your pipelines without having to write them from scratch.

These routines that you may use again and again save down on a lot of unnecessary labor in your development process. You don’t have to copy and paste workflow settings from one repository to another. Instead, you may make a workflow once and use it wherever you need it. For instance, if you have a lot of Node.js apps that all build the same manner, you may make one reusable workflow instead of copying configuration files over and over again.

This method is based on the DRY (Don’t Repeat Yourself) concept and encourages projects to be more uniform. Additionally, procedures that can be reused can be nested up to four levels deep, which makes it possible to create complex automation patterns. Many companies keep these processes in a central place where code owners have to approve modifications. This makes sure that the workflows stay the same and of high quality throughout time.

Support for any language, platform, or cloud

GitHub Actions is also quite flexible, which is another great thing about it. GitHub Actions probably works with your technological stack, no matter what it is. This method works with any platform, language, or cloud, so you can use it to develop CI/CD pipelines for almost any project.

GitHub Actions works with many programming languages, such as Node.js, Python, Java, Ruby, PHP, Go, Rust, and .NET. You don’t have to change your CI/CD platform to build, test, and deploy apps in any language your team wants.

GitHub also has hosted runners for Linux, macOS, Windows, ARM, GPU, and containers, which makes it easier to create and test your applications in diverse settings. You can build up self-hosted runners on your own virtual machines, either in the cloud or on-premises, if you want to use your own infrastructure.

GitHub Actions also lets you do matrix builds, which let you test your code on more than one operating system and runtime version at the same time. This ability to run things in parallel makes your workflow more faster and makes sure that everything works in all circumstances.

Step 1: Set Up Your GitHub Repository

Creating a repository is the first step in making any GitHub CI/CD process. This first step sets up the space where your code and routines will live together, making it easy for development and automation to operate together.

Create or choose an existing repository

To begin building your CI/CD pipeline, you’ll need a GitHub repository that houses your project code. You have two options: create a new repository or use an existing one.

For a new repository:

  1. Navigate to GitHub and click the “+” icon in the top-right corner, then select “New repository”
  2. Name your repository something descriptive and relevant to your project
  3. Add an optional description to help others understand your project’s purpose
  4. Choose your repository visibility – public repositories can use GitHub-hosted runners for free, whereas private repositories consume Actions minutes
  5. Initialize with a README if starting from scratch, or skip this if you’ll push existing code

You might wish to use a template repository if you’re working on a practice project. Templates give you projects that are already set up and ready to go, so you can copy and change them, which saves a lot of time.

Push your project code to GitHub

After you create your repository, you’ll need to put your code in it. If you’re working on a local project that already exists, take these steps to upload it to GitHub:

  1. Initialize Git in your project directory (if not already done):git init
  2. Add all files to the staging area:git add -A
  3. Commit your files with a descriptive message:git commit -m 'Initial project commit'
  4. Connect your local repository to the remote GitHub repository:git remote add origin git@github.com:username/repository-name.git (Replace “username” and “repository-name” with your actual GitHub username and repository name)
  5. Push your code to GitHub:git push -u origin main

These commands establish the connection between your local project and GitHub, essentially preparing the groundwork for your CI/CD pipeline.

Add a .github/workflows directory

GitHub Actions workflows must be stored in a specific location to be discovered and executed. Therefore, creating the proper directory structure is crucial:

  1. In your repository, create a directory named .github at the root level
  2. Inside the .github directory, create another directory named workflows

You can create this structure directly through GitHub’s web interface:

  • Navigate to your repository on GitHub
  • Click “Add file” then “Create new file”
  • Name the file .github/workflows/your-workflow-name.yml (GitHub will automatically create the directories)

Alternatively, create these directories locally and push them with your next commit:

mkdir -p .github/workflows

This is the location where all of your workflow files will be stored: .github/workflows. GitHub automatically searches this directory for YAML files (.yml or .yaml) to find and run workflows. Each workflow file is a separate automated process that can develop, test, or deploy your code.

We’ll talk about how to make your first workflow file with the right YAML structure to make a working CI/CD pipeline in the next part.

Step 2: Create Your First GitHub Actions Workflow

Diagram illustrating a GitHub Actions CI/CD pipeline with build, test, and deploy jobs running on virtual machines triggered by code pushes.

Image Source: VLink Inc.

The most important part of establishing a GitHub CI/CD pipeline is making workflow files. Now that your repository structure is set up, let’s write the configuration that will make your automation work.

Understand the YAML structure

YAML (Yet Another Markup Language) is the language used to write GitHub Actions processes. It uses indentation to show structure. The .github/workflows directory we made earlier is where all workflow files must be kept. They must have either a .yml or .yaml extension.

A basic workflow file consists of several key components:

  1. Name – An optional identifier for your workflow that appears in the GitHub Actions tab
  2. Run-name – The name that appears for each workflow run (can include variables)
  3. On – Specifies what events trigger the workflow
  4. Jobs – Defines what tasks the workflow will execute

Here’s a simple example of a complete workflow structure:

name: Build and Test
run-name: ${{ github.actor }} is running tests
on: [push, pull_request]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup environment
        uses: actions/setup-node@v4
        with:
          node-version: '14'
      - run: npm install
      - run: npm test

Define triggers for push or pull requests

The on field is crucial as it determines when your workflow executes. You can specify a single event or multiple events that will trigger your workflow.

For a basic push trigger that runs on any branch:

on: push

To trigger on multiple events:

on: [push, fork]

You can further refine triggers with filters. For example, to run a workflow only when pushing to specific branches:

on:
  push:
    branches:
      - main
      - 'releases/**'

Similarly, you can set up pull request triggers with activity types:

on:
  pull_request:
    types: [opened, reopened]

Path filters are especially useful to run workflows only when specific files change:

on:
  push:
    paths:
      - '**.js'

Add build and test jobs

Jobs define the actual work your workflow performs. Each job runs in a fresh instance of a virtual environment called a runner.

First, specify which operating system your job should run on:

jobs:
  build:
    runs-on: ubuntu-latest

Subsequently, add steps that define what actions to perform:

steps:
  - name: Checkout code
    uses: actions/checkout@v4
  - name: Setup Node
    uses: actions/setup-node@v4
    with:
      node-version: '14'
  - name: Install dependencies
    run: npm install
  - name: Run tests
    run: npm test

GitHub has pre-made processes for several popular programming languages and frameworks. You can definitely make continuous integration procedures for Python, Java, Node.js, .NET, Ruby, and a lot of other languages.

The needs keyword lets you make jobs depend on other jobs. This lets you construct complicated pipelines where some jobs have to finish before others can start.

Step 3: Trigger and Monitor Your CI/CD Pipeline

The next stage is to put your CI/CD pipeline to work and learn how to keep an eye on it after you’ve built up your process file. This step turns your setup into a process that runs, compiles, tests, and maybe even deploys your code.

Make a code change to trigger the workflow

Once your workflow file is set up, every event that matches your trigger settings will start the pipeline on its own. Making a modification to your codebase and submitting it to GitHub is the easiest approach to test this.

If you’re working on a website project, for example, you might change the wording in your main content file:

<!-- Change this: -->
<h1>The path to your next Open Source contribution.</h1>

<!-- To this: -->
<h1>The path to your next Open Source contribution and more pizza.</h1>

After committing and pushing this change, GitHub Actions will detect the push event and automatically start running your workflow based on the triggers you configured.

Use the workflow visualizer to track progress

GitHub provides a powerful visualization tool that gives you a real-time graphical representation of your workflow execution. To access it:

  1. Navigate to your repository on GitHub
  2. Click the “Actions” tab
  3. Select your workflow from the sidebar
  4. Choose the specific workflow run you want to monitor

The visualization graph displays each job as a node with color-coded status indicators – green checkmarks for successful steps, yellow indicators for in-progress tasks, and red marks for failures. This color-coding system allows you to quickly identify bottlenecks or failures at a glance.

Check live logs for debugging

When issues inevitably arise, live logs become your most valuable troubleshooting resource. To access them:

  1. From the workflow run page, click on the specific job you want to investigate
  2. Expand any failed steps to see detailed error messages
  3. Use the search function to find specific errors in larger logs

For more detailed debugging, you can enable additional debug logging by setting the ACTIONS_RUNNER_DEBUG secret to true in your repository settings. This provides extra information about how the runner executes your job.

GitHub also offers runner diagnostic logs that include valuable information about the execution environment. These can be downloaded as part of the log archive after a workflow completes.

Step 4: Deploy Your Application Automatically

The final stage in our CI/CD journey involves configuring automated deployments that push your application to production whenever your code passes all tests. This critical step completes the continuous delivery cycle, ensuring your changes reach users quickly and reliably.

Add deployment steps to your workflow

To deploy your application automatically, first ensure your deployment job only runs after previous jobs succeed by using the needs keyword:

deploy:
  needs: test
  runs-on: ubuntu-latest

Next, define appropriate permissions for your deployment. This step is crucial because deployments often require write access to repository contents:

permissions:
  contents: write
  pages: write
  id-token: write

Finally, specify your deployment environment and steps:

environment:
  name: production
  url: ${{ steps.deployment.outputs.page_url }}
steps:
  - name: Checkout repository
    uses: actions/checkout@v3
  - name: Setup environment
    uses: actions/setup-node@v3
    with:
      node-version: '18.x'
  - run: npm install
  - run: npm run build

Use GitHub Pages or third-party services like Vercel

GitHub Pages offers an effortless way to deploy static sites directly from your repository. To use it, navigate to your repository’s Settings tab, select Pages, and choose GitHub Actions as the source.

For GitHub Pages deployment, add these steps to your workflow:

- name: Upload artifacts
  uses: actions/upload-pages-artifact@v1
  with:
    path: "./out"
- name: Deploy to Pages
  id: deployment
  uses: actions/deploy-pages@v1

Alternatively, for more advanced applications, Vercel integration provides enhanced deployment capabilities. Configure Vercel by installing its CLI and adding appropriate steps to your workflow:

- name: Deploy to Vercel
  env:
    VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
  run: npx vercel --prod --token $VERCEL_TOKEN

Secure your secrets using GitHub Secrets

Securing sensitive information is paramount when automating deployments. Store API keys, access tokens, and credentials in GitHub Secrets, which encrypts them before they reach GitHub servers.

To add a secret:

  1. Navigate to your repository’s Settings
  2. Select Secrets and variables → Actions
  3. Click “New repository secret”
  4. Name your secret (e.g., VERCEL_TOKEN) and add its value

Reference secrets in your workflow using the syntax ${{ secrets.SECRET_NAME }}. Remember that secrets are automatically redacted from logs if accidentally printed, adding an extra layer of protection.

Be cautious with structured data as secrets, as redaction might fail if the exact match isn’t found. Instead, register individual values as separate secrets for better security.

Conclusion

GitHub CI/CD pipelines have fundamentally transformed the development landscape since their introduction in 2019. Throughout this guide, we’ve walked through the complete process of building a robust CI/CD pipeline directly within your GitHub repository.

The journey started with setting up a proper repository structure, followed by creating YAML workflow files that define your automation. We then explored how these workflows execute based on triggers like code pushes or pull requests. Finally, we examined deployment strategies that complete the delivery cycle.

What makes GitHub Actions particularly powerful? First and foremost, its native integration with GitHub eliminates the need for external tools or complex configurations. Additionally, access to over 11,000 pre-built actions from the Marketplace saves countless hours of development time. The platform-agnostic nature of GitHub Actions ensures compatibility with virtually any language, platform, or cloud service.

Remember that effective CI/CD pipelines deliver several key benefits. Automated testing catches bugs earlier in the development cycle. Consistent builds reduce “it works on my machine” problems. Streamlined deployments get your features to users faster and more reliably.

You now possess everything needed to implement CI/CD practices in your own projects. Start small with basic workflows, then gradually expand as your confidence grows. The visual workflow editor will help you track progress and diagnose issues when they arise.

GitHub Actions has certainly simplified what was once a complex, time-consuming process. Take advantage of this powerful tool to improve your code quality, increase development speed, and deliver more reliable applications. Happy coding!

RELATED ARTICLES

Most Popular