Day 33: Adding Linting and Unit Tests to My GitHub Actions Workflow 🚀


Welcome to Day 33 of my #100DaysOfDevOps journey! After setting up a basic GitHub Actions workflow on Day 35, today I enhanced it to run linting (flake8
) and unit tests (pytest
) automatically. This brings Continuous Integration (Day 34) to life by ensuring my code is clean and functional. As a beginner, I’m excited to share my step-by-step process, code, and lessons—perfect for anyone learning CI/CD! Let’s dive in! 💻
Why Linting and Unit Tests? 🤔
Linting: Checks code style (e.g.,
flake8
enforces PEP 8 for Python). Keeps my code readable and professional.Unit Tests: Verifies code works (e.g.,
pytest
tests myadd
function). Catches bugs early.CI/CD Connection: Automating these checks in GitHub Actions is core to Continuous Integration, ensuring quality on every push.
This builds on my ci-cd-practice
repo (github.com/ritesh355/ci-cd-practice) and preps me for Docker workflows (Days 39–40).
Step 1: Verifying My Setup 🗂️
I used my ci-cd-practice
repo from Days 32–33, which has:
app.py
: A simple function.def add(a, b): return a + b
test_
app.py
: Unit tests.from app import add def test_add(): assert add(2, 3) == 5 assert add(-1, 1) == 0
script.py
: A script from Day 35..github/workflows/ci.yml
: Basic workflow.
Commands:
cd ~/ci-cd-practice
git pull origin main
pip install flake8 pytest
flake8 app.py
pytest test_app.py
flake8
checked style;pytest
passed 2 tests.Fixed any style issues locally to ensure clean code.
Step 2: Enhancing the Workflow ⚙️
I updated .github/workflows/ci.yml
to add lint
and test
jobs alongside run-script
.
Updated ci.yml
:
name: CI Workflow with Linting and Tests
on:
push:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install dependencies
run: pip install flake8
- name: Run linting
run: flake8 app.py
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install dependencies
run: pip install pytest
- name: Run tests
run: pytest test_app.py
run-script:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Run script
run: python script.py
Commands:
git add .github/workflows/ci.yml
git commit -m "Add linting and unit tests to GitHub Actions workflow"
git push origin main
What Happened:
Pushed to
main
, triggering the workflow.Checked GitHub’s Actions tab:
Step 3: Testing with Errors 🔍
To practice debugging , I broke things:
Linting Failure:
Edited
app.py
:def add(a,b):return a+b
Pushed;
lint
job failed withflake8
errors (e.g., “E231 missing whitespace”).
Test Failure:
Edited
test_
app.py
:def test_add(): assert add(2, 3) == 6 # Wrong assert add(-1, 1) == 0
Pushed;
test
job failed withpytest
error (“5 != 6”).
Fixed Both:
Lesson: Logs in the Actions tab are key for debugging CI failures.
Why This Matters 🌟
CI in Action: My workflow now ensures code quality (
flake8
) and functionality (pytest
) on every push.Portfolio: This pipeline is a strong addition to my GitHub portfolio for DevOps jobs.
Weather App: I can apply this to my Flask app to automate checks before deployment.
Tips for Beginners 💡
Test Locally First: Run
flake8
andpytest
before pushing to avoid workflow failures.Check Logs: Use GitHub Actions logs to debug errors.
Keep Jobs Simple: Separate
lint
andtest
jobs for clarity.Document: I noted everything in
Day36.md
:Added `flake8` and `pytest` to `ci.yml`. Tested failures and fixes; learned to read logs. Ready for Day 37’s triggers.
Explore: Try adding a new test (e.g.,
assert add(0, 0) == 0
) and push to see it run.
Resources 📚
Docs:
flake8
(flake8.pycqa.org),pytest
(docs.pytest.org), GitHub Actions (docs.github.com/en/actions)Video: FreeCodeCamp’s “GitHub Actions Tutorial” (YouTube)
Tool: GitHub (github.com) for repos and Actions
What’s Next? 🔜
On Day 37, I’ll explore GitHub Actions triggers (e.g., push
, pull_request
) to make my workflow more flexible. This will enhance collaboration for my projects! Stay tuned!
Join the Journey! 🚀
Have you added tests to a CI pipeline? Share your tips or questions in the comments! Follow my #100DaysOfDevOps on Hashnode for more DevOps adventures. Let’s master CI/CD together! 💪
👨💻 Author
Ritesh Singh
🌐 LinkedIn | 📝 Hashnode | GitHub
#100DaysOfDevOps #CICD #GitHubActions #DevOps #Beginner
Subscribe to my newsletter
Read articles from Ritesh Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ritesh Singh
Ritesh Singh
Hi, I’m Ritesh 👋 I’m on a mission to become a DevOps Engineer — and I’m learning in public every single day.With a full-time commitment of 8–10 hours daily, I’m building skills in: ✅ Linux✅ Git & GitHub✅ Docker & Kubernetes✅ AWS EC2, S3✅ Jenkins, GitHub Actions✅ Terraform, Prometheus, Grafana I post daily blogs on Hashnode, push projects to GitHub, and stay active on LinkedIn and Twitter/X. Let’s connect, collaborate, and grow together 🚀 #100DaysOfDevOps #LearningInPublic #DevOps