* Update docs for the Python 3.11 baseline Contributing docs, Breeze docs, Docker stack docs and the user-facing installation pages used Python 3.10 as the example and default version. Examples and defaults now use 3.11; historical changelog entries and ADRs keep their original wording. * Re-pad the image naming table after dropping Python 3.10 * Fix stale Python 3.10 examples left in the Python 3.11 docs update Review found commands that still pin a 3.10.x interpreter, which can no longer install Breeze or Airflow, shell prompts and pytest transcripts that still show 3.10, and a note that tied the supported Python range to Airflow 3.2.0 even though the 3.2 to 3.4 release lines still accept 3.10. Two Breeze examples used options that do not exist. The python-client release notes presented `breeze --python 3.11` as equivalent to `UV_PYTHON=3.11`, but the reproducibility guard checks the interpreter Breeze itself runs on, so only the `UV_PYTHON` form works. The Docker stack build examples now refer to the default Python version instead of a hard-coded one, so they stop drifting with every bump. * Fix remaining Python 3.10 references in docs and image examples Review found more shell prompts that still show a 3.10 Breeze image. The air-gapped image example pinned Airflow 2.5.3, which publishes no 3.11 constraints, so its download step fetched a 404 page and failed; it also used extras that Airflow 3 no longer defines. The contributor quick start called 3.10 end-of-life before its October 2026 end-of-life date. * Update Python version in database setup guide Updated Python version in setup instructions from 3.8.10 to 3.11.16. * Fix stale Python 3.10 constraints examples in INSTALL Generated-by: Claude Opus 5 --------- Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
8.0 KiB
Table of Contents generated with DocToc
Apache Airflow — runtime invocation
How to invoke the project's runtime on a single source file. Used
by issue-reproducer
when running extracted code from issue descriptions.
The <runtime> placeholder resolves from the Run a single file
section below.
Hard rule (from AGENTS.md): never run pytest,
python or airflow directly on the host. Every reproducer runs inside
the Breeze container, which is the same
environment Airflow CI uses. The only host-side exception is a pure-unit
pytest (no database, no system dependencies) run through
uv run --project <PROJECT> pytest ...; fall back to Breeze as soon as it
fails on a missing system dependency.
Build prerequisite
Breeze must be installed and the CI image built for the Python version you run with:
- Install the per-worktree
breezeshim once per machine:scripts/tools/setup_breeze(installs~/.local/bin/breeze, which runs Breeze viauv run --lockedfrom the current worktree'sdev/breeze— see ADR 0017). - Docker must be running (see
dev/breeze/doc/01_installation.rst). - Build or refresh the CI image before a campaign so the first reproducer
does not pay the build cost inside its timeout:
breeze ci-image build --python <python>. - Python versions:
3.11(default),3.12,3.13,3.14—ALLOWED_PYTHON_MAJOR_MINOR_VERSIONSindev/breeze/src/airflow_breeze/global_constants.py;requires-pythoninairflow-core/pyproject.toml. Use the default unless the issue names a specific Python version. - Metadata-database backend:
sqlite(default),postgresormysqlvia--backend. Use the backend the issue reports when the bug is backend-specific (migrations, locking, SQL dialect); otherwise the default.
Paths inside the container: the repository is mounted at /opt/airflow,
the gitignored files/ folder at /files. Scratch reproducer scripts go
in files/ or dev/ (dev/ is mounted as /opt/airflow/dev/) — never
elsewhere in the source tree.
Run a single file
Three runtime shapes, chosen by what the reproducer is. <file> is the
in-container path of the reproducer (host files/<...> →
/files/<...>); <args> is optional argv.
Recipe — plain Python script against main sources:
breeze run python <file> <args>
Recipe — Dag file (the common case for Airflow bug reports). Point the Dags folder at the reproducer's own directory so no other Dag is parsed, migrate the throwaway metadata DB, then run one Dag run in-process:
breeze run bash -c "airflow db migrate >/dev/null && \
AIRFLOW__CORE__DAGS_FOLDER=$(dirname <file>) airflow dags test <dag_id>"
Recipe — pytest reproducer placed in the matching tests directory
(airflow-core/tests/unit/..., providers/<name>/tests/unit/...,
task-sdk/tests/...):
breeze run pytest <file> -xvs
# pure-unit, no DB / system deps only:
uv run --project <PROJECT> pytest <file> -xvs
Add --backend postgres|mysql and/or --python <X.Y> to any breeze run
line when the issue requires it.
Reproducing against a released version instead of main:
breeze run has no --use-airflow-version; use breeze shell, which
accepts the command as trailing arguments and reinstalls Airflow from
PyPI at entry:
breeze shell --use-airflow-version <X.Y.Z> [--airflow-extras <extras>] \
"<same command as above>"
--use-airflow-version also accepts wheel / sdist (from dist/),
<owner>/<repo>:<branch>, or a PR number — useful for checking whether an
open PR fixes the issue. Documented in
dev/breeze/doc/03_developer_tasks.rst.
Capture conventions
How to capture stdout, stderr, and exit code in a way the skill can parse.
| Stream | Convention |
|---|---|
stdout |
Capture in full. Breeze prints its own banner and entrypoint output before the command's output; the verdict is based only on the command's output that follows it. |
stderr |
Capture and merge into run.log (2>&1). Airflow logs, task tracebacks and Python warnings go to stderr. |
exit code |
breeze run / breeze shell "<cmd>" propagate the inner command's exit code: 0 = success, non-zero = failure. For airflow dags test, do not rely on the exit code alone — also read the final Dag run / task instance states and any traceback in the output. |
timeout |
600s per invocation. Container start-up and (for --use-airflow-version) the PyPI reinstall at entry take minutes before the reproducer body starts; a run that times out during start-up is inconclusive, not fails. |
Network and dependency handling
The Breeze CI image already contains Airflow core, the Task SDK and all
providers installed from local sources, so a reproducer against main
does not resolve dependencies at runtime. Network access is needed only
when building the image or when --use-airflow-version /
--airflow-extras install from PyPI at container entry.
- A reproducer that needs a provider or library not in the image must
not
pip installit silently. When running a released version, pass it via--airflow-extras; otherwise record the missing dependency in the verdict asinconclusive. - A failed PyPI install at entry, an image-build failure, or a
ModuleNotFoundErrorfor a provider is an environment failure — check for it in the output before classifying the run aspassesorfails. - Reproducers needing an external system (Kafka, MongoDB, …) use
breeze --integration <name>(seedev/breeze/doc/03_developer_tasks.rst); cloud-service reproducers that need real credentials cannot be run and are recorded asinconclusive. - Each
breeze runstarts a fresh container, so the metadata DB and installed packages do not leak between reproducers; no per-campaign cache isolation is needed.
| Key | Value |
|---|---|
resolves_dependencies_at_runtime |
false |
cache_isolation_flag |
(not applicable — each breeze run uses a fresh container) |
Cross-references
reassess-pool-defaults.md— named pools forissue-reassesssweeps.reproducer-conventions.md— per-issue evidence-package directory layout.issue-tracker-config.md— tracker URL and project key.