Skip to content
Open
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
158 changes: 158 additions & 0 deletions .github/workflows/build-pymetis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# Based on the `build_wheels` job of
# https://github.com/inducer/pymetis/blob/v2025.2.2/.github/workflows/wheels.yml
name: Build pymetis wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/pymetis.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-pymetis.yml'
- 'docs/packages/pymetis.yaml'
push:
branches: [main]
paths:
- '.github/workflows/build-pymetis.yml'
- 'docs/packages/pymetis.yaml'

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

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

env:
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
MUSLLINUX_RISCV64_IMAGE: quay.io/pypa/musllinux_1_2_riscv64

jobs:
setup:
uses: $/.github/workflows/_setup.yml
with:
package: pymetis
version: ${{ inputs.version }}

build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
name: Build pymetis ${{ matrix.version }} ${{ matrix.python }}-${{ matrix.libc }}_riscv64
runs-on: ubuntu-24.04-riscv
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
python: ["cp312", "cp313", "cp314", "cp314t"]
libc: [manylinux, musllinux]

env:
PYMETIS_VERSION: ${{ matrix.version }}

steps:
- name: Checkout pymetis v${{ env.PYMETIS_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: inducer/pymetis
ref: v${{ env.PYMETIS_VERSION }}
persist-credentials: false

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

- name: Patch pymetis source
run: git apply python-wheels/patches/pymetis/${{ env.PYMETIS_VERSION }}/*.patch

- uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
only: ${{ matrix.python }}-${{ matrix.libc }}_riscv64
env:
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
CIBW_MUSLLINUX_RISCV64_IMAGE: ${{ env.MUSLLINUX_RISCV64_IMAGE }}
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ PIP_ONLY_BINARY=numpy
# upstream's wheels.yml tests nothing; run the pytest suite its ci.yml runs
CIBW_TEST_REQUIRES: numpy pytest
CIBW_TEST_SOURCES: test
CIBW_TEST_COMMAND: python -m pytest -v test
# numpy has no riscv64 musllinux wheel in our registry.
CIBW_TEST_SKIP: "*-musllinux*"

- name: Check the extension and licences made it into the wheel
run: |
python3 - wheelhouse/*.whl <<'EOF'
import sys, zipfile
for whl in sys.argv[1:]:
names = zipfile.ZipFile(whl).namelist()
assert any(n.startswith("pymetis/_internal.") and n.endswith(".so") for n in names), names
licences = {n.split(".dist-info/licenses/", 1)[1] for n in names if ".dist-info/licenses/" in n and not n.endswith("/")}
assert licences == {"LICENSE", "LICENSE.pybind11", "src/metis/LICENSE.txt"}, (whl, licences)
print(whl, "ok")
EOF

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pymetis-${{ env.PYMETIS_VERSION }}-${{ matrix.python }}-${{ matrix.libc }}_riscv64
path: ./wheelhouse/*.whl
if-no-files-found: error

gpl_sources:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
name: Collect GPL sources for pymetis ${{ matrix.version }}
runs-on: ubuntu-24.04-riscv

env:
PYMETIS_VERSION: ${{ matrix.version }}

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

# The musllinux wheel vendors the image's libstdc++ and libgcc_s (gotcha 409).
- uses: ./actions/collect-gpl-sources
with:
image: ${{ env.MANYLINUX_RISCV64_IMAGE }}
packages: gcc
output: gpl-sources.tar

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pymetis-${{ env.PYMETIS_VERSION }}-gpl-sources
path: gpl-sources.tar
if-no-files-found: error

publish:
name: Publish pymetis ${{ matrix.version }}
needs: [setup, build_wheels, gpl_sources]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
secrets:
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
with:
artifact-pattern: pymetis-${{ matrix.version }}-*riscv64
gpl-sources-artifact: pymetis-${{ matrix.version }}-gpl-sources
gpl-sources-description: gcc
6 changes: 6 additions & 0 deletions docs/packages/pymetis.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package-name: pymetis
source-code: https://github.com/inducer/pymetis
license: MIT AND Apache-2.0
versions:
- version: 2025.2.2
patched: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
From 5290f985605abfb79f008e7bcfeb59a5682dc109 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Wed, 14 Oct 2026 11:02:42 +0000
Subject: [PATCH] pyproject: ship the METIS and pybind11 licences in the wheel

meson-python only writes dist-info/licenses/ entries for files named in
`[project] license-files`, and has no PEP 639 default glob behind it, so
every wheel built from this tree ships no licence text at all -- not
pymetis' own MIT LICENSE, not the Apache-2.0 notice of the METIS/GKlib
sources compiled into _internal, and not the BSD-3-Clause notice of the
pybind11 headers instantiated into it. Upstream's PyPI wheels carry the
same gap.

List the three explicitly; LICENSE.pybind11 is pybind11's own LICENSE,
verbatim from its v3.1.0 tag.

Upstream-Status: To upstream [not yet submitted; python-wheels does not open issues/PRs on third-party repos]
---
LICENSE.pybind11 | 29 +++++++++++++++++++++++++++++
pyproject.toml | 1 +
2 files changed, 30 insertions(+)
create mode 100644 LICENSE.pybind11

diff --git a/LICENSE.pybind11 b/LICENSE.pybind11
new file mode 100644
index 0000000..e466b0d
--- /dev/null
+++ b/LICENSE.pybind11
@@ -0,0 +1,29 @@
+Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
+external contributions to this project including patches, pull requests, etc.
diff --git a/pyproject.toml b/pyproject.toml
index 69aac21..3a5b2f7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,6 +11,7 @@ version = "2025.2.2"
description = "A graph partitioning package"
readme = "README.rst"
license = "MIT AND Apache-2.0"
+license-files = ["LICENSE", "LICENSE.pybind11", "src/metis/LICENSE.txt"]
maintainers = [ { name = "Andreas Kloeckner", email = "inform@tiker.net" } ]
authors = [ { name = "Andreas Kloeckner", email = "inform@tiker.net" } ]
requires-python = ">=3.10"
--
2.43.0

Loading