diff --git a/.github/workflows/docs-checks.yml b/.github/workflows/docs-checks.yml index 8de3690..f11e4bb 100644 --- a/.github/workflows/docs-checks.yml +++ b/.github/workflows/docs-checks.yml @@ -36,7 +36,13 @@ jobs: - name: Install Python dependencies run: | pip install git+https://github.com/gardenlinux/glrd.git@v4.1.0 - pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@0.10.20 + # Install python-gardenlinux-lib from the same commit the aggregation + # documents (see repos-config.json). This keeps the installed gardenlinux + # module in sync with the fetched source so Sphinx autodoc can import + # gardenlinux.* (e.g. oci -> podman, distro_version -> semver) and generate + # the CLI/API reference pages. Pinning an older release tag here drops + # those deps and breaks the python-gardenlinux-lib-cli reference. + pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@c1dfb1390e5352476cbfcee8ad809a04d808903b pip install -r requirements.txt - name: Run aggregate diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9b91157..ce8c9ce 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,7 +35,13 @@ jobs: - name: Install Python dependencies run: | pip install git+https://github.com/gardenlinux/glrd.git@v4.1.0 - pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@0.10.20 + # Install python-gardenlinux-lib from the same commit the aggregation + # documents (see repos-config.json). This keeps the installed gardenlinux + # module in sync with the fetched source so Sphinx autodoc can import + # gardenlinux.* (e.g. oci -> podman, distro_version -> semver) and generate + # the CLI/API reference pages. Pinning an older release tag here drops + # those deps and breaks the python-gardenlinux-lib-cli reference. + pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@c1dfb1390e5352476cbfcee8ad809a04d808903b pip install -r requirements.txt - name: Run tests diff --git a/Makefile b/Makefile index 1ad0bdd..b8ee392 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,13 @@ install: @echo "Installing dependencies..." pnpm install pip install git+https://github.com/gardenlinux/glrd.git@v4.1.0 - pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@0.10.20 + # Install python-gardenlinux-lib from the same commit the aggregation + # documents (see repos-config.json). This keeps the installed gardenlinux + # module in sync with the fetched source so Sphinx autodoc can import + # gardenlinux.* (e.g. oci -> podman, distro_version -> semver) and generate + # the CLI/API reference pages. Pinning an older release tag here drops + # those deps and breaks the python-gardenlinux-lib-cli reference. + pip install git+https://github.com/gardenlinux/python-gardenlinux-lib.git@c1dfb1390e5352476cbfcee8ad809a04d808903b pip install -r requirements.txt run: diff --git a/repos-config.json b/repos-config.json index 6f0963a..565906c 100644 --- a/repos-config.json +++ b/repos-config.json @@ -4,7 +4,7 @@ "name": "gardenlinux", "url": "https://github.com/gardenlinux/gardenlinux", "ref": "main", - "commit": "7310b68ed7a474380dc5c55229b84f5439cb26a8", + "commit": "f135908d017f8b306f89a36d2048f6fedad1e177", "root_files": [ "CONTRIBUTING.md", "SECURITY.md", @@ -16,14 +16,14 @@ { "name": "builder", "url": "https://github.com/gardenlinux/builder", - "ref": "docs/flavor_cname", - "commit": "c9a84891f05bd85872e58e5d77676774940eccb9" + "ref": "main", + "commit": "4bdc94bb29a8dcfcb7f3be50cd909a9af875b731" }, { "name": "python-gardenlinux-lib", "url": "https://github.com/gardenlinux/python-gardenlinux-lib", - "ref": "docs-ng", - "commit": "61a370280ff6c726f91b3d65f7ed172448841858", + "ref": "main", + "commit": "c1dfb1390e5352476cbfcee8ad809a04d808903b", "structure": "sphinx", "target_map": { "cli.md": "reference/python-gardenlinux-lib-cli.md", @@ -33,26 +33,26 @@ { "name": "package-linux", "url": "https://github.com/gardenlinux/package-linux", - "ref": "docs-ng", - "commit": "45f0d1a62a723d0052bcfbf9eb40e26366595164" + "ref": "main", + "commit": "f69981886bced20b25c241f19863370e6cee6b3c" }, { "name": "package-build", "url": "https://github.com/gardenlinux/package-build", - "ref": "docs-ng", - "commit": "2021e13e55a73d060450c295307c9a996f08ba91" + "ref": "main", + "commit": "faf09b767270aacd869fbf0b11154d3044e8ad58" }, { "name": "repo", "url": "https://github.com/gardenlinux/repo", - "ref": "docs-ng", - "commit": "030acbd0d9c08da047e65f8becd28862aefecd17" + "ref": "main", + "commit": "cd9dba1588400e6ea44a5076a673c3587fe93c3c" }, { "name": "glrd", "url": "https://github.com/gardenlinux/glrd", - "ref": "docs-ng", - "commit": "c51d0a8f902322848aa17bdee8ddd3a86bf86bf3" + "ref": "main", + "commit": "d24a4d63107fdba44531faf831668a26c7ca20a2" } ] } diff --git a/requirements.txt b/requirements.txt index 68a74e3..979d565 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ codespell==2.4.2 pytest pyyaml # glrd @ git+https://github.com/gardenlinux/glrd.git@v4.2.0 -# gardenlinux @ git+https://github.com/gardenlinux/python-gardenlinux-lib.git@0.10.20 +# gardenlinux @ git+https://github.com/gardenlinux/python-gardenlinux-lib.git@c1dfb1390e5352476cbfcee8ad809a04d808903b sphinx sphinx-markdown-builder sphinx-rtd-theme diff --git a/src/aggregate.py b/src/aggregate.py index a0b0baf..f39c9c2 100755 --- a/src/aggregate.py +++ b/src/aggregate.py @@ -16,6 +16,7 @@ from aggregation.structure import verify_internal_links from aggregation.flavor_matrix import generate_flavor_matrix_docs from aggregation.github_api import GitHubAPIError, list_repo_releases +from aggregation.install_pins import sync_install_pins from aggregation.release_notes import generate_release_notes_docs from aggregation.releases import generate_release_docs @@ -283,6 +284,13 @@ def main() -> int: save_config(str(config_path), repos) print(f"\nāœ“ Config updated: {config_path}") + # Keep python-gardenlinux-lib install pins in sync with the lock so + # the aggregation environments install the same commit they document + # (see aggregation.install_pins for the full rationale). + pgl_commit = resolved_commits.get("python-gardenlinux-lib") + if pgl_commit: + sync_install_pins(project_root, pgl_commit) + # Generate flavor matrix documentation after all repos are aggregated # Use the gardenlinux temp dir (still available inside the with block) if gardenlinux_temp_dir and gardenlinux_temp_dir.exists(): diff --git a/src/aggregation/install_pins.py b/src/aggregation/install_pins.py new file mode 100644 index 0000000..6715954 --- /dev/null +++ b/src/aggregation/install_pins.py @@ -0,0 +1,81 @@ +"""Keep python-gardenlinux-lib install pins in sync with repos-config.json. + +``repos-config.json`` is the single source of truth for the commit that the +aggregation pipeline fetches and Sphinx-builds. The environments that run the +aggregation must install the *same* commit so Sphinx autodoc can import that +source's transitive dependencies (e.g. ``oci`` -> ``podman``, +``distro_version`` -> ``semver``) and generate the CLI/API reference pages. +Installing an older release tag drops those deps and breaks the +``python-gardenlinux-lib-cli`` reference during the VitePress build. + +This module rewrites the ``pip install git+.../python-gardenlinux-lib.git@`` +pin in every file that installs the library, using the commit locked in +``repos-config.json``. It is called from ``aggregate.py`` after the lock file is +regenerated (``--update-locks``) so the install pins never drift from the lock. +""" + +import re +from pathlib import Path +from typing import List + +REPO_NAME = "python-gardenlinux-lib" + +# Files whose python-gardenlinux-lib install pin must match repos-config.json. +# Paths are relative to the project root. +INSTALL_PIN_FILES = ( + "requirements.txt", + "Makefile", + ".github/workflows/docs-checks.yml", + ".github/workflows/tests.yml", +) + +# Matches the git ref (tag or commit) after the python-gardenlinux-lib URL. +_INSTALL_RE = re.compile( + r"(git\+https://github\.com/gardenlinux/python-gardenlinux-lib\.git@)[^\s\"']+" +) + + +def sync_install_pins( + project_root: Path, + commit: str, + files: List[str] | None = None, +) -> bool: + """Rewrite python-gardenlinux-lib install pins to *commit*. + + Args: + project_root: Repository root containing the install files. + commit: Commit hash locked in repos-config.json. + files: Optional override of the relative file paths to update + (defaults to :data:`INSTALL_PIN_FILES`). + + Returns: + ``True`` if any file was modified, ``False`` otherwise. + """ + targets = files if files is not None else INSTALL_PIN_FILES + + print(f"Syncing {REPO_NAME} install pins to {commit}") + changed = False + + for rel in targets: + path = project_root / rel + if not path.exists(): + print(f" Skipped (not found): {rel}") + continue + + original = path.read_text(encoding="utf-8") + updated, count = _INSTALL_RE.subn(rf"\g<1>{commit}", original) + + if count == 0: + print(f" Skipped (no install pin): {rel}") + continue + if updated == original: + print(f" Already up to date: {rel}") + continue + + path.write_text(updated, encoding="utf-8") + print(f" Updated {count} pin(s): {rel}") + changed = True + + if not changed: + print("No install pins needed updating.") + return changed diff --git a/src/aggregation/releases.py b/src/aggregation/releases.py index 85bb8e8..308167e 100644 --- a/src/aggregation/releases.py +++ b/src/aggregation/releases.py @@ -287,6 +287,19 @@ def generate_release_docs(docs_dir: Path, existing_gh_tags: set[str]) -> bool: release_file = "maintained-releases.md" release_path = releases_dir / release_file + # The static page (frontmatter, intro, headings) is aggregated from the + # gardenlinux repo via 'github_target_path'. If it was not aggregated (for + # example because the source 'docs/' tree is absent at the pinned commit), + # skip generation with a warning rather than crashing the whole build. + if not release_path.exists(): + print( + f"Warning: {release_path} not found — skipping maintained-releases " + "generation. Ensure the source page is aggregated from the " + "gardenlinux repo (github_target_path frontmatter).", + file=sys.stderr, + ) + return False + # Read existing file and keep only frontmatter and static content # (everything before the generated tables) existing_content = release_path.read_text() @@ -321,6 +334,18 @@ def generate_release_docs(docs_dir: Path, existing_gh_tags: set[str]) -> bool: release_file = "archived-releases.md" release_path = releases_dir / release_file + # As with maintained-releases, the static page is aggregated from the + # gardenlinux repo. Skip gracefully if it was not aggregated. + if not release_path.exists(): + print( + f"Warning: {release_path} not found — skipping archived-releases " + "generation. Ensure the source page is aggregated from the " + "gardenlinux repo (github_target_path frontmatter).", + file=sys.stderr, + ) + print("Release documentation generation complete.") + return True + # Read existing file and keep only frontmatter and static content existing_content = release_path.read_text() lines = existing_content.split("\n")