The Lint Source-of-Truth and Pinned Toolchain Release
Three independent fixes to the generated build/CI files, plus two generation-time quality-of-life improvements. Nothing in the 2.15.2 two-build coverage flow changes.
What changed
1. .flake8 is the only lint source of truth
The generated GitHub flake job ran flake8 --isolated with the full settings list spelled out on the command line, so the .flake8 that xmsconan gen renders was never read by CI. The two copies had drifted in both directions:
.flake8ignoredB028andW503; the CI command line did not..flake8excludeddocs/source/conf.py; the repos actually keep it atpydocs/source/conf.py, which only the CI command line excluded.
A clean local run therefore did not imply a clean CI run. The flake job now installs xmsconan, runs xmsconan_gen build.toml to render .flake8, and runs plain flake8 _package — the same shape GitLab's Lint job already used. .flake8.jinja excludes both conf.py locations and drops isolated = true, which is meaningless inside a config file.
Lint settings now live in exactly one place: .flake8.jinja.
2. Build and deploy jobs pin the toolchain
xmsconan>=<version>becomesxmsconan==<version>in every build/deploy/lint step of both the GitHub and GitLab templates.pip install conanbecomespip install "conan~=2.31.0".
xmsconan owns the Conan profiles and Conan computes package_ids, so either one floating silently shifts every package_id and detaches a repo from the binaries already published to the remote. The GitHub Coverage.yaml workflow is the deliberate exception and still floats on >= — it is the canary that surfaces xmsconan regressions early (see 2.15.2).
3. Dead emscripten include dropped
CMakeLists.txt.jinja included emscriptenbuildinfo.cmake under IS_EMSCRIPTEN_BUILD, but xmsconan has never generated that file and no repo ships one, so the branch could only ever fail. Removed along with the IS_EMSCRIPTEN_BUILD cache variable. condabuildinfo.cmake is unaffected.
4. Visual Studio filter folders mirror the on-disk tree
CMakeLists.txt.jinja gained a single source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ...) call at directory scope, so Visual Studio filter folders match the on-disk directory structure across every target — static library, test runner, and pybind module — in all build configurations. One directory-scope call is enough because source_group registers per file, not per target. The variables are deliberately unquoted: a quoted "${var}" with an empty var would expand to a literal empty-string filename and fail the TREE-root check.
5. Clearer error for a missing build.toml key
render_template_with_toml wraps jinja's UndefinedError as ValueError('Missing field in build.toml: ...'), so a missing key reads as an instruction to add the key rather than jinja's bare 'foo' is undefined.
Migration
xms libraries pick this up by regenerating with xmsconan ci and xmsconan gen and committing the result.
- Generate CI from a released xmsconan. With
==, a workflow generated from an unreleased working copy pins a version that is not on devpi (e.g.2.15.3.dev3) and CI will fail to install it. Installxmsconan==2.15.3before regenerating. - Upgrades are explicit from here on. Picking up a new xmsconan or Conan means re-running
xmsconan ci(and bumping theconan~=value in the templates) and committing the result — a reviewable change instead of a silent one. - Lint parity, not stricter lint. The regenerated GitHub
flakejob applies.flake8as written, which is slightly more permissive than the old inline arguments (B028andW503are ignored) and excludes bothconf.pylocations. A repo that was clean locally but red in CI on those codes goes green; no new findings are expected.
Documentation
docs/USAGE.md§10.1 — theflakejob's contract: lint settings live in.flake8.jinjaand are never passed on the command line.docs/USAGE.md§10.3 (new) — pinned tool versions table, theCoverage.yamlcanary exception, and the two consequences of==pinning.
Verification
- 539 unit tests pass (5 skipped); flake8 clean with the CI plugin set.
- New tests:
test_github_flake_job_uses_generated_flake8_configandtest_ci_pins_conan_version(CI templates),test_flake8_excludes_both_sphinx_conf_locationsandtest_cmakelists_has_no_emscripten_branch(build files),test_cmake_template_emits_source_group_tree(pins the unquotedsource_groupshape), andtest_render_raises_clear_error_for_missing_toml_key. - The two existing tests that asserted the old
xmsconan>=contract were updated to==.