Skip to content
Merged
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
147 changes: 147 additions & 0 deletions .github/workflows/build-iminuit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on upstream's own wheel build setup:
# https://github.com/scikit-hep/iminuit/blob/v2.32.0/.github/workflows/release.yml
name: Build iminuit wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'iminuit version to build (git tag without leading v, e.g. 2.32.0)'
required: true
default: '2.32.0'
pull_request:
paths:
- '.github/workflows/build-iminuit.yml'

concurrency:
group: ${{ github.workflow }}-${{ inputs.version || '2.32.0' }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read # to fetch code (actions/checkout)

env:
IMINUIT_VERSION: ${{ inputs.version || '2.32.0' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

jobs:
setup:
uses: $/.github/workflows/_setup.yml

build_sdist:
needs: [setup]
# The sdist packages the iminuit wrapper plus the vendored MINUIT2/mathcore
# sources pulled from the extern/root submodule; it's architecture-independent,
# so build it once on x86 instead of burning a scarce riscv runner (CLAUDE.md
# gotcha 4).
name: Build iminuit ${{ inputs.version || '2.32.0' }} sdist
runs-on: ubuntu-latest
outputs:
sdist_name: ${{ steps.sdist.outputs.sdist_name }}
package_version: ${{ steps.sdist.outputs.package_version }}
steps:
- name: Checkout iminuit v${{ env.IMINUIT_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: scikit-hep/iminuit
ref: v${{ env.IMINUIT_VERSION }}
submodules: true
persist-credentials: false

- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: python-wheels
persist-credentials: false

- name: Install Python
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: '3.12'
activate-environment: true
enable-cache: false

# extern/root/LICENSE (LGPL v2.1, the MINUIT2 sources' own license) is
# never packaged: sdist.exclude drops extern/root wholesale and
# sdist.include only re-adds the compiled sources, not the license
# text (CLAUDE.md gotcha 32/123 shape).
- name: Patch iminuit source
run: git apply python-wheels/patches/iminuit/${{ env.IMINUIT_VERSION }}/00*.patch

- name: Build sdist
id: sdist
run: |
uv pip install build twine
python -m build --sdist
twine check dist/*
sdists=(dist/*.tar.gz)
sdist_name="$(basename "${sdists[0]}")"
echo "sdist_name=${sdist_name}" >> "$GITHUB_OUTPUT"
echo "package_version=$(echo "${sdist_name}" | sed -En 's/iminuit-(.+)\.tar\.gz/\1/p')" >> "$GITHUB_OUTPUT"

- name: Upload sdist artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: iminuit-${{ env.IMINUIT_VERSION }}-sdist
path: dist/*.tar.gz
if-no-files-found: error

build_wheels:
needs: [setup, build_sdist]
name: Build iminuit ${{ inputs.version || '2.32.0' }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
python: ["cp312", "cp313", "cp314", "cp314t"]

steps:
- name: Download sdist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: iminuit-${{ env.IMINUIT_VERSION }}-sdist
path: dist/

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
package-dir: dist/${{ needs.build_sdist.outputs.sdist_name }}
env:
CIBW_ARCHS: riscv64
CIBW_BUILD: ${{ matrix.python }}-manylinux_riscv64
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# CIBW_ENVIRONMENT replaces, rather than merges into, upstream's own
# [tool.cibuildwheel.environment] table (CLAUDE.md gotcha 107), so its
# two keys are repeated here alongside our registry for numpy (a
# runtime dependency numpy ships no riscv64 wheel for on PyPI itself).
CIBW_ENVIRONMENT: >-
PIP_ONLY_BINARY=:all:
UV_ONLY_BINARY=:all:
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
UV_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
UV_INDEX_STRATEGY=unsafe-best-match
# Upstream's own test-requires/test-command (pytest only) come from
# the sdist's pyproject.toml; only the licence assertion is ours.
CIBW_TEST_COMMAND: >-
python -c "import importlib.metadata as m; l = sorted(str(p).rsplit('/', 1)[-1] for p in m.files('iminuit') if '.dist-info/licenses/' in str(p)); assert l == ['LICENSE', 'LICENSE.minuit2'], l"
&& python -m pytest {package}/tests

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: iminuit-${{ needs.build_sdist.outputs.package_version }}-${{ matrix.python }}-manylinux_riscv64
path: ./wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish iminuit ${{ inputs.version || '2.32.0' }}
needs: [setup, build_sdist, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: iminuit-${{ needs.build_sdist.outputs.package_version }}-*-manylinux_riscv64
Loading