Mastering GitHub Actions: Setting Up Workflows & Self-Hosted Runners for CI/CD

Jasai HansdaJasai Hansda
8 min read

GitHub Actions is a powerful automation tool that helps developers streamline their workflows for building, testing, and deploying applications. Whether you want to automate testing or set up a full CI/CD pipeline, GitHub Actions provides the flexibility to achieve this efficiently.

In this blog, we'll cover:

  • What GitHub Actions are and why they are useful.

  • What runners are and how they work.

  • The difference between GitHub-hosted runners and self-hosted runners.

  • How to set up a self-hosted runner on your own machine or server.

  • How to write a GitHub Actions workflow to build and run a Docker container.

  • Step-by-step implementation and explanation of each process.

Understanding GitHub Actions

What is GitHub Actions?

GitHub Actions is a comprehensive CI/CD (Continuous Integration/Continuous Deployment) tool provided by GitHub. It enables developers to automate a wide range of processes, enhancing efficiency and reliability in software development.

It helps you automate processes like:

  • Running tests when code changes.

  • Building applications before deployment.

  • Deploying applications automatically when changes are pushed.

  • Running scheduled tasks.

GitHub Actions operates using workflows, which are essentially sets of instructions that define the automation steps to be executed. These workflows are triggered by specific events such as code commits, pull requests, or even manual actions initiated by users. By using workflows, developers can create a seamless and automated pipeline that handles everything from testing to deployment, ensuring a smooth and efficient development process.

Key Features of GitHub Actions

  • Event-Driven Workflows: GitHub Actions can be triggered by a variety of events, including pushes, pull requests, and scheduled times, allowing for flexible automation.

  • Integration with GitHub Ecosystem: Seamlessly integrates with GitHub repositories, making it easy to automate tasks directly related to your codebase.

  • Marketplace for Actions: Access to a wide range of pre-built actions in the GitHub Marketplace, which can be used to extend and customize workflows.

  • Matrix Builds: Supports running jobs in parallel across multiple configurations, such as different operating systems or versions of a language, to ensure compatibility.

Benefits of Using GitHub Actions

  • Efficiency: Automates repetitive tasks, reducing manual effort and speeding up the development process.

  • Consistency: Ensures that processes like testing and deployment are performed consistently every time code changes are made.

  • Scalability: Easily scales with your project, allowing you to add more workflows and actions as your needs grow.

  • Collaboration: Facilitates collaboration among team members by providing a clear and automated process for integrating and deploying code changes.

Common Use Cases

  • Continuous Integration: Automatically run tests and build applications whenever code is pushed to the repository.

  • Continuous Deployment: Deploy applications to production or staging environments automatically after successful builds.

  • Scheduled Tasks: Run maintenance scripts or other tasks at scheduled intervals without manual intervention.

  • Custom Automation: Create custom workflows to automate any process that can be scripted, from checking code quality to complex deployment plans.

GitHub Actions Documentation

For more detailed information and guidance on setting up and using GitHub Actions, you can refer to the GitHub Actions Documentation. This resource provides comprehensive instructions, examples, and best practices to help you effectively utilize GitHub Actions in your projects.

GitHub Actions on GitHub

Explore the GitHub Actions repository to discover a variety of pre-built actions that you can incorporate into your workflows. This repository contains official actions maintained by GitHub, which can be used to automate tasks such as setting up environments, running tests, and deploying applications.


Understanding Runners in GitHub Actions

What is a Runner?

A runner is a machine that executes GitHub Actions workflows. Runners are machines that run your application. It can be a virtual machine, a container, or even your own computer. Runners are responsible for running the jobs defined in your workflows, and they can be customized to suit the needs of your project.

Types of Runners:

1. GitHub-Hosted Runners (Default)

  • Provided and managed by GitHub: These runners are automatically managed by GitHub, which means you don't have to worry about maintenance or updates.

  • Pre-installed software: They come with a wide range of pre-installed software, including different operating systems like Linux, Windows, and macOS.

  • Scalable but no static IP: While they can scale to meet demand, they do not have a fixed public IP address, which can be a limitation for certain deployment scenarios.

💡 Best for: Running automated tests, packaging applications, and builds that don’t need a fixed server.

2. Self-Hosted Runners (Custom)

  • User-managed: You set up and manage the machine that runs your workflows, giving you more control over the environment.

  • Persistent environments: They provide persistent environments and access to external networks, which can be beneficial for certain tasks.

  • Custom software: You can install any software you need, which is useful for specialized builds or deployments.

💡 Best for: Deployments where you need a static IP address or require custom software. Ideal for running on your own server or VPS for deployments and long-running processes.

3. Enterprise Runners

  • Designed for large organizations: These runners are tailored for enterprise environments, providing enhanced security, compliance, and scalability features.

  • Centralized management: They offer centralized management capabilities, making it easier to oversee and control multiple runners across an organization.

  • Integration with enterprise tools: They can integrate with existing enterprise tools and infrastructure, providing a seamless workflow experience.

💡 Best for: Large organizations that require robust security, compliance, and management features for their CI/CD pipelines.


Setting Up a Self-Hosted Runner in GitHub Actions

In this section, we’ll configure a self-hosted runner to execute workflows on our own machine.

Step 1: Register a Self-Hosted Runner

  1. Go to your GitHub repository

    • Navigate to SettingsActionsRunners

    • Click "New self-hosted runner"

  2. Choose an Operating System

    • Select the appropriate OS for your server (Linux, macOS, or Windows).
  3. Follow the Instructions Provided by GitHub

    • GitHub will provide setup commands to download and install the runner in your respective machine.

Step 2: Install and Start the Runner (Linux Example)

💻 Run these commands on your Linux machine:

mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/download/v2.308.0/actions-runner-linux-x64-2.308.0.tar.gz
tar xzf ./actions-runner-linux-x64.tar.gz

Configure the runner with GitHub

./config.sh --url https://github.com/YOUR-REPO --token YOUR_TOKEN

Replace YOUR-REPO with your actual repository URL.

Start the runner:

./run.sh

🔄 Keep this terminal open because the runner must be active for workflows to execute.


Creating a GitHub Actions Workflow for CI/CD

Creating a GitHub Actions workflow for CI/CD involves defining a series of automated steps that are triggered by specific events in your repository. Here's an expanded guide on how to create such a workflow:

Create GitHub Actions Workflow on GitHub

  1. Go to your repository
    Open the GitHub repository where you want to add the workflow.

  2. Click on the “Actions” tab
    Located at the top of the repo (beside “Code”, “Issues”, etc.)

  3. Click “New Workflow” or “Set up a workflow yourself”

    • You’ll see suggested templates (Node.js, Python, Docker, etc.)

    • Or scroll down and click “set up a workflow yourself”.

  4. Edit the Workflow YAML
    You'll be taken to a file editor with a default template like:

     name: CI/CD Pipeline
    
     on:
       push:
         branches:
           - main
       pull_request:
         branches:
           - main
       workflow_dispatch:  # Allows manual triggering
    
     jobs:
       build-and-deploy:
         runs-on: self-hosted  # Runs on the self-hosted runner
    
         env:
           IMAGE_NAME: my-docker-app
           CONTAINER_NAME: MyApp
    
         steps:
           - name: Checkout Repository
             uses: actions/checkout@v3
    
           - name: Install Dependencies
             run: | 
               python3 -m pip install --no-cache-dir -r requirements.txt
    
           - name: Run Unit Tests
             run: |
               python3 -m unittest discover -s tests
    
           - name: Build Docker Image
             run: |
               docker build -t $IMAGE_NAME .
    
           - name: Stop and Remove Existing Container (if exists)
             run: |
               docker ps -q --filter "name=$CONTAINER_NAME" | grep -q . && docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME || echo "No existing container."
    
           - name: Run Docker Container
             run: |
               docker run -d -p 80:80 --name $CONTAINER_NAME --restart always $IMAGE_NAME
    
  5. Name the file (optional)
    Top-left you'll see something like:
    .github/workflows/blank.yml
    You can rename it to ci.yml, devops.yml, deploy.yml, etc.

  6. Click “Start commit”

    • Write a commit message.

    • Choose “Commit directly to the main branch”.

    • Click the Commit new file button.

Done! You’ve now created your workflow directly from GitHub UI. It’ll start running if your trigger condition (on: push, etc.) matches.


How This Workflow Works

1. Triggers the Workflow

  • Runs when code is pushed to the main branch.

  • Also runs for pull requests and manual dispatch.

2. Checks Out the Code

  • Pulls the latest repository code into the runner.

3. Installs Dependencies

  • Installs Python dependencies from requirements.txt.

4. Runs Unit Tests

  • Uses Python’s built-in unittest framework to test the application.

5. Builds a Docker Image

  • Creates a Docker container from the latest code.

6. Stops and Removes Old Containers

  • If a previous container exists, it is stopped and deleted.

7. Runs the New Container

  • Starts the latest Docker container, mapping port 80.

Running and Testing the Workflow

  1. Push Changes to GitHub

     git add .
     git commit -m "Added CI/CD workflow"
     git push origin main
    
  2. Monitor Workflow Execution

    • Go to GitHub RepositoryActions

    • Select the latest workflow run to view logs.

  3. Verify Deployment

    • If using a cloud server, visit http://your-server-ip/ to check if your app is running.

    • If running locally, test using:

        docker ps -a  # Check running containers
        docker logs MyApp  # View application logs
      

Why Use Self-Hosted Runners for Deployment?

FeatureGitHub-Hosted RunnerSelf-Hosted Runner
Free UsageLimited free minutesNo restrictions
Custom SoftwareNo (pre-installed only)Yes (full control)
Public IPNoYes
DeploymentNot idealBest for deploying apps
SpeedSlower (cold start)Faster (persistent machine)

Use self-hosted runners for:

  • Deploying applications with a public IP.

  • Running workflows on private servers.

  • Persistent environments for fast execution.


Conclusion

Mastering GitHub Actions and setting up workflows with self-hosted runners can greatly enhance your CI/CD processes. Automating tasks like testing, building, and deploying applications improves efficiency and collaboration. Self-hosted runners offer more control, making them ideal for deployments needing a static IP or specialized environments. With the provided knowledge and steps, you're ready to implement a robust CI/CD pipeline for seamless automation. Embrace these tools to streamline your development workflow.

0
Subscribe to my newsletter

Read articles from Jasai Hansda directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jasai Hansda
Jasai Hansda

Software Engineer (2 years) | In-transition to DevOps. Passionate about building and deploying software efficiently. Eager to leverage my development background in the DevOps and cloud computing world. Open to new opportunities!