Skip to Content
Course content

306: Continuous Integration Basics for Python Projects

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're working in a high-end professional kitchen. You've got a head chef, a few sous-chefs, and a line of prep cooks all working on one massive banquet menu. Now, if every cook just threw their ingredients into the big pot without anyone tasting it, you'd eventually serve a soup that's accidentally twice as salty as it should be because two different people thought the dish needed more salt. To prevent this, professional kitchens use a "tasting station." Before any component is added to the final dish, it has to be tasted and approved. If it's wrong, it's fixed right there on the prep table, not after it's reached the customer's plate.

Continuous Integration (CI) is exactly that tasting station, but for your code. Instead of a sous-chef, we use an automated server. Instead of tasting for salt, we run a battery of tests and style checks. Every time you "push" a change to your repository, the CI server wakes up, grabs your code, and puts it through the ringer. If a single test fails, the "dish" is rejected, and you're notified immediately. I can't tell you how many times in my early career I broke a production environment because I "thought" my change was safe, only to realize I'd broken a feature in a completely different part of the app. CI removes that "I thought" from the equation.

The Pipeline Anatomy

When we talk about CI, we're usually talking about a pipeline. Think of this as a checklist the computer follows. For a Python project, a standard pipeline usually looks like this:

  • Checkout: The server clones your code from GitHub or GitLab.
  • Environment Setup: It installs the correct version of Python and your dependencies (usually via pip install -r requirements.txt).
  • Linting: It checks if your code follows PEP 8. I'm a big fan of flake8 or black here. There's no point in running tests if the code is an unreadable mess.
  • Testing: It runs your test suite (typically using pytest). If 99 tests pass but 1 fails, the whole build fails.

Wiring it up with GitHub Actions

You don't need to buy a separate server to do this anymore. Most of us use GitHub Actions because it's built right into the repo. You define your pipeline in a YAML file located at .github/workflows/ci.yml. Here is a real-world example of what that looks like for a project that handles basic financial calculations.

name: Python CI
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
          
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8 pytest
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
          
      - name: Lint with flake8
        run: |
          # stop the build if there are Python syntax errors or undefined names
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          
      - name: Run tests with pytest
        run: |
          pytest

Dealing with the "Red X"

Once this is set up, you'll start seeing a green checkmark or a red X next to your commits. When you see that red X, don't panic—that's actually the system working. It means the CI caught a bug before it ever hit your main branch. My rule of thumb is simple: never merge a Pull Request with a red X. It doesn't matter if you "know" why it's failing or if it's "just a tiny formatting error." Fixing the CI build is part of the development process, not an extra chore to do at the end.




📋 Practical Task

Building a CI Pipeline for the "Currency Converter" Project

You have a small Python project called currency_converter. It has a requirements.txt file and a tests/ folder containing pytest tests. Currently, the project is managed manually, and bugs are slipping into the main branch.

Your Goal: Create a GitHub Actions workflow file that automates the quality control process.

Requirements:

  • The workflow should trigger on every push and every pull_request.
  • It must use ubuntu-latest as the runner.
  • It must install Python 3.9.
  • It must install pytest and flake8.
  • It must run flake8 across the entire project to check for syntax errors.
  • It must run pytest to ensure the conversion logic is still accurate.

Deliverable: Write the complete YAML configuration for .github/workflows/ci.yml that fulfills these requirements.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.