From a3b1f28ed28b2ed8c0eb4c242c5455ed077b2c0c Mon Sep 17 00:00:00 2001 From: Gage Larsen Date: Tue, 1 Sep 2026 13:45:05 -0600 Subject: [PATCH 1/3] Move the GitLab Windows jobs onto the GLR-UV runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The per-ABI GLR-py310 / GLR-py313 images are gone, replaced by a single GLR-UV image carrying uv and pre-loaded 3.10 / 3.13 / 3.14 interpreters. Those images existed for one reason: to make `python` on PATH the matrix version. The recipe hands CMake `Python3_EXECUTABLE = sys.executable` and the generated CMakeLists.txt requires `find_package(Python3 ... EXACT REQUIRED)`, so the interpreter running conan *is* the ABI being built -- which meant the ABI had to be chosen by picking an image and could not be changed inside the job. That is what PY_TAG and `image: GLR-${PY_TAG}` were for, and both are now gone: the job establishes the interpreter itself with `uv venv --python ${PYTHON_TARGET_VERSION}`, activates it, and installs conan and xmsconan into it with `uv pip install`. GitLab runs a job's script lines as one shell, so the activation carries. `uv --version` runs first so a runner without uv fails on a line that says so rather than four lines later on an install that reads like a packaging problem. `tags: WinVM` is unchanged -- the tag routes to the Windows fleet, `image:` only picks the VM template it starts. Also drops the hard-coded /c/Users/admin from the deploy job's cache snapshot in favor of ${HOME}. The conan home is `~/.conan2`, so that literal was an assumption about the old service account, and under any other one the job shipped an empty artifact and stayed green -- exactly the kind of assumption a move to a different machine has to stop making. Docs: USAGE.md §5.6, §9.x, §10.2 and the troubleshooting list, including two new entries for the failures this shape can produce. --- docs/USAGE.md | 18 +-- tests/test_ci_file_generator.py | 108 +++++++++++++++++- .../ci_templates/gitlab-ci.yml.jinja | 67 ++++++++--- 3 files changed, 167 insertions(+), 26 deletions(-) diff --git a/docs/USAGE.md b/docs/USAGE.md index 5dcb60b..0cc2bba 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -454,10 +454,10 @@ it did before. Why three lists instead of one: -- **Windows** interpreters all come from `actions/setup-python` (GitHub) or a - `GLR-pyXYZ` runner tag (GitLab), so a version costs only runner minutes. 3.10 - lives here because the desktop products (GMS/SMS/WMS) consume a 3.10 Windows - wheel; nothing else needs it. +- **Windows** interpreters all come from `actions/setup-python` (GitHub) or + `uv venv --python` on the `GLR-UV` runner (GitLab), so a version costs only + runner minutes. 3.10 lives here because the desktop products (GMS/SMS/WMS) + consume a 3.10 Windows wheel; nothing else needs it. - **macOS** is cheap to fan out too, but inherits nothing from the Windows list — adding 3.10 for the desktop products should not triple the mac matrix. - **Linux** runs in a container, and each version needs a published @@ -501,9 +501,9 @@ several wheels locally, invoke `python build.py` once per version (or construct the resolved coverage ABI (§5.7) before invoking `build.py`, so a local coverage run needs no manual export — and an ambient value does not win over `build.toml`. -Either way, a local pybind build only works **from an interpreter of the version being built**: the recipe points CMake at `sys.executable` and the generated `CMakeLists.txt` requires that exact version. CI never notices because `actions/setup-python` supplies a matching interpreter; on a workstation you supply it, which is why the VS2019 wheel workflow is one run per Python version from a virtual environment of that version (§16.8). +Either way, a local pybind build only works **from an interpreter of the version being built**: the recipe points CMake at `sys.executable` and the generated `CMakeLists.txt` requires that exact version. CI never notices because it arranges one: `actions/setup-python` on GitHub, `uv venv --python ${PYTHON_TARGET_VERSION}` on the GitLab Windows jobs (§10.2). On a workstation you supply it, which is why the VS2019 wheel workflow is one run per Python version from a virtual environment of that version (§16.8). -> **Runner / image expectations.** A Windows opt-in assumes the matching `GLR-pyXYZ` GitLab runner tag exists (`GLR-py310`, `GLR-py314`). A Linux opt-in assumes the matching `conan-gcc13-py` image exists **and is readable by CI** — on GHCR the 3.13 image is public while 3.14 is private, and the generated `container:` block pulls anonymously, so a private image needs its visibility flipped (or a `credentials:` stanza added) before its leg can start. +> **Runner / image expectations.** On GitLab a Windows opt-in assumes the `GLR-UV` image can supply the interpreter — it carries `uv` and pre-loaded 3.10 / 3.13 / 3.14, and `uv venv --python` downloads anything else it is asked for, so a version outside that set costs a download on every job rather than failing. A Linux opt-in assumes the matching `conan-gcc13-py` image exists **and is readable by CI** — on GHCR the 3.13 image is public while 3.14 is private, and the generated `container:` block pulls anonymously, so a private image needs its visibility flipped (or a `credentials:` stanza added) before its leg can start. --- @@ -607,7 +607,7 @@ The generated jobs follow the pattern: - `[ci].split_tests` is also rejected when the `[filter]` table leaves no Linux testing configuration (`options.testing = false`, or a `pybind = true` pin). Splitting makes the build job export `XMS_SKIP_CXX_TESTS=1`, so with no runner staged there is nowhere left for the suite to run — the pipeline would pass having tested nothing. Note that `[ci].build_types` is not the axis here: a `pybind = true` pin keeps Release configurations while staging no runner at all. - **One test job per testing configuration, each naming its own.** `[ci].split_tests` emits a `Run C++ Tests -