Coverage: drop docker container, split into two independent builds#76
Merged
Conversation
Without ``--upgrade``, ``pip install xmsconan>=X.Y.Z`` is a no-op whenever the runner image has xmsconan pre-installed at any version satisfying the floor. The xmscore Coverage workflow runs inside ``ghcr.io/aquaveo/conan-gcc13-py3.13:latest`` which bakes in xmsconan, so the step was silently locking every Coverage run to whatever the image happened to carry at build time — not to whatever is on devpi. That was invisible until 2.15.1: the 2.15.0 testing+pybind regression (the CxxTest symbol leak from the previous commit) shipped, the docker image refreshed to 2.15.0, xmscore Coverage ran 2.15.0 from the image, failed, we shipped 2.15.1 with the fix to devpi, xmscore Coverage re-ran — and the pre-installed 2.15.0 still won because ``>=2.14.0`` was already satisfied. The fix never reached xmscore CI. Add ``--upgrade`` and quote the constraint across all nine occurrences in the CI templates (4 in github-ci, 1 in github-coverage, 4 in gitlab-ci). Every CI invocation now resolves the latest xmsconan satisfying the floor — which is the contract the workflow appeared to express in the first place. Downstream xms libraries pick this up by regenerating their CI yamls with ``xmsconan ci`` / ``xmsconan_ci`` once a release containing this change is on devpi. xmscore's Coverage.yaml in particular needs regeneration before the 2.15.1 testing_sources fix can take effect. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Coverage workflow's docker image (conan-gcc13-py3.13) was baking xmsconan into the runner image; ``pip install xmsconan>=X.Y.Z`` then silently no-op'd because the in-image version already satisfied the floor. That locked every Coverage run to whatever xmsconan the image happened to carry — which is how xmscore Coverage kept failing against in-image 2.15.0 even after 2.15.1's fix was on devpi. Remove the ``container:`` block from ``github-coverage.yaml.jinja`` entirely (including the previous xvfb branch). The job now runs on plain ubuntu-latest, sets up Python via actions/setup-python, and pip-installs conan/gcovr/xmsconan on every run. ubuntu-latest currently ships gcc 13.3 which matches the conan profile's ``compiler.version=13``. For libraries that set ``[ci].xvfb = true``, the workflow now does ``sudo apt-get install -y xvfb`` instead of pulling a heavier custom container. ``xmsconan_coverage`` already wraps test execution in ``xvfb-run`` when xvfb is enabled, so no further changes are needed. ``[ci].docker_image`` is no longer honored by Coverage. It still works for the build/deploy workflows in ``github-ci.yaml.jinja``. Updated ``docs/USAGE.md`` §11.4 to reflect this. Test ``test_github_coverage_uses_xvfb_image_when_requested`` is inverted into ``test_github_coverage_apt_installs_xvfb_when_requested`` and asserts there is no ``container:`` directive AND that ``apt-get install -y xvfb`` appears in the rendered workflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three layered fixes to stabilize the Coverage workflow. xmscore Coverage CI was failing for two reasons that compounded:
conan-gcc13-py3.13docker image baked xmsconan in, andpip install xmsconan>=X.Y.Zsilently no-op'd whenever the image's pinned version already satisfied the floor. So the canary was locked to whatever xmsconan the image happened to carry, not what was on devpi.pybind=True + testing=True + Debugcoverage config was structurally fragile — it existed nowhere else in the build matrix, so any change totesting_sourceslinkage or pybind ABI silently broke Coverage. Most recent symptom:undefined symbol: CxxTest::charToStringat pybinddlopenafter commit1d054c2movedtesting_sourcesout of the main library. Issues xmsconan_coverage passes flat filter to build.py; pybind/testing criteria silently dropped #62, After #61/#62 fixed, testing=True + pybind=True still matches zero configs (mutually exclusive fan-outs) #64, _find_coverage_package picks non-deterministic Python version when python_versions has >1 entry #65, xmsconan_coverage builds without --coverage because XMS_COVERAGE isn't in the conan buildenv #69, xmsconan_coverage reports Python 0% because it looks for cov-py.* at the wrong path #71 all clustered around this same shape.1. Coverage goes containerless
The Coverage workflow no longer uses any docker container. It runs directly on
ubuntu-latest, sets up Python viaactions/setup-python@v5, and pip-installs conan / gcovr / xmsconan on every run. ubuntu-latest currently ships gcc 13.3 which matches the conan profile'scompiler.version=13. For libraries that set[ci].xvfb = true, the workflow apt-installs xvfb as a job step instead of pulling a custom X11/GDAL container. This removes the hidden coupling between the runner-image refresh cadence and what xmsconan version the canary actually ran.2.
--upgradeadded to remaining CI templatesgithub-ci.yaml.jinjaandgitlab-ci.yml.jinjastill use docker images for the build/deploy/lint workflows (manylinux compatibility for wheel repair, locked compiler for ABI stability). Those installs gain--upgradeand quoted constraints so they don't silently lock to a baked-in xmsconan when one happens to be in the image.3. Coverage split into two independent builds
Replace the single combined
pybind=True + testing=True + Debugcoverage config with two independent builds:testing=True, pybind=False, Debug— drives CxxTest under--coverage.gcovrreads.gcdafrom this build folder.pybind=True, testing=False, Debug, pinned to onepython_version— drivespytest-covagainst the wheel.cov-py.xml/cov-py-summary.json/coverage-html-pyare copied out of this build folder.xmsconan_coveragerunsbuild.pytwice (sequentially, one job, shared conan cache), locates each package via_find_coverage_package(kind={"testing"|"pybind"}), runs gcovr against the testing folder, and copies pytest-cov artifacts from the pybind folder. The packager no longer emits a coverage-only carve-out — the matrix is asserted to never produce apybind=True + testing=Trueconfig regardless ofXMS_COVERAGE.Coverage number impact: libraries that previously relied on pybind-driven C++ coverage may see their C++ percentage drop, since only CxxTest-reachable code now contributes to
cov-cpp.xml. xmscore is unaffected (cpp_threshold=0); downstream libraries with non-zerocpp_thresholdshould re-baseline against the testing-only build.Downstream propagation
xms libraries pick this up by regenerating CI yamls with
xmsconan cionce 2.15.2 is on devpi. xmscore in particular needs to regenerateCoverage.yamlso the testing_sources fix from 2.15.1 AND the two-build split reach its CI runner.What this drops
conan-gcc13-py3.13runner image for Coverage (was the default).conan-gcc13-x11-gdal-py3.13runner image forci_xvfb=trueCoverage (now apt installs xvfb instead).[ci].docker_imageoverride on the Coverage workflow specifically. It's still honored by build/deploy workflows.XmsConanPackager_coveragecarve-out that flippedtesting=Trueon the Debug+pybind variant whenXMS_COVERAGE=1.If any xms library was relying on libraries pre-baked into those images beyond what apt provides on ubuntu-latest, that library will need to add explicit install steps to its workflow (likely via the existing template extension points).
Documentation updates
docs/USAGE.md§5.7 —[coverage].python_versionrow rewritten to describe the pybind-build pinning.docs/USAGE.md§7.2 —testingoption row clarified as mutually exclusive withpybind=Truein the standard fan-out.docs/USAGE.md§11 — full two-build flow described (testing build → pybind build → gcovr → threshold gate).XMS_COVERAGE=1documented as the Debug+pybind gate-relaxation switch (the testing-only Debug variant is part of the standard fan-out and no longer needs the env var).Release plan
Land as 2.15.2 — version is dynamic via setuptools-scm; tag
2.15.2on master after merge.Test plan
pytest tests/ -m "not integration"→ 536 passed, 1 skipped.test_github_coverage_yaml_generated_when_coverage_true— asserts the generated workflow has NOcontainer:directive, hasactions/setup-python, and usespip install --upgrade "xmsconan>=…".test_github_coverage_apt_installs_xvfb_when_requested— inverted from the old "uses the xvfb docker image" assertion; now confirms xvfb is apt-installed instead.test_pybind_and_testing_are_never_combined_in_one_config— asserts the packager never emits the combined config, with or withoutXMS_COVERAGE.test_build_py_invoked_twice_with_disjoint_filters— assertsrun_coveragerunsbuild.pytwice with disjoint testing/pybind filters.test_gcovr_runs_against_testing_build_folder_not_pybind— asserts gcovr--rootis the testing folder, not the pybind folder.cov-cpp.xml(testing-only) andcov-py.xml(pybind-only) without theCxxTest::charToStringregression.🤖 Generated with Claude Code