Skip to content

Add sphinx-airflow-theme as uv workspace member#65840

Open
srchilukoori wants to merge 3 commits intoapache:mainfrom
srchilukoori:feature/sphinx-theme-workspace
Open

Add sphinx-airflow-theme as uv workspace member#65840
srchilukoori wants to merge 3 commits intoapache:mainfrom
srchilukoori:feature/sphinx-theme-workspace

Conversation

@srchilukoori
Copy link
Copy Markdown
Contributor

@srchilukoori srchilukoori commented Apr 25, 2026

Summary

  • Vendors sphinx_airflow_theme (v0.3.9) templates from apache/airflow-site into docs-theme/ as a uv workspace member
  • Replaces the remote .whl URL dependency with a local workspace dependency
  • Static build artifacts (_gen/ — minified CSS/JS/fonts) are not committed to git; a fetch script extracts them from the published wheel on demand

Closes: #45576

Changes

  • docs-theme/: Vendored theme source (templates, config) from apache/airflow-site_gen/ is gitignored
  • scripts/ci/fetch_theme_assets.py: Idempotent script that downloads the published wheel from airflow.apache.org and extracts all theme files (templates + _gen/) into docs-theme/sphinx_airflow_theme/. Skips __init__.py (version-managed locally). Applies compliance patches post-extraction (license headers, inclusive language). Version-stamped to skip redundant downloads
  • docs-theme/sphinx_airflow_theme/__init__.py: Added guard that raises FileNotFoundError with clear instructions if _gen/ is missing. Fixed pre-existing bug where "__version__" was returned as a literal string instead of the version variable
  • pyproject.toml: Added docs-theme to [tool.uv.workspace] members and sphinx-airflow-theme to [tool.uv.sources]
  • devel-common/pyproject.toml: Changed sphinx-airflow-theme from .whl URL to standard version specifier (>=0.3.9)
  • Dockerfile.ci: Added RUN python fetch_theme_assets.py so CI images have _gen/ for non-bind-mount scenarios (e.g., --mount-sources=remove with --use-airflow-version)
  • .github/workflows/airflow-distributions-tests.yml: Added a host-side python scripts/ci/fetch_theme_assets.py step before breeze testing — required because breeze's default MOUNT_SELECTED bind-mounts host docs-theme/ over the container path, which masks the image-baked _gen/. The fetch on the runner populates the bind-mounted directory.
  • dev/breeze/src/airflow_breeze/commands/developer_commands.py: Auto-fetches theme assets before build-docs if _gen/ is missing
  • dev/breeze/src/airflow_breeze/utils/docker_command_utils.py: Added docs-theme to VOLUMES_FOR_SELECTED_MOUNTS
  • scripts/ci/prek/upgrade_important_versions.py: Restored theme version tracking — now updates __init__.py version instead of the old wheel URL pattern
  • .pre-commit-config.yaml: Removed _gen/ exclusions (no longer tracked in git)
  • selective_checks.py: Removed redundant ^docs-theme pattern (already matched by ^docs)
  • dev/breeze/tests/test_theme_workspace.py: Tests verifying workspace wiring, gitignore, and fetch script presence

Design decisions

  • Why not commit _gen/? It's 1.1MB of minified CSS, vendored JS (3 jQuery versions, 2 Popper versions), and binary fonts — 92% of the theme by size. Keeping build artifacts out of git avoids permanent repo bloat.
  • Why fetch from the wheel? The wheel URL on airflow.apache.org is the same source the current dependency already uses. No new infrastructure required.
  • Why a guard in __init__.py? Without _gen/, Sphinx fails with cryptic errors. The guard gives a one-line fix instruction.
  • Two-layer fetch (Dockerfile.ci + workflow)? Yes. Breeze's default mount mode bind-mounts docs-theme/ from host into the container at test time, masking anything baked into the image at that path. The workflow step ensures the host directory has _gen/ for the bind-mount path; the Dockerfile RUN covers non-bind-mount paths (e.g., --use-airflow-version).
  • How is this kept in sync with airflow-site? upgrade_important_versions.py detects new theme releases and bumps __version__ in __init__.py. When the version changes, fetch_theme_assets.py extracts the full wheel contents, bringing templates and build artifacts in sync with upstream. Compliance patches (license headers, inclusive language) are applied automatically post-extraction. Changes made locally (e.g., during a Sphinx upgrade) are backported to airflow-site via PR.

Motivation

As described in #45576, modifying the Sphinx docs theme currently requires building and publishing a .whl to airflow.apache.org before changes can be tested against Airflow docs. Adding the theme as a uv workspace member means uv sync resolves it from the local docs-theme/ directory. Editing a template and rebuilding docs immediately reflects the change.

Was generative AI tooling used to co-author this PR?

  • Yes

@boring-cyborg boring-cyborg Bot added area:dev-tools backport-to-v3-2-test Mark PR with this label to backport to v3-2-test branch labels Apr 25, 2026
@srchilukoori srchilukoori reopened this Apr 26, 2026
@srchilukoori srchilukoori force-pushed the feature/sphinx-theme-workspace branch 4 times, most recently from 02b9bc6 to 4bacb0f Compare April 26, 2026 14:27
@srchilukoori srchilukoori marked this pull request as ready for review April 26, 2026 19:03
@potiuk
Copy link
Copy Markdown
Member

potiuk commented Apr 26, 2026

How are you going to make sure it is going to be synchronized between airlfow-site and airflow repo ?

Copy link
Copy Markdown
Member

@potiuk potiuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting for explantion of how the process shoudl work

(AIRFLOW_ROOT_PATH / "dev" / "provider_db_inventory.py", False),
(AIRFLOW_ROOT_PATH / "dev" / "pyproject.toml", False),
(AIRFLOW_ROOT_PATH / "go-sdk" / ".pre-commit-config.yaml", False),
(AIRFLOW_ROOT_PATH / "docs-theme" / "sphinx_airflow_theme" / "__init__.py", False),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@potiuk this step pulls the latest theme files from the upstream airflow-site

@srchilukoori srchilukoori force-pushed the feature/sphinx-theme-workspace branch from 4bacb0f to 7dc298f Compare April 26, 2026 23:58
@srchilukoori srchilukoori requested a review from potiuk April 27, 2026 00:24
@srchilukoori srchilukoori force-pushed the feature/sphinx-theme-workspace branch 3 times, most recently from 8fa2a00 to dd88bf6 Compare April 29, 2026 14:16
@srchilukoori srchilukoori force-pushed the feature/sphinx-theme-workspace branch from dd88bf6 to 26ed34d Compare May 2, 2026 18:31
urlopen can fail transiently in CI (HTTP 401, timeouts, connection
resets). Retry up to 3 times with exponential backoff (2s, 4s) before
exiting with an error.
@srchilukoori
Copy link
Copy Markdown
Contributor Author

Waiting for explantion of how the process shoudl work

What changed: sphinx-airflow-theme moves from an external URL dependency to a uv workspace member, with a fetch pipeline that pulls compiled assets from the published wheel at build time.

Before → After

BEFORE:
  devel-common/pyproject.toml
    └── sphinx-airflow-theme @https://...whl  (external URL dep, fetched by pip)

AFTER:
  pyproject.toml (workspace root)
    ├── members: [..., "docs-theme"]
    └── sources: sphinx-airflow-theme = {workspace: true}

  devel-common/pyproject.toml
    └── sphinx-airflow-theme  (workspace ref, no URL)

  docs-theme/                          ← new workspace member
    ├── pyproject.toml                   (flit build backend)
    └── sphinx_airflow_theme/
        ├── __init__.py                  (version + _gen/ guard)
        ├── *.html templates             (committed, editable locally)
        ├── theme.conf
        ├── static/js/globaltoc.js
        └── static/_gen/                 (gitignored, fetched at build)

Asset Fetch Pipeline

scripts/ci/fetch_theme_assets.py
  │
  ├─ reads __version__ from __init__.py
  ├─ checks _gen/.version stamp → skips if current (idempotent)
  │
  ├─ downloads wheel from airflow.apache.org
  │   └─ 3 retries with exponential backoff (2s, 4s)
  │   └─ hard exit after exhausting retries
  │
  ├─ extracts theme files into docs-theme/sphinx_airflow_theme/
  ├─ applies compliance patches (license headers, inclusive language)
  └─ writes _gen/.version stamp

CI Entry Points

Dockerfile.ci          → RUN python fetch_theme_assets.py     (baked into image)
distributions-tests.yml → pre-step: fetch on host              (bind-mount masks image content)
Breeze shell start      → auto-fetch if _gen/ missing
local.yml               → bind-mount docs-theme/ into container

Key decisions:

  • Templates committed, compiled assets fetched — clean repo, local theme dev enabled
  • Idempotent via .version stamp file
  • Retry with exponential backoff guards against transient CI failures
  • Bind-mount in local.yml masks Dockerfile.ci baked content → fetch runs on host side too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-tools backport-to-v3-2-test Mark PR with this label to backport to v3-2-test branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an option to mount airflow-site/sphinx_airflow_theme when running CI locally

2 participants