Iftekhar EatherTechnical Lead · System Architecture · Cloud
Back to Blog
#Git#DevOps#VersionControl#GitHub#SoftwareDevelopment#Programming#BeginnerGuide#Collaboration#CLI#Engineering

Part 6: GitHub Actions

A Practical Tutorial for Beginners to Advanced Users

Iftekhar Ahmed Eather9 min read
Part 6: GitHub Actions

In the previous article, we learned about Git Hooks and how they can automate checks on a developer's machine.

But there is an important question:

What happens after we push our code to GitHub?

Imagine this workflow:

Developer
    ↓
Write Code
    ↓
git commit
    ↓
git push
    ↓
GitHub


Now imagine GitHub automatically:

  • Runs tests

  • Checks code quality

  • Builds the application

  • Performs security checks

  • Creates a Docker image

  • Deploys the application


That is where GitHub Actions comes in.


What Is GitHub Actions?

GitHub Actions is an automation and CI/CD platform built into GitHub.


It allows us to define automated workflows that run when specific events happen in a repository.


For example:

git push
    ↓
GitHub Actions
    ↓
Run Tests
    ↓
Build Application
    ↓
Security Scan
    ↓
Deploy


Instead of manually performing these steps every time, we define them once and let GitHub automate them.


Why Do We Need CI/CD?

Let's say five developers are working on the same application.


Every developer pushes code several times a day.


Without automation, someone might need to manually:

Pull latest code
    ↓
Install dependencies
    ↓
Run tests
    ↓
Build application
    ↓
Check errors
    ↓
Deploy


This is slow and error-prone.


With CI/CD:

Developer
    ↓
git push
    ↓
Automated Pipeline
    ↓
Test
    ↓
Build
    ↓
Deploy


The goal is simple:

Make software delivery repeatable, reliable, and automated.


CI vs CD

Before going further, understand these two terms.


Continuous Integration — CI

CI means automatically integrating and validating code changes.


A typical CI process could be:

Code Push
    ↓
Install Dependencies
    ↓
Run Tests
    ↓
Lint
    ↓
Build


The purpose is to detect problems early.


For example:

Developer A → Code
Developer B → Code
Developer C → Code
        ↓
     GitHub
        ↓
   CI Pipeline
        ↓
     Tests


If a developer introduces a bug, the pipeline can detect it before the change is merged.


Continuous Delivery / Deployment — CD

CD extends the pipeline beyond testing and building.


For example:

Code
 ↓
Test
 ↓
Build
 ↓
Deploy to Staging
 ↓
Approval
 ↓
Deploy to Production


Depending on the organization, CD can mean Continuous Delivery or Continuous Deployment.


The important idea is automated software delivery.


GitHub Actions Workflow

A GitHub Actions workflow is defined using a YAML file.


The workflow files are normally stored inside:

.github/workflows/


For example:

project/
├── .github/
│   └── workflows/
│       └── ci.yml
├── src/
├── tests/
└── README.md


GitHub automatically detects workflow files in this directory.


A Simple Workflow

Here is a basic example:

name: CI

on:
  push:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run tests
        run: echo "Running tests..."


Don't worry if this looks unfamiliar.

Let's break it down.


name

name: CI

This is simply the name of the workflow.


GitHub will display this name in the Actions interface.


on

on:
  push:
    branches:
      - main

This defines when the workflow should run.


In this example:

Push to main
     ↓
Workflow starts


GitHub Actions can respond to many repository events, such as:

push
pull_request
workflow_dispatch
schedule


For example:

on:
  pull_request:

means the workflow can run when a Pull Request is created or updated.


jobs

jobs:
  test:

A workflow contains one or more jobs.


Think of a job as a major unit of work.


For example:

Workflow
   ↓
┌───────────────┐
│ Build         │
└───────────────┘

┌───────────────┐
│ Test          │
└───────────────┘

┌───────────────┐
│ Security Scan │
└───────────────┘


These can be organized into a complete CI/CD pipeline.


runs-on

runs-on: ubuntu-latest

This specifies the environment where the job runs.


For example:

Ubuntu
Windows
macOS


GitHub provides hosted runners that execute the workflow.


steps

steps:

A job contains individual steps.


For example:

steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Run tests
    run: npm test


The workflow becomes:

Job
 ↓
Checkout Code
 ↓
Run Tests


uses vs run

This is an important distinction.


uses

uses: actions/checkout@v4

uses means we are using an existing GitHub Action.


For example:

actions/checkout

is an action commonly used to retrieve repository code inside the runner.


run

run: npm test

run executes a shell command.


For example:

run: npm install

or:

run: npm test

or:

run: docker build -t myapp .


So the mental model is:

uses → Use an existing Action

run → Execute a command


A More Realistic CI Pipeline

Let's imagine a Node.js application.


A basic pipeline might look like:

Developer
    ↓
git push
    ↓
GitHub
    ↓
Checkout
    ↓
Install Dependencies
    ↓
Run Lint
    ↓
Run Tests
    ↓
Build


A simplified workflow could contain:

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Install dependencies
    run: npm install

  - name: Run lint
    run: npm run lint

  - name: Run tests
    run: npm test

  - name: Build
    run: npm run build


Now every push can automatically go through the same validation process.


GitHub Actions and Pull Requests

GitHub Actions becomes particularly powerful when combined with Pull Requests.


Imagine:

Developer
    ↓
Create Feature Branch
    ↓
Write Code
    ↓
Push Branch
    ↓
Create Pull Request
    ↓
GitHub Actions
    ↓
Run Tests
    ↓
Security Checks
    ↓
Code Review
    ↓
Merge


This creates a controlled software delivery process.


For example, your team can require:

"A Pull Request cannot be merged if the CI pipeline fails."


Now quality checks are not dependent only on individual developers.


GitHub Actions Secrets

CI/CD pipelines often need sensitive information.


For example:

AWS credentials
API keys
Database passwords
Deployment tokens


These values should not be written directly into workflow files.


Never do this:

env:
  AWS_SECRET_ACCESS_KEY: "my-secret-password"


Instead, sensitive values should be stored using GitHub's secret-management capabilities and referenced securely by the workflow.


The principle is:

Never hard-code secrets into source code or CI/CD configuration.


This is especially important in DevOps and cloud environments.


GitHub Actions for Deployment

GitHub Actions is not limited to testing.


We can use it for deployment.


For example:

Developer
    ↓
git push
    ↓
GitHub Actions
    ↓
Test
    ↓
Build Docker Image
    ↓
Push Image to Registry
    ↓
Deploy


A cloud deployment might look like:

GitHub
   ↓
GitHub Actions
   ↓
Docker Build
   ↓
Container Registry
   ↓
Kubernetes / ECS / VM
   ↓
Application


This is where GitHub Actions becomes a real DevOps delivery tool.


GitHub Actions + Docker

Suppose your application has a Dockerfile.


The pipeline could:

Code Push
    ↓
Run Tests
    ↓
docker build
    ↓
Create Image
    ↓
Push Image
    ↓
Deploy


For example:

docker build -t myapp:latest .


Then the image can be pushed to a container registry.


The deployment platform can then pull the image and run the new version.


GitHub Actions + Git Hooks

Remember our previous article?


We discussed Git Hooks.


Now we can combine both concepts.

Developer Machine
        ↓
Git Hook
        ↓
Fast Local Checks
        ↓
git push
        ↓
GitHub
        ↓
GitHub Actions
        ↓
Full CI Pipeline
        ↓
Deploy


This creates multiple layers of protection.


Local Layer

Git Hooks can perform fast checks.


CI Layer

GitHub Actions performs centralized validation.


Deployment Layer

The pipeline can automate delivery.


This is a much stronger engineering workflow than relying on manual processes.


A Professional CI/CD Pipeline

A mature project might eventually have something like:

Developer
    ↓
Feature Branch
    ↓
Git Hook
    ↓
Pull Request
    ↓
GitHub Actions
    ↓
┌──────────────────────┐
│ Code Quality         │
│ Unit Tests            │
│ Integration Tests     │
│ Security Scan         │
│ Dependency Scan       │
│ Build                 │
└──────────────────────┘
            ↓
       Code Review
            ↓
          Merge
            ↓
       Deploy Staging
            ↓
      Acceptance Tests
            ↓
       Production


Notice how Git, GitHub, Git Hooks, CI/CD and deployment are connected.


They are not isolated technologies.


Together they form a software delivery system.


GitHub Actions vs Jenkins

You may also hear about Jenkins.


Both can be used to build CI/CD pipelines.


A simplified comparison:

GitHub Actions

Jenkins

Built into GitHub

Separate CI/CD platform

YAML-based workflows

Pipeline configuration / Jenkinsfile

GitHub-hosted or self-hosted runners

Usually self-managed infrastructure

Easy GitHub integration

Highly extensible

Lower initial operational overhead

More infrastructure management


Neither is universally "better."


The right choice depends on the organization's requirements, infrastructure, security model, existing ecosystem, and operational capabilities.


As a system engineer, don't ask only:

"Which tool is popular?"


Ask:

"What problem are we solving, and what operational model fits our organization?"


Common Mistakes

There are several mistakes beginners often make with CI/CD.


1. Putting secrets in YAML

Never commit passwords or API keys.


2. Making pipelines unnecessarily slow

If every small change takes 30 minutes to validate, developers will eventually try to bypass the process.


3. Running everything in one huge job

Large pipelines can become difficult to understand and troubleshoot.


4. Ignoring failed pipelines

A CI pipeline only provides value if the team actually responds to failures.


5. Deploying directly to production without controls

Production deployment should have appropriate testing, approval, rollback, monitoring, and access controls.


The Engineering Mindset

GitHub Actions teaches an important DevOps principle:

If a process happens repeatedly, consider automating it.


Instead of:

Developer remembers
Developer executes
Developer checks
Developer deploys

we move toward:

Developer changes code
        ↓
Automation validates
        ↓
Automation builds
        ↓
Automation deploys
        ↓
Monitoring verifies


This improves:

  • Consistency

  • Repeatability

  • Speed

  • Traceability

  • Quality

  • Reliability


The Bigger Picture

At the beginning of this Git series, Git was simply:

git add
git commit
git push


Now look at where we are:

Git
 ↓
Branches
 ↓
Merge
 ↓
Squash
 ↓
Cherry-pick
 ↓
Git Hooks
 ↓
GitHub
 ↓
GitHub Actions
 ↓
CI/CD
 ↓
Automated Deployment


This is the progression from using Git as a version-control tool to using Git as part of a professional software engineering system.


Final Thought

GitHub Actions is not just about writing YAML files.


The real lesson is about designing reliable delivery processes.


A professional engineering team should gradually move from:

Manual
   ↓
Repeatable
   ↓
Automated
   ↓
Observable
   ↓
Reliable


And that's exactly where GitHub Actions fits into the DevOps journey.


Git manages the history.

GitHub provides collaboration.

Git Hooks automate local checks.

GitHub Actions automates the delivery pipeline.


Together, they form a strong foundation for modern software engineering.