From 2e6f4ae2175ff396e17aa31b7cc25d15e754cb26 Mon Sep 17 00:00:00 2001 From: Pierre Raybaut <1311787+PierreRaybaut@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:00:48 +0200 Subject: [PATCH] ci(rtd): install development Sigima for branch and pull request builds Read the Docs installs SigimaX dependencies from PyPI only, so documentation builds fail whenever SigimaX requires a Sigima version that is not released yet (e.g. Sigima >= 1.4.0 on PR #13). Add a pre_install step mirroring the GitHub Actions test workflows: for branch and pull request builds, Sigima is installed from the GitHub branch with the same name as the SigimaX branch, falling back to develop. Tag builds and the main branch keep using PyPI releases. Assisted-by: Claude Opus 5.5 --- .readthedocs.yaml | 3 + scripts/rtd_install_sigima.py | 106 ++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 scripts/rtd_install_sigima.py diff --git a/.readthedocs.yaml b/.readthedocs.yaml index e495f7f..b35710b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,6 +17,9 @@ build: - libxcb-xinerama0 - libxcb-xfixes0 jobs: + pre_install: + # Development builds may require a Sigima version not yet released on PyPI + - "python scripts/rtd_install_sigima.py" pre_build: # Start Xvfb before building docs - "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" diff --git a/scripts/rtd_install_sigima.py b/scripts/rtd_install_sigima.py new file mode 100644 index 0000000..2f76be8 --- /dev/null +++ b/scripts/rtd_install_sigima.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +""" +Install the development version of Sigima for Read the Docs builds. + +SigimaX is developed alongside Sigima: development branches and pull requests +may require a Sigima version which is not yet published on PyPI, so installing +``sigimax[doc]`` from PyPI alone would fail. + +This script mirrors the GitHub Actions test workflows: + +- tag builds and the ``main`` branch: nothing is done, Sigima is installed from + PyPI by the regular ``python.install`` step; +- other branches and pull requests: Sigima is installed from the GitHub branch + with the same name as the SigimaX branch if it exists, otherwise from + ``develop``. The regular ``python.install`` step then keeps this version as it + already satisfies SigimaX requirements. + +It is intended to be run as a ``build.jobs.pre_install`` step and only relies +on the standard library and ``git``. +""" + +from __future__ import annotations + +import os +import subprocess +import sys + +SIGIMA_REPO = "https://github.com/DataLab-Platform/Sigima.git" +SIGIMAX_REPO = "https://github.com/DataLab-Platform/SigimaX.git" +DEFAULT_BRANCH = "develop" +RELEASE_BRANCH = "main" + + +def get_remote_branches(url: str) -> dict[str, str]: + """Return the branches of a remote Git repository. + + Args: + url: Remote repository URL + + Returns: + Mapping of branch names to the commit hash of their head + """ + output = subprocess.run( + ["git", "ls-remote", "--heads", url], + capture_output=True, + text=True, + check=True, + ).stdout + branches = {} + for line in output.splitlines(): + commit, ref = line.split("\t", 1) + branches[ref.removeprefix("refs/heads/")] = commit + return branches + + +def get_sigimax_branch() -> str | None: + """Return the SigimaX branch being built, if it can be determined. + + For pull request builds, Read the Docs only provides the pull request number, + so the branch is the one of the SigimaX repository whose head is the commit + being built. + + Returns: + Branch name, or None for tag builds and pull requests from forks + """ + version_type = os.environ.get("READTHEDOCS_VERSION_TYPE") + if version_type == "branch": + return os.environ["READTHEDOCS_GIT_IDENTIFIER"] + if version_type == "external": + commit = os.environ["READTHEDOCS_GIT_COMMIT_HASH"] + for branch, head in get_remote_branches(SIGIMAX_REPO).items(): + if head == commit: + return branch + return None + + +def main() -> None: + """Install Sigima from GitHub for development builds.""" + version_type = os.environ.get("READTHEDOCS_VERSION_TYPE") + if version_type not in ("branch", "external"): + print(f"Version type {version_type!r}: Sigima will be installed from PyPI") + return + sigimax_branch = get_sigimax_branch() + if sigimax_branch == RELEASE_BRANCH: + print(f"Branch {RELEASE_BRANCH!r}: Sigima will be installed from PyPI") + return + if sigimax_branch in get_remote_branches(SIGIMA_REPO): + sigima_branch = sigimax_branch + else: + sigima_branch = DEFAULT_BRANCH + print(f"SigimaX branch: {sigimax_branch!r} -> Sigima branch: {sigima_branch!r}") + subprocess.run( + [ + sys.executable, + "-m", + "pip", + "install", + "--no-cache-dir", + f"sigima @ git+{SIGIMA_REPO}@{sigima_branch}", + ], + check=True, + ) + + +if __name__ == "__main__": + main()