5.4 · Deployment & CI/CD (GitHub Actions, cloud)

Level 5 · Pro level & industrialization

5.4Deployment & CI/CD (GitHub Actions, cloud)

Goal: Put a Python app into production and automate tests + deployment.
Estimated time: 16 min · self-paced reading · If you only have 5 min: read “The essentials in 30s” + the diagram.

The essentials in 30 seconds

  • Guardian CI: on every push, checkout → install → ruff + pytest — red blocks, green authorises.
  • Ship versioned: Docker image to the registry or a platform connected to the repo — every release is traceable.
  • Sober prod: secrets out of YAML, logs and /health, tested rollback — deploying means being able to come back.

Running mini-case — Nabil goes live from Algiers

Nabil's containerised analysis runs well — but only on the team's machines in Algiers. He puts it online: a connected Git repo, a GitHub Actions workflow running ruff and pytest on every push, a versioned image delivered to a platform connected to the repo, logs and a health endpoint in place. Final episode of cases 5.1-5.3 — Nabil closes the loop from pro code to a living app.

Final episode of cases 5.1-5.3 — Nabil closes design, async and Docker with going to production.

1. CI: testing on every push

The GitHub Actions workflow is the guardian: checkout → install Python → pip install -r requirements → ruff + pytest. Every push is proven in minutes: red blocks the merge, green authorises. CI is not an option to “add later” — it is in place from the very first test. Nabil deliberately triggers a failure to see the alert: the day it really breaks, he will know how to read the red.

The green README badge proves the standard: style + tests on every change, with no human intervention.

2. Shipping: image or platform

Two complementary paths. The Docker image pushed to the registry (see 5.3): traceable, reproducible, deployed wherever you want. Or the platform connected to the repo (Render, Railway, Fly and equivalents): every green push updates the site automatically — simple to start with. Secrets in repo secrets, never in YAML: prod is configured, not coded. Nabil compares offers when choosing (plans change) and targets the simple path first, control next.

Either way, every delivery is versioned (tags, SHA): you know exactly what is live.

3. The prod minimum: logs, health, rollback

Deploying = being able to come back. The minimum: structured logs (logging), a /health endpoint for monitoring, versions to roll back to. Without a tested rollback, every release is a jump with no parachute. Nabil tests the way back before the big night: on incident day, he restores instead of improvising — and gets the infrastructure choice and access validated by his IT department before exposing real data.

Without this trio, you do not deploy: you gamble.

Common misinterpretation: “CI can wait until later — and secrets can stay in the YAML, it is convenient.” No. With no CI from the first test, regressions ship silently; later means never. And a secret in versioned YAML stays readable to anyone with repo access: secrets in repo secrets / environment variables, never in plain text.
Shipping with confidence Prove in CI, ship versioned, come back if needed CI (ruff+pytest) Proveon every pushDelivery (versioned) Imageor platformRollback (tested) Comeback if needed
Prove in CI, ship versioned, come back if needed
Text version of the diagram (SEO / screen readers / translation): 1) CI: Nabil pushes from Algiers, the workflow installs and runs ruff + pytest — red blocks. 2) Delivery: if green, a versioned image or a connected platform goes live. 3) Prod: logs, /health and tested rollback; secrets out of YAML. Lesson: prove, ship versioned, be able to come back.

🔎 Concrete example — Nabil's workflow

Style + tests on every push, green badge as proof.

name: ci
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {python-version: "3.12"}
      - run: pip install -r requirements.txt
      - run: ruff check . && pytest -q

Reading: style + tests on every push — red blocks the merge.

Lesson: the green README badge proves the standard continuously.

Section vocabulary

Deployment
Making the app reachable online, off your machine.

Simple example: Nabil's analysis leaves localhost for a public address.

What it is not: a script running only on his PC.

Reflex: is my app reachable off my machine?

CI
Automatically testing every change, from the very first test.

Simple example: Every push of Nabil's runs ruff and pytest.

What it is not: tests run by hand when someone thinks of it.

Reflex: can a push pass with no proof?

Pipeline
An automatic suite of steps (tests, build, deployment) triggered on every push.

Simple example: Nabil's workflow: install, check, test.

What it is not: a manual copy-paste release.

Reflex: is my delivery reproducible?

GitHub Actions
Pipelines described as versioned YAML in .github/workflows.

Simple example: Nabil's ci.yml file, reread like code.

What it is not: a mystery server deploying who knows how.

Reflex: is my pipeline versioned and rereadable?

Rollback
Going back to the previous version, tested before it is needed.

Simple example: Nabil restores the previous version after an incident.

What it is not: fixing in panic directly in prod.

Reflex: did I test my way back?

In practice — Automating tests and deployment

  1. Version your project with Git and push it to a GitHub repo (git init, add, commit, push).
  2. Create a GitHub Actions workflow (.github/workflows/ci.yml) that installs dependencies and runs pytest on every push.
  3. Check in the “Actions” tab that the pipeline runs and turns green; trigger a test failure to see the alert.
  4. Deploy the app on a cloud platform (Render/Railway) connected to the repo: every push updates the site automatically.
You own a CI/CD pipeline that automatically tests and deploys on every change: your app is live, reliable and maintained. Journey complete!

Ready-to-say script — announcing the go-live

“Our analysis is ready to leave localhost: I set up CI from the first test — ruff and pytest on every push, red blocks. I ship versioned via the platform connected to the repo, secrets in repo secrets, logs and a health endpoint in place, rollback tested. Before exposing real data, I get the infrastructure and access validated by IT.”

Say to your manager to get the go-live and the IT circuit on sensitive data approved.

Copy-paste template — generic Python CI workflow

name: ci
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {python-version: "3.12"}
      - run: pip install -r requirements.txt
      - run: ruff check . && pytest -q

Solo / tight budget

Nabil alone: the minimal workflow (ruff + pytest) is enough — the repo's free CI guards prod.

Small business / small team

Green badge + red blocking the merge: nobody ships without proof, even in a hurry.

SME in Algiers

Nabil gets host, access and backups validated by IT in Algiers before exposing real data.

Starting team

Pair up: one writes the workflow, the other checks secrets, /health and rollback; review before the first prod.

Caution: Secrets: never put credentials, keys or tokens in plain text in YAML, code or the repo — use repo secrets and environment variables. Cloud costs: plans and tiers change often, compare offers and watch usage when choosing, without committing blindly. Sensitive data: get the infrastructure choice and access validated by IT (and a lawyer if needed) before exposing real data.

✓ Best practices

  • CI from the first test: green authorises, red blocks.
  • Secrets in repo secrets, never in plain text in YAML.
  • Rollback tested before prod: deploying means being able to come back.

✗ Common pitfalls

  • “We will add CI later” (regressions ship silently).
  • Secrets in plain text in versioned YAML.
  • Deploying with no way back and no monitoring (/health, logs).

Key takeaways

  • Deployment makes the application reachable online (cloud/PaaS).
  • CI/CD automates tests and releases on every code change.
  • GitHub Actions describes pipelines in a versioned YAML file.
  • Git/GitHub is the foundation: versioning, collaboration and pipeline trigger.

48h challenge — apply tomorrow

Add the workflow above to 1 repo: does it push green — and does red block after a triggered failure?

Section exit checklist
  • I can explain CI vs CD in one sentence.
  • My workflow tests on every push (proven green).
  • I know where secrets go (out of YAML).
Self-rating 1-5: is my delivery proven and traceable?is no secret lying around in my repo?

Frequently asked questions

What does CI/CD add over manual deployment?

It removes human error and wasted time: on every change, tests run automatically and, if they pass, the app goes live with no intervention. You ship more often, faster and more safely — a modern-team standard. And red blocking the merge beats any reminders.

Where to host a Python app cheaply?

Repo-connected platforms (Render, Railway, Fly and equivalents) offer entry tiers and automatic deployment from GitHub: ideal to start. For more control, the big clouds are more powerful but more complex — reserve them for needs that justify it. Compare offers when choosing (they change) and get IT validation before exposing sensitive data.

Check your understanding

What does a CI/CD pipeline (e.g. GitHub Actions) do?

Additional resources (optional, to go further)

Level 5 examFresh, harder questions to test what you've learned