P36 · CI/CD & Delivery
pipelines as code, test matrices & delivery
Gate and deliver a Python project: declare a pipeline as code with quality gates and a test matrix, then package it into a small, reproducible, non-root container image and promote a green build to an immutable release - taught local-first via an in-process CI simulator, with this repo's own pipeline as the worked example.
A quality gate that can be skipped is a suggestion. That distinction is the whole subject of this pillar: the difference between a project that has tests and a project where a change that breaks them cannot reach the main branch. The mechanism is unglamorous and entirely learnable — a pipeline declared as code, where the dependency between jobs is the gate.
You author a real GitHub Actions workflow and then run it through an in-process
CI simulator, which is what makes the semantics visible rather than folkloric. A
job's needs is what stops downstream work when an upstream check fails; a
failed gate skips what depends on it instead of running it hopefully; fail-fast
cancels the siblings when one matrix cell has already answered the question. A
matrix fans the same job across versions or platforms, which is how "works on my
Python" becomes a claim about several. And promotion is the last idea: only a
green build is eligible to become a release, which sounds obvious and is exactly
what a manual process quietly stops honouring under deadline.
The delivery half ships a service rather than a library. You build a Dockerfile linter for the release-hygiene mistakes that recur in real images — an unpinned base image, layer ordering that busts the cache on every build, running as root, a single-stage build that ships the compiler along with the application — which teaches the rules far better than reading them. Then versioning: mapping a semantic version onto an immutable, promoted image tag, so that what is running in production can be identified rather than inferred. This repository's own pipeline is the worked example.