Coding's Art — #1 Web Development & Custom Web Design in Jagraon
DevOps & Cloud • 6 min read • 10 Oct, 2026

Simple DevOps Crash Course: Build a Real CI/CD Pipeline in 15 Minutes

Simple DevOps Crash Course: Build a Real CI/CD Pipeline in 15 Minutes - Coding Tutorial Guide

DevOps sounds like a fancy corporate buzzword, but the idea is dead simple. Developers write code. Operations engineers keep servers running. In the old days, developers threw their code over a wall to the operations team and prayed that it worked. When it crashed, everyone blamed each other.

DevOps removes the wall. It turns manual tasks into code. Instead of copying files to a server late at night, you write scripts that test, build, and deploy your software automatically every time you push a change to Git. Here is your hands-on programming tutorial to set up a real pipeline from scratch.

The Core Workflow: Code, Test, Build, Ship

Every reliable DevOps setup follows a loop called CI/CD. CI stands for Continuous Integration. CD stands for Continuous Delivery or Continuous Deployment. Here is what happens in that loop:

  • Continuous Integration: Whenever you push code, an automated server grabs it, installs dependencies, and runs your test suite. If a test fails, the pipeline stops and alerts you immediately.
  • Continuous Delivery: Once tests pass, the pipeline packages your code into a clean, ready-to-run container or artifact.
  • Continuous Deployment: The pipeline automatically pushes that container to your staging or production servers without any human button-clicking.

Step 1: Write a Simple App and a Test

Let us create a small Python web service. We will write one tiny function and one unit test so our pipeline has something real to verify.

Save this as app.py:

def calculate_discount(price, discount_percent):
    if price < 0 or discount_percent < 0:
        raise ValueError("Values cannot be negative")
    if discount_percent > 100:
        raise ValueError("Discount cannot exceed 100 percent")
    return price * (1 - (discount_percent / 100))

if __name__ == "__main__":
    print(f"Test price: {calculate_discount(100, 20)}")

Now create a test file named test_app.py using Python's built-in unittest runner:

import unittest
from app import calculate_discount

class TestApp(unittest.TestCase):
    def test_standard_discount(self):
        self.assertEqual(calculate_discount(100, 10), 90.0)

    def test_negative_price(self):
        with self.assertRaises(ValueError):
            calculate_discount(-50, 10)

if __name__ == "__main__":
    unittest.main()

Step 2: Automate Everything with GitHub Actions

You do not need to pay for heavy enterprise servers to learn DevOps. GitHub Actions gives you free runners. To create your first pipeline, make a folder in your project called .github/workflows and put a file named pipeline.yml inside it.

name: Main Pipeline

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Run unit tests
        run: |
          python -m unittest test_app.py

Every time you run git push, GitHub spins up a clean Ubuntu server, pulls your branch, and runs your tests. If someone writes bad code that breaks a calculation, the pull request turns red and blocks the merge.

Step 3: Package the App with Docker

The oldest problem in software development is the phrase: "It worked on my machine." A container solves this. It wraps your code, the exact operating system, and all packages into an immutable box.

Create a file named Dockerfile in your root folder:

# Use a tiny, secure base image
FROM python:3.11-slim

# Create a non-root system user for security
RUN useradd -m appuser

WORKDIR /home/appuser

# Copy app code
COPY app.py .

USER appuser

# Run the script
CMD ["python", "app.py"]

Build and run the container locally to verify it works:

docker build -t simple-devops-app:latest .
docker run --rm simple-devops-app:latest

Step 4: Handy Coding Shortcuts with Makefiles

Typing long Docker and Git commands over and over wastes time and invites typos. Veteran engineers use small coding shortcuts. A simple Makefile in your project root lets you run everything with short, memorable words.

.PHONY: test build run clean

test:
	python3 -m unittest test_app.py

build:
	docker build -t simple-devops-app:latest .

run:
	docker run --rm simple-devops-app:latest

all: test build run

Now, instead of remembering three different shell commands, you just open your terminal and type make all. If tests fail, Make stops immediately and never builds the Docker image.

Edge Cases and Common DevOps Pitfalls

Pipelines break in funny ways when you move to real production systems. Watch out for these four common traps:

1. Unpinned Dependencies

If your build script installs packages using pip install flask without fixing the version number, your pipeline might pass today and break tomorrow when Flask releases a major update. Always lock your versions using a lockfile or exact tags like flask==3.0.2.

2. Hardcoded Secrets

Never put database passwords, SSH keys, or API tokens inside your Git repository or your Dockerfile. Anyone with read access can steal them. Use environment variables and store credentials inside GitHub Secrets or an encrypted vault.

3. Ignoring Exit Codes

In shell scripts, commands often fail quietly while the script keeps going. Always add set -e at the top of bash scripts used in your pipelines. This tells bash to halt execution immediately if any single line returns a non-zero exit code.

4. Storage Leaks on Self-Hosted Runners

If you run your own build agents, old Docker images and build caches will eat all your hard drive space within weeks. Set up automated cron jobs to run docker system prune -af --volumes on your build nodes weekly.

Summary Checklist for Your Daily Work

Good DevOps is not about using twenty different tools at once. It is about keeping your release cycle predictable and painless. Keep your automated steps small, fail fast when something is wrong, and automate any task you find yourself doing more than twice.

" ,

Frequently Asked Questions

Q.

Q.

Q.

HS

Hardeep Singh

Lead AI & Full-Stack Architect | Founder, Coding's Art

Hardeep is a senior software engineer and published author specializing in Python automation, enterprise Laravel systems, and autonomous AI agents. With over 8 years of hands-on experience, he designs robust digital solutions and publishes practical engineering playbooks for developers and technical leaders across India and globally.

Related Developer Guides

Chat with AI Assistant