From a7604c57d036a3ba1a6a2c86d5a03d31f1de39bb Mon Sep 17 00:00:00 2001 From: Sean Meyer Date: Tue, 13 Jan 2026 08:51:15 -0700 Subject: [PATCH] docs: Add Python dependency lockfile with CI validation Add proper lockfile generation and CI validation for Python dependencies used in documentation building. Changes: - Rename requirements-min/requirements.txt to requirements.in (unpinned deps) - Replace pip freeze with uv pip compile for lockfile generation - Add update-deps target for regenerating lockfile - Add verify-deps target for CI validation - Add CI job to verify lockfile stays in sync with requirements.in The lockfile (requirements.txt) is generated using uv with: make -C Documentation update-deps Developer workflow: 1. Edit requirements.in to add/update dependencies 2. Run: make -C Documentation update-deps 3. Commit both requirements.in and requirements.txt This enables: - Security vulnerability management via exact version tracking - Build reproducibility across environments - Audit trail for dependency changes Signed-off-by: Sean Meyer --- .github/workflows/documentation.yaml | 14 ++ Documentation/Makefile | 27 ++- .../requirements.txt => requirements.in} | 8 +- Documentation/requirements.txt | 227 +++++++++++++----- 4 files changed, 208 insertions(+), 68 deletions(-) rename Documentation/{requirements-min/requirements.txt => requirements.in} (58%) diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml index b27bac73e12b5..bd098bba1d2ec 100644 --- a/.github/workflows/documentation.yaml +++ b/.github/workflows/documentation.yaml @@ -69,6 +69,20 @@ jobs: entrypoint: ./Documentation/check-build.sh args: html + verify-deps: + name: Verify Python lockfile + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + - name: Install uv + uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6.0.1 + - name: Verify lockfile is in sync + run: | + make -C Documentation verify-deps + check-generated-documentation: name: Check generated documentation if: ${{ github.event_name != 'merge_group' }} diff --git a/Documentation/Makefile b/Documentation/Makefile index 591729eb7a12f..4ef787a3c55d6 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -5,7 +5,7 @@ include ../Makefile.defs include ../Makefile.quiet HELM_VALUES := helm-values.rst -REQUIREMENTS_NODEP := requirements-min/requirements.txt +REQUIREMENTS_IN := requirements.in REQUIREMENTS := requirements.txt SPHINX_OPTS := "-j=auto" @@ -28,7 +28,7 @@ endef ##@ Development Images DOCS_BASE_IMG ?= cilium/docs-base -base-image: Dockerfile ## Build the docs-base image for updating the requirements.txt file. +base-image: Dockerfile ## Build the docs-base image for documentation building. $(call build_image,$<,docs-base,$(DOCS_BASE_IMG)) DOCS_BUILDER_IMG ?= cilium/docs-builder @@ -163,10 +163,25 @@ update-redirects: builder-image ## Build and serve the documentation locally. ##@ Development -update-requirements: base-image $(REQUIREMENTS_NODEP) ## Regenerate the requirements.txt file from requirements-min/requirements.txt. - @echo '## Auto-generated from $(REQUIREMENTS_NODEP) with "make update-requirements"' > $(REQUIREMENTS) - $(QUIET)$(DOCKER_CTR_BASE) $(DOCS_BASE_IMG) \ - bash -c "export HOME=/tmp && pip install --no-warn-script-location -r $(REQUIREMENTS_NODEP) && pip freeze -r $(REQUIREMENTS_NODEP) >> $(REQUIREMENTS)" +.PHONY: update-deps +update-deps: $(REQUIREMENTS_IN) ## Regenerate the requirements.txt lockfile from requirements.in using uv. + uv pip compile --upgrade --python-version 3.11 --python-platform linux $(REQUIREMENTS_IN) -o $(REQUIREMENTS) + +.PHONY: verify-deps +verify-deps: $(REQUIREMENTS_IN) $(REQUIREMENTS) ## Verify requirements.txt is in sync with requirements.in. + @echo "Verifying requirements.txt is in sync with requirements.in..." + $(QUIET)TMP=$$(mktemp) && \ + TMP_CURRENT=$$(mktemp) && \ + TMP_NEW=$$(mktemp) && \ + uv pip compile --upgrade --python-version 3.11 --python-platform linux $(REQUIREMENTS_IN) -o "$$TMP" 2>/dev/null && \ + grep -v '^#' $(REQUIREMENTS) | grep -v '^\s*#' | grep -v '^\s*$$' > "$$TMP_CURRENT" && \ + grep -v '^#' "$$TMP" | grep -v '^\s*#' | grep -v '^\s*$$' > "$$TMP_NEW" && \ + diff -q "$$TMP_CURRENT" "$$TMP_NEW" > /dev/null || \ + (echo "ERROR: requirements.txt is out of sync with requirements.in" && \ + echo "Run 'make -C Documentation update-deps' to regenerate" && \ + rm -f "$$TMP" "$$TMP_CURRENT" "$$TMP_NEW" && exit 1) && \ + rm -f "$$TMP" "$$TMP_CURRENT" "$$TMP_NEW" + @echo "requirements.txt is in sync" clean: ## Clean up all artefacts from documentation. -$(QUIET)rm -rf _build _exts/__pycache__ _preview Pipfile Pipfile.lock diff --git a/Documentation/requirements-min/requirements.txt b/Documentation/requirements.in similarity index 58% rename from Documentation/requirements-min/requirements.txt rename to Documentation/requirements.in index d4211bdc2d046..97a3aeb107d70 100644 --- a/Documentation/requirements-min/requirements.txt +++ b/Documentation/requirements.in @@ -1,8 +1,14 @@ +# Generate lockfile with: make -C Documentation update-deps +# Requires: uv (https://docs.astral.sh/uv/) +# +# Docs dependencies pinned per Cilium documentation build requirements +# Python 3.11 is used (see Dockerfile) + sphinx==7.1.2 sphinx-autobuild==2021.3.14 # Custom theme, forked from Read the Docs -git+https://github.com/cilium/sphinx_rtd_theme.git@cilium/rebase-2023-09#egg=sphinx-rtd-theme-cilium +sphinx-rtd-theme-cilium @ git+https://github.com/cilium/sphinx_rtd_theme.git@cilium/rebase-2023-09 # We use semver to parse Cilium's version in the config file semver==3.0.1 diff --git a/Documentation/requirements.txt b/Documentation/requirements.txt index 7e8be23cd5305..3cd4e6e32bafa 100644 --- a/Documentation/requirements.txt +++ b/Documentation/requirements.txt @@ -1,71 +1,176 @@ -## Auto-generated from requirements-min/requirements.txt with "make update-requirements" -Sphinx==7.1.2 +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.11 --python-platform linux requirements.in -o requirements.txt +alabaster==0.7.16 + # via sphinx +annotated-types==0.7.0 + # via pydantic +attrs==25.4.0 + # via + # jsonschema + # referencing +babel==2.17.0 + # via sphinx +certifi==2026.1.4 + # via requests +charset-normalizer==3.4.4 + # via requests +click==8.3.1 + # via typer +colorama==0.4.6 + # via sphinx-autobuild +deepmerge==2.0 + # via sphinxcontrib-openapi +docutils==0.18.1 + # via + # myst-parser + # rstcheck-core + # sphinx + # sphinx-mdinclude + # sphinx-rtd-theme-cilium + # sphinx-tabs +idna==3.11 + # via requests +imagesize==1.4.1 + # via sphinx +jinja2==3.1.6 + # via + # myst-parser + # sphinx +jsonschema==4.26.0 + # via sphinxcontrib-openapi +jsonschema-specifications==2025.9.1 + # via jsonschema +livereload==2.7.1 + # via sphinx-autobuild +markdown-it-py==3.0.0 + # via + # mdit-py-plugins + # myst-parser + # rich +markupsafe==3.0.3 + # via jinja2 +mdit-py-plugins==0.5.0 + # via myst-parser +mdurl==0.1.2 + # via markdown-it-py +mistune==3.2.0 + # via sphinx-mdinclude +myst-parser==2.0.0 + # via -r requirements.in +packaging==25.0 + # via sphinx +pathspec==1.0.3 + # via yamllint +picobox==4.0.0 + # via sphinxcontrib-openapi +pydantic==2.12.5 + # via rstcheck-core +pydantic-core==2.41.5 + # via pydantic +pyenchant==3.3.0 + # via sphinxcontrib-spelling +pygments==2.19.2 + # via + # rich + # sphinx + # sphinx-mdinclude + # sphinx-tabs +pyyaml==6.0.3 + # via + # myst-parser + # sphinxcontrib-openapi + # yamllint +referencing==0.37.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.5 + # via sphinx +rich==14.2.0 + # via typer +rpds-py==0.30.0 + # via + # jsonschema + # referencing +rstcheck==6.2.0 + # via -r requirements.in +rstcheck-core==1.2.2 + # via rstcheck +semver==3.0.1 + # via -r requirements.in +shellingham==1.5.4 + # via typer +six==1.17.0 + # via sphinxcontrib-httpdomain +snowballstemmer==3.0.1 + # via sphinx +sphinx==7.1.2 + # via + # -r requirements.in + # myst-parser + # sphinx-autobuild + # sphinx-mdinclude + # sphinx-rtd-theme-cilium + # sphinx-tabs + # sphinx-version-warning + # sphinxcontrib-googleanalytics + # sphinxcontrib-httpdomain + # sphinxcontrib-jquery + # sphinxcontrib-openapi + # sphinxcontrib-spelling + # sphinxext-rediraffe sphinx-autobuild==2021.3.14 - -# Custom theme, forked from Read the Docs + # via -r requirements.in +sphinx-mdinclude==0.6.1 + # via sphinxcontrib-openapi sphinx-rtd-theme-cilium @ git+https://github.com/cilium/sphinx_rtd_theme.git@5e45810d0af338f8a7a6337b0377412ddf973dbc -# We use semver to parse Cilium's version in the config file -semver==3.0.1 -# Sphinx extensions -myst-parser==2.0.0 + # via -r requirements.in sphinx-tabs==3.4.1 + # via -r requirements.in sphinx-version-warning==1.1.2 + # via -r requirements.in +sphinxcontrib-applehelp==2.0.0 + # via sphinx +sphinxcontrib-devhelp==2.0.0 + # via sphinx sphinxcontrib-googleanalytics==0.4 + # via -r requirements.in +sphinxcontrib-htmlhelp==2.1.0 + # via sphinx +sphinxcontrib-httpdomain==1.8.1 + # via sphinxcontrib-openapi +sphinxcontrib-jquery==4.1 + # via sphinx-rtd-theme-cilium +sphinxcontrib-jsmath==1.0.1 + # via sphinx sphinxcontrib-openapi==0.8.1 + # via -r requirements.in +sphinxcontrib-qthelp==2.0.0 + # via sphinx +sphinxcontrib-serializinghtml==2.0.0 + # via + # sphinx + # sphinxcontrib-websupport sphinxcontrib-spelling==8.0.0 + # via -r requirements.in sphinxcontrib-websupport==1.2.4 + # via -r requirements.in sphinxext-rediraffe==0.2.7 -# Linters -rstcheck==6.2.0 + # via -r requirements.in +tornado==6.5.4 + # via livereload +typer==0.21.1 + # via rstcheck +typing-extensions==4.15.0 + # via + # pydantic + # pydantic-core + # referencing + # typer + # typing-inspection +typing-inspection==0.4.2 + # via pydantic +urllib3==2.6.3 + # via requests yamllint==1.32.0 -## The following requirements were added by pip freeze: -alabaster==0.7.13 -annotated-types==0.5.0 -attrs==23.1.0 -Babel==2.12.1 -certifi==2024.7.4 -charset-normalizer==3.2.0 -click==8.1.7 -colorama==0.4.6 -deepmerge==1.1.0 -docutils==0.18.1 -idna==3.7 -imagesize==1.4.1 -Jinja2==3.1.6 -jsonschema==4.19.0 -jsonschema-specifications==2023.7.1 -livereload==2.6.3 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==2.0.5 -packaging==23.1 -pathspec==0.11.2 -picobox==3.0.0 -pydantic==2.7.1 -pydantic_core==2.18.2 -pyenchant==3.2.2 -Pygments==2.16.1 -PyYAML==6.0.1 -referencing==0.30.2 -requests==2.32.4 -rich==13.5.2 -rpds-py==0.10.3 -rstcheck-core==1.1.1 -shellingham==1.5.3 -six==1.16.0 -snowballstemmer==2.2.0 -sphinx_mdinclude==0.5.3 -sphinxcontrib-applehelp==1.0.4 -sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==2.0.1 -sphinxcontrib-httpdomain==1.8.1 -sphinxcontrib-jquery==4.1 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.5 -tornado==6.5 -typer==0.9.0 -typing_extensions==4.7.1 -urllib3==2.5.0 + # via -r requirements.in