Problem
In today’s fast-paced development cycles, the demand to ship high-quality code quickly is more important than ever before. However, several tedious, labor-intensive, and prone to mistakes procedures that stand between producing code and releasing it to consumers frequently slow down teams.
Every Developer faces these common issues:
- Repetitive Checks: Before each push, unit tests, linters, and build scripts are manually executed.
- Inconsistent Environments: Code that passes locally in one environment but fails in another is known as the “it works on my machine” dilemma.
- High-Stakes Deployments: Deploying code by following a meticulous, manual checklist in which even one mistake could result in downtime.
- Slow Comments Loops: The review process is prolonged when you wait for a coworker to pull your branch, run tests, and provide comments on a pull request.
Solution
The introduction of GitHub Actions has closed a major gap and answered most automation questions, which is built directly into the platform where most developers code.
GitHub Actions is a powerful and flexible automation engine that allows you to create custom software development life cycle workflows inside your GitHub repository. It serves as your project’s devoted assistant, handling the tedious duties so your team can concentrate on creating amazing features, which is what they do best.
You can tell GitHub to automatically build, test, package, release, or deploy your code in response to pull requests or new commits by establishing a set of rules. This translates into a more efficient process from beginning to end, quicker feedback, and more dependable deployments.
The Question: Why GitHub Actions
Now, with our understanding of GitHub Actions, which acts as an automation platform that lets you orchestrate workflows based on any event within your repository.
The “why” has to do with effectiveness and reliability. Codifying your development procedures (such as testing and deployment) into a workflow file guarantees that each change is handled consistently.
This enables you to:
- Automate CI/CD: Develop, test, and release your code automatically.
- Organize Your Repository: Assign reviewers, tag issues automatically, and accept new contributors.
- Start Custom Processes: Whenever you produce a new release, publish packages to npm, send Slack notifications, or produce documentation.
The Core Concepts of GitHub Actions
Getting started with GitHub Actions requires a basic understanding of how GitHub/Git and YAML work. The knowledge will help lay the necessary foundation needed. Every workflow is specified in a YAML file found in your repository’s. github/workflows/directory.
Workflow
The automated procedure that you wish to execute. It can have one or more jobs and is described by a single YAML file. Additionally, workflows can be started manually or according to a predetermined schedule.
Event
The triggers that initiate a process. This could be a push, pull_request, schedule, or workflow_dispatch, a manual trigger.
To learn more about GitHub Events, check their official documentation for the different events: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#issues
# .github/workflows/simple-demo.yml
# A name for the workflow
name: Simple Demo Workflow
# The 'on' keyword defines the events that trigger this workflow.
on:
# 1. Triggers on any release activity (e.g., created, published)
release:
# 2. Triggers on specific issue activities
issues:
types: [opened, edited, milestoned]
# 3. Triggers a push to specific branches
push:
branches:
- 'main'
- 'releases/**'
# 4. Triggers when a pull request is opened against a specific branch
pull_request:
types: [opened]
branches:
- 'releases/**'
# The jobs to run for the workflow.
jobs:
simple_job:
# This job will run on a GitHub-hosted Ubuntu runner
runs-on: ubuntu-latest
steps:
- name: A simple step
run: echo "This workflow was triggered by the ${{ github.event_name }} event."
Job
A runner is a series of actions that run on a virtual machine. Jobs operate in parallel by default. A GitHub Action processes one or more jobs; each includes a series of steps that carry out commands or actions.
One job can be configured to rely on another work or jobs. Jobs will operate in parallel if they lack dependencies. When two jobs are interdependent, one will wait for the other to be completed before beginning.
# .github/workflows/simple-jobs-demo.yml
name: Simple Job Dependency Demo
on:
push:
branches:
- main
jobs:
# This job runs first as it has no dependencies.
development:
runs-on: ubuntu-latest
steps:
- name: Run development tasks
run: echo "Setting up development environment..."
# This job depends on the 'development' job.
build:
runs-on: ubuntu-latest
needs: development
steps:
- name: Build the application
run: echo "Building the application..."
# This job depends on both 'build' and 'development' jobs.
# It will only start after both have completed successfully.
testing:
runs-on: ubuntu-latest
needs: [build, development]
steps:
- name: Test the application
run: echo "Running tests..."
Step
A job-related individual task, a step can be a reusable script known as an action or a shell command (such as npm install).
Runner
The server that manages your workflows is called Runner. You can host your own for greater control, but GitHub offers free Linux, Windows, and macOS runners.
Action
You can use this pre-made, repeatable command in your workflow. The GitHub Marketplace offers thousands of actions, or you can make your own.
# .github/workflows/concepts-demo.yml
name: Basic Concepts Demo
on:
push:
branches: [ main ]
jobs:
demo_job:
# 1. Runner: The server that will run your job.
# In this case, it's a GitHub-hosted virtual machine running the latest version of Ubuntu.
runs-on: ubuntu-latest
# A job contains a sequence of tasks called steps.
steps:
# 2. Step 1: Using a pre-built 'Action'.
# This step uses the 'checkout' action to download your repository's code onto the runner.
- name: Check out repository code
uses: actions/checkout@v4 # <- This is the Action
# 3. Step 2: Running a shell command.
# This is another step, but instead of using an action, it runs a simple command-line script.
- name: Say hello
run: echo "Hello, world! This is a simple command-line step." # <- This is a shell command Step
Common Scenarios: “When” and “Where” to Use GitHub Actions
As more developers begin to integrate GitHub Actions into their daily processes, knowing when and where to use such capacity is also highly important.
- Continuous Integration (CI): Create and execute tests automatically each time a pull request is opened or a commit is pushed. This is the most common use case.
- Continuous Deployment (or CD): When tests are successful, automatically move your code to a production or staging environment (such as your server, Heroku, AWS, or Azure).
- Publishing Packages: Every time you make a new release, your library or package will be automatically published to a registry, such as npm, PyPI, or Docker Hub.
- Issue and PR Triage: Assign reviewers to pull requests, automatically categorize new issues based on keywords, or close stale issues after a period of inactivity.
- Notifications: When a deployment is successful or unsuccessful, send a notification to a Slack or Discord room.
- Scheduled Task: Execute a workflow regularly (e.g., every night at midnight) to complete activities like creating a performance report or looking for broken links on your website.
Best Practices
To get the best out of GitHub Actions, the following best practices should be followed.
Build and Test
- Cache Dependencies: To store dependencies (such as Maven packages or node_modules) in between runs, use the actions/cache action. This significantly accelerates your workflows.
- Employ a Matrix Strategy: To test every possible combination with the least amount of code duplication, use a build matrix (strategy: matrix) if your application must support several operating systems or versions of a language (e.g., Node.js 18 & 20; Linux & Windows).
- Fail Fast: Arrange your tasks so that the most important and rapid tests are completed first. They save you time and resources by stopping the workflow if they fail.
Deploy and Rollback
- Use Environments: Make use of GitHub Environments to safeguard sensitive branches, such as main. You can include protection rules, like needing a certain individual to authorize a deployment.
- Safely Handle Secrets: Don’t include passwords or API keys in your workflow files. Keep them in your organization’s settings or repository as encrypted secrets.
- Make a Rollback Plan: You have an excellent deployment process, but what if something goes wrong? Make a distinct workflow that is manually triggered to swiftly redeploy an earlier stable version of your application.
Troubleshooting
- Enable Debug Logging: To enable step debug logging if a workflow is failing inexplicably, create a secret called ACTIONS_STEP_DEBUG and set its value to true.
- Analyze the Logs: Your best ally is the logs for every workflow run. They offer a thorough, sequential account of everything that took place.
- Connect with tmate: The tmate/setup-tmate action can be used to solve extremely complex problems on a runner hosted on GitHub. To allow examining the environment in real-time, it pauses the workflow and grants access to the runner via an SSH session.
Simple Setup of GitHub Action Locally
Let’s start by creating a Repository on GitHub and cloning it into our local directory.

Code Quality Check
One of the great features of GitHub Actions is the ability to perform code quality checks before moving to any of the main/master branches.
Create a GitHub Action YAML file that gets triggered when we push to any of the branches except the main branch or when we do a Pull Request to the main branch.

name: Python Tests
on:
push:
branches:
- '**' # Match all branches
- '!main' # Exclude the main branch
pull_request:
branches:
- main # Also run when PRs target main branch
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run test
run: python tests/test_run.py
With the code pushed to the dev branch, you will notice this will trigger the test action we just created.


Scheduling Workflow
Scheduling a workflow in GitHub Actions allows you to automatically run a workflow at a specific time or on a repeating interval, without needing a push, pull_request, or any other repository event to trigger it.
The example below shows how to schedule a Python script that moves data from Redshift to S3 Bucket incrementally using the concept of last modified date.
Using the Schedule feature in GitHub Action, we can schedule a job to run at a particular interval. Also, ensure adding the GitHub Secret as the codebase will be using the AWS Secret Manager.

Make sure these are set in your repo’s Settings > Secrets and variables > Actions.

name: Daily Redshift to S3 Data Migration
on:
schedule:
# Run at 5 AM UTC (6 AM Nigerian time) every day
- cron: '0 5 * * *'
workflow_dispatch:
jobs:
run-migration:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION || 'eu-west-2' }}
- name: Run Redshift to S3 migration script
run: |
python app/move_redshift_s3_asm.py
env:
AWS_SDK_LOAD_CONFIG: 1

GitHub Action Deployment with Other Cloud Services
Beyond just code quality checks and scheduling of workflows, GitHub has a Marketplace containing thousands of pre-built actions created by companies and the community. You can seamlessly integrate them with virtually any cloud provider or service.
Regardless of where your resources are located, this puts GitHub Actions in a position to serve as the main command center for your whole deployment plan.
A few typical use cases for deploying to other services are:
- Container Workflows (Docker): Automating the containerization of programs is one of the main use cases for
- Deploying to Microsoft Azure: There is a comprehensive set of formal steps available to teams that have invested in the Azure ecosystem. Deployments to several Azure services can be automated, including:
- Azure Web Apps: Your application (such as a .NET or Node.js app) can be built using a workflow and then deployed straight to an Azure App Service machine.
- Azure Functions: Serverless functions that are automatically deployed.
- Azure Kubernetes Service (AKS): Create and launch containerized apps on your Kubernetes cluster.
Conclusion
GitHub Actions offers a versatile, integrated automation engine that directly addresses the tedious, manual phases in the development process. By automating your builds, tests, and deployments, you can eliminate repetitive work, reduce errors, and free up your team to concentrate on creating excellent code. In this article, we broke down the concept of GitHub Actions, what it is, and when to use it.
Next Steps