Part 6: GitHub Actions
A Practical Tutorial for Beginners to Advanced Users

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.