Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/.github/workflows/ @skilledwolf
/.github/scripts/ @skilledwolf
/.github/ci-matrix/ @skilledwolf
/.github/dependabot.yml @skilledwolf
/CMakeLists.txt @skilledwolf
/pyproject.toml @skilledwolf
/config/FindBoostForALPS.cmake @skilledwolf
15 changes: 15 additions & 0 deletions .github/RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Releasing pyalps

1. Update `project.version` in `pyproject.toml` and merge the change through CI.
2. Create a GitHub release whose tag is exactly `v<project.version>`.
3. Publish the GitHub release. Draft releases do not publish packages.
4. Approve the protected `pypi` environment deployment after the source
distribution and all wheels pass verification.

The release workflow builds one source distribution, then builds every wheel
from that exact archive. Manual dispatch is build-only and can be used to test
release packaging without obtaining a PyPI identity token.

PyPI Trusted Publishing must be restricted to repository `skilledwolf/ALPS`,
workflow `build_wheels.yml`, and environment `pypi`. The publish action emits
PEP 740 attestations by default.
70 changes: 29 additions & 41 deletions .github/ci-matrix/README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,31 @@
# CI build matrix

`linux.json` and `macos.json` are the single source of truth for the ALPS build
matrix. They are consumed by the reusable workflow
[`build-alps.yml`](../workflows/build-alps.yml), which filters entries by tier:

- **`"tier": "quick"`** — runs on every pull request and push to master
([`ci.yml`](../workflows/ci.yml)). These entries cover the *boundaries* of each
axis: oldest/newest GCC, oldest/newest Clang, newest C++ standard, a combined
all-minimums job (oldest Boost + oldest Python + the C++17 floor), and one
macOS arm64 + one macOS x86_64 job.
- **`"tier": "full"`** — additionally runs in the weekly sweep and on manual
dispatch ([`full-matrix.yml`](../workflows/full-matrix.yml)): the interior of
each version axis (intermediate compilers, Boost, Python, C++ standards) plus
extra macOS targets. The full tier is a superset — it includes the quick
entries too.

Rationale: intermediate versions almost never break independently — if the
oldest and newest compiler both pass, the ones in between failing alone is
rare. Boundaries gate PRs; the exhaustive sweep catches ecosystem drift
(new compiler/Boost/Python releases) on a schedule instead of taxing every PR.

Entry fields: `label` (job name + ccache key — keep unique), `tier`, `os`,
`comp_pack` (apt/brew package spec), `c_compiler`/`cxx_compiler`, `c_version`
(Linux only), `cxx_stdlib` (macOS only), `py_version`, `boost_version`
(e.g. `91` = Boost 1.91.0), optional `cxx_standard` (defaults to 17, the
floor; passed to CMake as -DCMAKE_CXX_STANDARD).

Optional per-entry extras (Linux only):

- `"sanitize": "undefined"` or `"address,undefined"` — build and test with
GCC sanitizers (-fno-sanitize-recover=all, so findings fail tests).
- `"permissive": false` — drop -fpermissive; the canary tracking its removal.
- `"experimental": true` — the job reports failures without failing the run
(continue-on-error). Used for sanitizers and canaries while their findings
are being burned down; flip to strict once green.

Canary entries (`py-next-canary`, `no-fpermissive`) live in the full tier to
catch ecosystem drift early: a yellow weekly job instead of a red release
week. When a Boost beta is available, add a canary entry for it the same way.

Axis sweeps hold everything else at the baseline: ubuntu-24.04, gcc-14,
Python 3.14, Boost 1.91, C++17.
`linux.json` and `macos.json` are the single source of truth for source-build
coverage. The reusable workflow combines both files and filters entries by tier.

- **`quick`** is the pull-request gate: one all-minimums Linux build, current
GCC, current Clang with the newest C++ mode, and current macOS arm64.
- **`full`** runs weekly and on demand. It adds the supported Clang floor,
next compilers, Linux arm64, macOS Intel/current-OS canaries, sanitizers,
next Python, and a real build without legacy permissive mode.

The quick tier contains four builds; the full tier contains fourteen. We test
support boundaries and meaningful platform combinations rather than every
interior compiler, Boost, Python, and C++ version. Interior versions share the
same language and ABI boundaries and previously consumed most runner capacity
without independently useful signal.

Every Boost entry includes the SHA-256 published beside the archive on
`archives.boost.io`. The build passes the extracted directory as
`Boost_SRC_DIR`, which is the variable consumed by `FindBoostForALPS.cmake`.
The all-minimums combination constrains NumPy below 2 because Boost releases
before 1.87 do not support the NumPy 2 C API.

Only quick entries set `remote_cache: true`. Their ccache archives are restored
on pull requests but saved only from `master`, with one immutable generation per
ISO week. Scheduled compatibility entries intentionally build cold, preventing
the full matrix from creating dozens of disposable caches per run.

Canaries are strict. A scheduled sanitizer, next-toolchain, next-Python, or
no-permissive failure fails the compatibility workflow so it cannot remain a
silent yellow result.
240 changes: 199 additions & 41 deletions .github/ci-matrix/linux.json
Original file line number Diff line number Diff line change
@@ -1,43 +1,201 @@
[
{ "label": "gcc-12-ubuntu22", "tier": "full", "os": "ubuntu-22.04", "comp_pack": "gcc-12 g++-12", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 12, "py_version": "3.14", "boost_version": 91 },
{ "label": "gcc-14-ubuntu24", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-15-ubuntu22","tier": "full", "os": "ubuntu-22.04", "comp_pack": "clang-15", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 15, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-18-ubuntu24","tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-18", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 18, "py_version": "3.14", "boost_version": 91 },

{ "label": "gcc-11", "tier": "quick", "os": "ubuntu-22.04", "comp_pack": "gcc-11 g++-11", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 11, "py_version": "3.14", "boost_version": 91 },
{ "label": "gcc-13", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-13 g++-13", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 13, "py_version": "3.14", "boost_version": 91 },
{ "label": "gcc-15", "tier": "quick", "os": "ubuntu-24.04", "comp_pack": "gcc-15 g++-15", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 15, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-14", "tier": "quick", "os": "ubuntu-22.04", "comp_pack": "clang-14", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 14, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-16", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-16", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 16, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-17", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-17", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 17, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-19", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-19", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 19, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-20", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-20", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 20, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-21", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "clang-21", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 21, "py_version": "3.14", "boost_version": 91 },
{ "label": "clang-22", "tier": "quick", "os": "ubuntu-24.04", "comp_pack": "clang-22", "c_compiler": "clang", "cxx_compiler": "clang++", "c_version": 22, "py_version": "3.14", "boost_version": 91 },

{ "label": "boost-1.76", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 76 },
{ "label": "boost-1.81", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 81 },
{ "label": "boost-1.86", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 86 },
{ "label": "boost-1.87", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 87 },
{ "label": "boost-1.88", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 88 },
{ "label": "boost-1.89", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 89 },
{ "label": "boost-1.90", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 90 },

{ "label": "py3.10", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.10", "boost_version": 91 },
{ "label": "py3.11", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.11", "boost_version": 91 },
{ "label": "py3.12", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.12", "boost_version": 91 },
{ "label": "py3.13", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.13", "boost_version": 91 },

{ "label": "cxx20", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91, "cxx_standard": 20 },
{ "label": "cxx23", "tier": "quick", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91, "cxx_standard": 23 },

{ "label": "minimums", "tier": "quick", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.10", "boost_version": 76, "cxx_standard": 17 },

{ "label": "arm64-gcc-14", "tier": "full", "os": "ubuntu-24.04-arm", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91 },

{ "label": "ubsan", "tier": "quick", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91, "sanitize": "undefined", "experimental": true },
{ "label": "asan-ubsan", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91, "sanitize": "address,undefined", "experimental": true },

{ "label": "py-next-canary", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.15-dev", "boost_version": 91, "experimental": true },
{ "label": "no-fpermissive", "tier": "full", "os": "ubuntu-24.04", "comp_pack": "gcc-14 g++-14", "c_compiler": "gcc", "cxx_compiler": "g++", "c_version": 14, "py_version": "3.14", "boost_version": 91, "permissive": false, "experimental": true }
{
"label": "minimums",
"tier": "quick",
"platform": "linux",
"os": "ubuntu-22.04",
"comp_pack": "gcc-11 g++-11",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 11,
"py_version": "3.10",
"numpy_spec": "numpy>=1.26,<2",
"boost_version": 76,
"boost_sha256": "7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": true
},
{
"label": "gcc-current",
"tier": "quick",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": true
},
{
"label": "clang-current-cxx23",
"tier": "quick",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "clang-18",
"c_compiler": "clang",
"cxx_compiler": "clang++",
"c_version": 18,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 23,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": true
},
{
"label": "clang-floor",
"tier": "full",
"platform": "linux",
"os": "ubuntu-22.04",
"comp_pack": "clang-14",
"c_compiler": "clang",
"cxx_compiler": "clang++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "gcc-next",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-15 g++-15",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 15,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "clang-next",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "clang-22",
"c_compiler": "clang",
"cxx_compiler": "clang++",
"c_version": 22,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "linux-arm64",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04-arm",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "ubsan",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "undefined",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "asan-ubsan",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "address,undefined",
"permissive": true,
"allow_prereleases": false,
"remote_cache": false
},
{
"label": "py-next",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.15-dev",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": true,
"allow_prereleases": true,
"remote_cache": false
},
{
"label": "no-fpermissive",
"tier": "full",
"platform": "linux",
"os": "ubuntu-24.04",
"comp_pack": "gcc-14 g++-14",
"c_compiler": "gcc",
"cxx_compiler": "g++",
"c_version": 14,
"py_version": "3.14",
"boost_version": 91,
"boost_sha256": "5734305f40a76c30f951c9abd409a45a2a19fb546efe4162119250bbe4d3a463",
"cxx_standard": 17,
"sanitize": "",
"permissive": false,
"allow_prereleases": false,
"remote_cache": false
}
]
Loading
Loading