-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
306: Continuous Integration Basics for Python Projects
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
flake8orblackhere. 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
pushand everypull_request. - It must use
ubuntu-latestas the runner. - It must install Python 3.9.
- It must install
pytestandflake8. - It must run
flake8across the entire project to check for syntax errors. - It must run
pytestto ensure the conversion logic is still accurate.
Deliverable: Write the complete YAML configuration for .github/workflows/ci.yml that fulfills these requirements.
There are no comments for now.