Skip to content

BLD: add the actions #1

BLD: add the actions

BLD: add the actions #1

Workflow file for this run

name: Publish sdist and wheels
env:
# A tag or branch name or a commit hash for the scipy/scipy repo, for which
# to build wheels. This is normally set to `main` in the main branch of this
# repo, and to a tag name (e.g., `v2.3.2`) on a release branch.
SOURCE_REF_TO_BUILD: main
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# │ │ │ │ │
- cron: "9 9 * * MON"
pull_request:
branches:
- main
- maintenance/**
push:
branches:
- main # FOR TESTING ONLY
workflow_dispatch:
inputs:
environment:
description: Which PyPI environment to upload to, if any
required: true
type: choice
options: ["none", "testpypi", "pypi"]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build_wheels:
name: BLD > ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }}-${{ matrix.buildplat[3] }}
runs-on: ${{ matrix.buildplat[0] }}
strategy:
# Ensure that a wheel builder finishes even if another fails
fail-fast: false
matrix:
# Github Actions doesn't support pairing matrix values together, let's improvise
# https://github.com/github/feedback/discussions/7835#discussioncomment-1769026
buildplat:
# should also be able to do multi-archs on a single entry, e.g.
# [windows-2025, win*, "AMD64 x86"]. However, those two require a different compiler setup
# so easier to separate out here.
- [ubuntu-24.04, manylinux, x86_64, "", ""]
- [ubuntu-24.04, musllinux, x86_64, "", ""]
- [ubuntu-24.04-arm, manylinux, aarch64, "", ""]
- [ubuntu-24.04-arm, musllinux, aarch64, "", ""]
- [macos-13, macosx, x86_64, openblas, "10.14"]
- [macos-15-intel, macosx, x86_64, accelerate, "14.0"]
- [macos-14, macosx, arm64, openblas, "12.3"]
- [macos-14, macosx, arm64, accelerate, "14.0"]
- [windows-2025, win, AMD64, "", ""]
- [windows-11-arm, win, ARM64, "", ""]
python: [["cp311", "3.11"], ["cp312", "3.12"], ["cp313", "3.13"], ["cp313t", "3.13"], ["cp314", "cp314"], ["cp314t", "cp314"]]
# python[0] is used to specify the python versions made by cibuildwheel
steps:
- name: Checkout scipy-release
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Checkout scipy
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: scipy/scipy
ref: ${{ env.SOURCE_REF_TO_BUILD }}
path: scipy-src
submodules: true
persist-credentials: false
# the version of python we'll run cibuildwheel with
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: 3.13
- name: win_amd64 - install rtools
if: ${{ matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'AMD64' }}
run: |
# mingw-w64
choco install rtools -y --no-progress --force --version=4.0.0.20220206
echo "c:\rtools40\ucrt64\bin;" >> $env:GITHUB_PATH
- name: Set environment variables for ARM64
if: matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'ARM64'
run: |
echo "CC=clang-cl" >> $env:GITHUB_ENV
echo "CXX=clang-cl" >> $env:GITHUB_ENV
echo "FC=flang" >> $env:GITHUB_ENV
echo "TARGET_ARCH=${{ matrix.buildplat[2] }}" >> $env:GITHUB_ENV
- name: Set up Flang and pkgconf for ARM64
if: matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'ARM64'
uses: ./.github/windows_arm64_steps
- name: pkg-config-for-win
if: runner.os == 'windows'
run: |
choco install -y --no-progress --stoponfirstfailure --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite
$CIBW = "${{ github.workspace }}/.openblas"
# pkgconfig needs a complete path, and not just "./openblas since the
# build is run in a tmp dir (?)
# It seems somewhere in the env passing, `\` is not
# passed through, so convert it to '/'
$CIBW = $CIBW.replace("\","/")
echo "CIBW_ENVIRONMENT_WINDOWS=PKG_CONFIG_PATH=$CIBW" >> $env:GITHUB_ENV
# the macOS matrix is complicated.
# - arm64, accelerate, >=14.0
# The easiest of them all (sort of). However, if you wish to target 14 you
# can only build on macos-14 with the system compiler. If you try building on
# macos-15 there are libraries with a minimum target of 15. Presumably when
# the macos-14 is dropped we'll need to customise the compiler a bit.
# In addition, we can't use Accelerate for < 14 because the library had bugs.
# This means OpenBLAS has to be used.
# - x86_64, accelerate, >=14.0
# Complicated because x86_64 is only available on the macos-15-intel image.
# - x86_64, openblas, "10.14"
# Complicated because x86_64 is only available on the macos-15-intel image.
# Needs an older compiler.
# - arm64, openblas, "12.3"
# Complicated because MACOS_DEPLOYMENT_TARGET has to be set to 12.3 (there's
# some reason why we don't support <12.3), which results in 12_3 in the wheel
# name. This is illegal, so we have to change the wheel name to 12_0 after
# the build.
# OpenBLAS is also complicated because the `delocate` step tries
# to copy two libgfortran libraries into the wheel, and falls over. This
# necessitates using install_name_tool on the scipy_openblas32 dylibs.
# The libraries are also built with an older version of gfortran (11), which
# requires installation of that version. Whilst this version is available
# from homebrew, it doesn't come with an old enough deployment target.
# We therefore have to jump through hoops to install a community packaged
# compiler.
- name: Setup macOS
if: startsWith( matrix.buildplat[0], 'macos-' )
run: |
if [[ ${{ matrix.buildplat[3] }} == 'accelerate' ]]; then
echo CIBW_CONFIG_SETTINGS=\"setup-args=-Dblas=accelerate\" >> "$GITHUB_ENV"
# use preinstalled gfortran for Accelerate builds
ln -s $(which gfortran-13) gfortran
export PATH=$PWD:$PATH
echo "PATH=$PATH" >> "$GITHUB_ENV"
# Builds with Accelerate only target macOS>=14.0
CIBW_ENV="CIBW_ENVIRONMENT_MACOS=MACOSX_DEPLOYMENT_TARGET=14.0 INSTALL_OPENBLAS=false"
else
# use conda-forge compilers the difficult targets
INSTALL_DIR=/Users/runner/miniforge3
wget -q -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
# Make the installer executable
chmod +x Miniforge3.sh
# Run the installer in batch mode (-b) and specify the installation prefix (-p)
# The -u flag is for updating an existing installation if it exists
./Miniforge3.sh -b -u -p "${INSTALL_DIR}"
source "${INSTALL_DIR}/etc/profile.d/conda.sh"
conda init
conda create -q -y -n build compilers
echo "conda activate build" >> $HOME/.bash_profile
cat $HOME/.bash_profile
CIBW_ENV="CIBW_ENVIRONMENT_MACOS=PKG_CONFIG_PATH=$PWD/.openblas \
MACOSX_DEPLOYMENT_TARGET=${{ matrix.buildplat[4] }}"
fi
echo "$CIBW_ENV" >> $GITHUB_ENV
PREFIX=DYLD_LIBRARY_PATH="\$(dirname \$(gfortran --print-file-name libgfortran.dylib))"
CIBW="$PREFIX delocate-wheel -v $EXCLUDE --require-archs {delocate_archs} -w {dest_dir} {wheel}"
echo "CIBW_REPAIR_WHEEL_COMMAND_MACOS=$CIBW" >> $GITHUB_ENV
- name: Build Wheels
shell: bash -el {0}
run: |
pip install cibuildwheel
export CIBW_BUILD=${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}*
export CIBW_ARCHS=${{ matrix.buildplat[2] }}
export CIBW_ENABLE="cpython-freethreading cpython-prerelease"
cibuildwheel --output-dir=dist --config-file=cibuildwheel.toml scipy-src
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
path: ./dist/*.whl
name: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }}-${{ matrix.buildplat[3] }}-${{ matrix.buildplat[4] }}
# We upload nightlies only on cron job runs, so it doesn't overlap with
# builds from which we publish to PyPI - we don't want these extra
# dependencies when building release artifacts.
- name: install micromamba
# win-arm64 is unsupported by micromamba at the moment
if: github.event_name == 'schedule' && matrix.buildplat[1] != 'win_arm64'
uses: mamba-org/setup-micromamba@b09ef9b599704322748535812ca03efb2625677b # v2.0.5
with:
# For installation of anaconda-client, required for upload to anaconda.org
init-shell: bash
environment-name: upload-env
create-args: >-
anaconda-client
- name: win-arm64 install anaconda client
if: github.event_name == 'schedule' && matrix.buildplat[1] == 'win_arm64'
run: |
# Rust installation needed for rpds-py.
Invoke-WebRequest https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe -UseBasicParsing -Outfile rustup-init.exe
.\rustup-init.exe -y
$env:PATH="$env:PATH;$env:USERPROFILE\.cargo\bin"
pip install anaconda-client
- name: Upload to anaconda.org
if: github.event_name == 'schedule' && github.repository == 'scipy/scipy-release'
shell: bash -el {0} # required for micromamba
env:
TOKEN: ${{ secrets.scipy_NIGHTLY_UPLOAD_TOKEN }}
run: |
anaconda -q -t ${TOKEN} upload --force -u scientific-python-nightly-wheels ./dist/*.whl
# -------------------------------------------------------------------------------------
build_sdist:
name: Build sdist
runs-on: ubuntu-latest
if: github.repository == 'andyfaff/scipy'
steps:
- name: Checkout scipy
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: scipy/scipy
submodules: true
ref: ${{ env.SOURCE_REF_TO_BUILD }}
persist-credentials: false
- name: Build sdist
run: |
python -m pip install -U pip build
# need openblas even for the sdist build
OPENBLAS=openblas32
pkgconf_path=$GITHUB_WORKSPACE/.openblas
rm -rf $pkgconf_path
mkdir -p $pkgconf_path
python -m pip install -r $GITHUB_WORKSPACE/requirements/openblas.txt
python -c "import scipy_${OPENBLAS}; print(scipy_${OPENBLAS}.get_pkg_config())" > $pkgconf_path/scipy-openblas.pc
export PKG_CONFIG_PATH=$pkgconf_path
echo "PKG_CONFIG_PATH=$pkgconf_path" >> "$GITHUB_ENV"
python -m build --sdist
- name: Test the sdist
run: |
python -m pip install -v dist/*.gz
pip install -r $GITHUB_WORKSPACE/requirements/test.txt
cd .. # Can't import scipy within scipy src directory
python -c "import scipy, sys; print(scipy.__version__); sys.exit(scipy.test() is False)"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: sdist
path: ./dist/*
# -------------------------------------------------------------------------------------
testpypi-publish:
name: Publish release to TestPyPI
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'testpypi'
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/scipy
permissions:
id-token: write # mandatory for trusted publishing
steps:
- name: Download sdist and wheels
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: dist
merge-multiple: true
- name: Publish
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true
print-hash: true
attestations: true
# -------------------------------------------------------------------------------------
check_version:
name: Ensure commit is tag before upload to PyPi
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'pypi'
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
steps:
- name: Checkout scipy
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: scipy/scipy
ref: ${{ env.SOURCE_REF_TO_BUILD }}
path: scipy-src
fetch-depth: 0
fetch-tags: true
submodules: false
persist-credentials: false
- name: Examine git commit
run: |
cd scipy-src
hash=$(git describe HEAD)
echo $hash
if [[ $hash == *"-"*"-"* ]]; then
echo "SOURCE_REF_TO_BUILD is not a tag"
exit 1
else
echo "SOURCE_REF_TO_BUILD is a tag"
fi;
# -------------------------------------------------------------------------------------
pypi-publish:
name: Publish release to PyPI
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'pypi'
needs: [check_version]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/scipy
permissions:
id-token: write # mandatory for trusted publishing
steps:
- name: Download sdist and wheels
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: dist
merge-multiple: true
- name: Publish
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
print-hash: true
attestations: true