fix(modules-16,18,19,20): runner receipt on red, runnable M20 Part A, container caveats

- M19: `if: always()` on the "where did this run?" receipt step only (GitLab
  when: always noted) so it prints even when lint/test fail; real steps unchanged.
- M20: mark Part A optional with its runtime prereq (npx/Node or uvx/uv) named;
  Part B/C (Python SDK) carry the load-bearing path. Reconciled objectives/checks.
- M16: native-Linux bind-mount caveat (root-owned __pycache__; PYTHONDONTWRITEBYTECODE).
- M16/M18: prerequisite that the container engine/daemon must be RUNNING
  (docker --version is false reassurance; docker info; podman machine start).

Closes #41
Closes #42
Closes #45
Closes #46

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
This commit is contained in:
2026-06-22 17:20:22 -04:00
parent 6691755060
commit 5166d58c20
5 changed files with 51 additions and 15 deletions
@@ -173,7 +173,11 @@ containerize and run the app you already have.
- The `tasks-app` folder from Module 1 (`tasks.py`, `cli.py`).
- A container engine. **Docker Desktop** (macOS/Windows) or **Docker Engine** (Linux) is the common
choice; **Podman** works too and the commands below map 1:1 (`podman` for `docker`). Verify with
`docker --version` (or `podman --version`).
`docker --version` (or `podman --version`). **The engine must be *running* before you build:**
`docker --version` reports the client version even when the engine is stopped, so it's false
reassurance — `docker build` then fails with "Cannot connect to the Docker daemon." On
macOS/Windows start it first (launch Docker Desktop, or `podman machine start`); confirm the daemon
is up with `docker info` (or `podman info`), which only succeeds when the engine is actually live.
- The starter files from this module's `lab/`: [`Dockerfile`](lab/Dockerfile) and
[`dockerignore-starter`](lab/dockerignore-starter).
- Your AI assistant.
@@ -234,6 +238,16 @@ containerize and run the app you already have.
> Git Bash), or from PowerShell — `${PWD}` resolves correctly in each. The other `docker run`
> commands mount nothing of yours and are identical everywhere.
> **On native Linux:** the container runs as root by default, and the bind mount maps that straight
> onto your real project folder — so the `__pycache__` directories Python writes during the test
> run land in your repo owned by `root:root`, and you can't delete them without `sudo rm -rf`.
> Prevent it by telling Python not to write bytecode in the container: add
> `-e PYTHONDONTWRITEBYTECODE=1` to the `docker run` line (with pytest you'd also pass
> `pytest -p no:cacheprovider` to suppress `.pytest_cache`). A `.gitignore` won't help — it hides
> the files from Git but they're still on disk and still sudo-only to remove. Avoid `--user
> $(id -u):$(id -g)` here: it fixes ownership but breaks any in-container `pip install` into the
> image's root-owned site-packages.
This is, in miniature, exactly what containerized CI does. If it passes here, it passes the same
way on any machine with the engine — your laptop's local Python version is now irrelevant.