Skip to content

Update build, CI and dependencies#1280

Merged
carlosggarcia merged 15 commits intoLSSTDESC:fixci_setuptoolsfrom
marcpaterno:fixci_setuptools
Feb 27, 2026
Merged

Update build, CI and dependencies#1280
carlosggarcia merged 15 commits intoLSSTDESC:fixci_setuptoolsfrom
marcpaterno:fixci_setuptools

Conversation

@marcpaterno
Copy link
Contributor

Description

This PR modernizes the CI infrastructure and resolves CI failures caused by setuptools compatibility issues. The primary fix addresses setuptools issue #5174 by removing the obsolete workaround that was downgrading setuptools to <81, which was preventing the CI from running successfully. The local test environment confirmed that setuptools 82.0.0 works correctly with isitgr 1.0.5 and classy 3.3.4.0.

Additional improvements include:

  • Update GitHub Actions to current versions (checkout v2/v3→v4, setup-python v2→v5, cache v3→v4)
  • Add Python version matrix testing for Python 3.11, 3.12, 3.13, and 3.14
  • Enable manual workflow triggering via workflow_dispatch with customizable parameters
  • Implement native concurrency control to replace deprecated cancel-workflow-action
  • Add pip package caching to reduce CI build times
  • Switch from Anaconda channel to conda-forge to avoid licensing issues
  • Migrate PyPI publishing to trusted publishing with id-token
  • Add comprehensive CONTRIBUTING.md with development environment setup, testing instructions, and debugging guidance
  • Tighten scipy version constraint (<1.14) to avoid compatibility breakages with velocileptors
  • Update numpy constraint to <2.4 due to fast-pt's use of the deprecated np.trapz

New dependencies: wheel and cython<3 (required for building classy)

PyPI publishing issues

This PR proposes changing from the use of an API token stored as a GitHub secret (PYPI_PYCCL_UPLOAD) to using PyPI's recommended "Trusted Publishing".

Someone with PyPI project admin/owner access must configure the trusted publisher on PyPI before this workflow will work. This is typically either:

  • The project maintainers, or
  • Anyone with "Owner" or "Maintainer" role on the pyccl PyPI project

To register, someone needs to:

  1. Log into PyPI
  2. Go to the pyccl project settings
  3. Navigate to "Publishing" → "Add a new publisher"
  4. Configure the trusted publisher with:
    • Owner: The GitHub organization/username (e.g., LSSTDESC)
    • Repository name: CCL
    • Workflow name: publish.yml
    • Environment name: (leave blank unless using GitHub environments, which does not seem necessary)

This must be done before the next release, otherwise the PyPI publish step will fail.

I think this part of the PR can be reverted without damage to the rest of the PR.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Replace deprecated GitHub Actions versions and update build
processes. Migrate from styfle/cancel-workflow-action to native
concurrency feature for canceling redundant builds. Update
checkout actions from v2/v3 to v4, setup-python from v2 to v5,
and cache from v3 to v4. Switch PyPI publishing to trusted
publishing with id-token and update build process from setup.py
to python -m build.

Add permissions sections to all workflows and fix macOS
environment variable handling by using GitHub ENV syntax instead
of shell exports. Remove legacy commented code and update cache
key generation.

Add comprehensive CONTRIBUTING.md with development environment
setup guide for both conda and manual setup, testing instructions,
and debugging guidance. Add .gitignore files to exclude generated
_version.py and notebook conversions.
Add two new steps to the CI workflow to cache pip packages between
runs. This reduces build time by reusing downloaded packages across
multiple CI jobs and re-runs.

The new steps retrieve the pip cache directory and use GitHub Actions
cache@v4 to store and restore it, keyed on the environment files and
setup.py to ensure cache validity.
The CI workflow now tests against Python versions 3.11, 3.12, 3.13,
and 3.14 explicitly. The setup-miniconda step now uses the
matrix-specified Python version, and cache keys for both conda and
pip environments are now versioned by Python version to prevent
cache conflicts.
Enable manual triggering of the CI workflow with customizable
parameters. Developers can now test specific Python versions
and operating systems without pushing code to the repository.

The workflow_dispatch event accepts two inputs: python-version
to test individual versions and os to select ubuntu-latest,
macos-latest, or all platforms. The matrix strategy was made
dynamic to respect these inputs.

Added documentation in CONTRIBUTING.md explaining how to
manually trigger workflows via GitHub Web Interface and CLI,
with practical use cases for testing specific configurations.
The main branch does not exist; this project uses the older
standard name, master.
Tighten scipy bound and add dependency update instructions

Update environment.yml to require scipy < 1.14 to avoid recent
compatibility breakages with velocileptors. Remove the obsolete
channel_priority line. Add a new "Updating dependencies" section to
CONTRIBUTING.md that documents how to update the conda environment,
reinstall pip-listed packages, and recreate the test environment for
contributors.
The separate isitgr and classy installation steps in the CI
workflow were redundant because both packages are already specified
in .github/environment.yml. More importantly, the isitgr step was
downgrading setuptools from 82.0.0 to <81 based on an outdated
workaround for setuptools issue #5174.

The local test environment successfully uses setuptools 82.0.0 with
isitgr 1.0.5 and classy 3.3.4.0, proving that the setuptools
downgrade is unnecessary. The CI now relies entirely on
environment.yml for package versions, matching the working local
configuration.
Copilot AI review requested due to automatic review settings February 12, 2026 15:49
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the CI/CD infrastructure to address setuptools compatibility issues (specifically issue #5174) and updates GitHub Actions to current versions. The changes remove an obsolete setuptools version pinning workaround that was preventing CI from running with modern setuptools versions (82+), and update the test infrastructure to support Python 3.11-3.14 across Ubuntu and macOS.

Changes:

  • Update GitHub Actions (checkout v2/v3→v4, setup-python v2→v5, cache v3→v4) and add Python version matrix (3.11-3.14)
  • Migrate PyPI publishing to trusted publishing and modernize build process using python -m build
  • Remove obsolete setuptools version pinning, add pip caching, and update dependency constraints (scipy <1.14, numpy <2.4)

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.github/workflows/ci.yml Updated GitHub Actions versions, added Python 3.11-3.14 matrix testing, implemented workflow_dispatch for manual triggers, native concurrency control, pip caching, and switched to conda-forge-only channel
.github/workflows/publish.yml Migrated to trusted publishing (OIDC), updated actions versions, modernized build process with python -m build
.github/environment.yml Removed setuptools <82 constraint, added nodefaults to conda channels, updated numpy/scipy constraints with documentation, added wheel and cython<3 dependencies
CONTRIBUTING.md Added comprehensive development guide covering environment setup, testing, debugging, CI workflow manual triggering, and dependency updates
pyccl/.gitignore Added _version.py (auto-generated by setuptools_scm)
examples/.gitignore Added Benchmark_Comparisons.py (already present, no change in functionality)
Comments suppressed due to low confidence (1)

.github/workflows/publish.yml:35

  • The workflow is configured for trusted publishing (with id-token: write permission) but still uses the old password-based authentication. When using trusted publishing, the "password" field should be removed entirely. The pypa/gh-action-pypi-publish action will automatically use the OIDC token when id-token permission is granted and no password is provided.
    - name: Publish to PyPI
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        password: ${{ secrets.PYPI_PYCCL_UPLOAD }}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@carlosggarcia carlosggarcia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, thanks @marcpaterno!

I left a few comments above. Some extra comments:

  • Maybe we can bump the python version to 3.10, since the tests are going to be run from there. Here:
    requires-python = ">=3.8"
  • In the same file, maybe we can add other dependencies. At the moment we only list numpy, but scipy it's also needed and probably others.

fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest]
os: ${{ (github.event.inputs.os == 'all' || github.event.inputs.os == '') && fromJSON('["macos-latest", "ubuntu-latest"]') || fromJSON(format('["{0}"]', github.event.inputs.os)) }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the way Matt Kwiecien implemented this in TJPCov. I think it's cleaner. See https://github.com/LSSTDESC/TJPCov/blob/33299d43a5aad13c93669ab88cd9f51e434ab305/.github/workflows/ci.yaml#L44-L48

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution used in TJPCov is simpler to look at, but lacks flexibility that this implementation has. Specifically, this implementation allows use of gh workflow to select a specific python version, or a specific OS, in any combination (e.g. only Ubuntu, but all python versions). The simpler configuration in TJPCov only allows gh workflow ... to run the full matrix.

Let me know if this is enough of a reason to keep the current configuration, or if you would rather lose the flexibility and have the simpler configuration as in TJPCov.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will always want to test all python versions with all OS. I'd advocate for simplicity also to keep the maintenance simple for possible future collaborators. But I can be convinced otherwise if you have found such flexibility very useful.

- pip:
#- classy<3
# - isitgr<=1.0.2 # Done in ci.yml to avoid issues with pkg_resources in setuptools 82
- classy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though it seems to run with the latest version of classy. I'd add a comment saying that the benchmarks were generated with 2.9.4, in case they cause problems in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to get the build to work with an older classy, but that runs into trouble.
It requires a very old cython and a long-unsupported old version of numpy.

With the new version of classy, there are failing benchmark tests. I do not know whether the failures are due to the new version of classy. Determining the cause of the failures will take more CCL expertise than I have.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the logs and the fails come from the MG tests, so it's related to isitgr. @gqcristhian or @c-d-leonard might know how to regenerate the benchmark data?

Consolidate developer documentation into readthedocs source files and
reference them from CONTRIBUTING.md to reduce duplication. Update
project requirements to Python 3.10+ and add missing build dependencies
to pyproject.toml.

Add a Makefile to streamline local package build testing and cleaning.
Update CI configuration to test Python 3.10. Standardize commands for
running tests and benchmarks with OMP_NUM_THREADS set to 2.

Update environment.yml with version constraints and comments.
@marcpaterno
Copy link
Contributor Author

The failing checks are some of the benchmarks. Some of these may be due to the newer versions of classy, isitgr and classy.
The classy version moved from 2.9.4 to 3.3.4.0; the newer version is needed to avoid requiring ancient versions of cython and numpy (which would be incompatible with many other things, among them firecrown).
The isitgr version moved from 1.0.2 to 1.0.5; this allows a build with newer setuptools. The downgrade of setuptools to build the older isitgr was the source of other CI build failures.

I do not have the required expertise to determine whether the benchmark failures are signs of meaningful physics output differences, or are innocuous.

Copy link
Collaborator

@carlosggarcia carlosggarcia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work! I think the error comes from the update of isitgr. Maybe @c-d-leonard or @gqcristhian can have a look.

I left just 2 other minor comments.

After completing the :ref:`devinstall`, you can change the ``Python`` library
in your local copy of CCL. Any changes you make will be visible in ``Python``
after you restart your interpreter. A typical workflow is to make some change,
rerun a failing benchmark or unit test, etc. until you've completed your new
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep this line

@@ -0,0 +1,35 @@
.PHONY: test-build clean
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this addition.

@carlosggarcia
Copy link
Collaborator

carlosggarcia commented Feb 13, 2026

I've updated benchmarks/test_power_nu.py to make it work with any version of CLASS. Instead of using pre-generated data, now it generates it on the fly. The tests pass. The remaining failing ones are related to isitgr and @gqcristhian is looking at them.

@carlosggarcia carlosggarcia merged commit 171f5f1 into LSSTDESC:fixci_setuptools Feb 27, 2026
2 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants