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
118 changes: 118 additions & 0 deletions .github/workflows/build-amazon-ion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on the `build-wheels` job of
# https://github.com/amazon-ion/ion-python/blob/v0.14.6/.github/workflows/release.yml
name: Build amazon-ion wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'amazon-ion version to build (git tag without the leading v, e.g. 0.14.6)'
required: true
default: '0.14.6'
pull_request:
paths:
- '.github/workflows/build-amazon-ion.yml'
- 'patches/amazon-ion/**'

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

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

env:
# `inputs.version` is empty on pull_request events; default to 0.14.6 there.
AMAZON_ION_VERSION: ${{ inputs.version || '0.14.6' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

jobs:
build_wheels:
name: Build amazon-ion ${{ inputs.version || '0.14.6' }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
python: ["cp312", "cp313", "cp314", "cp314t"]

steps:
- name: Checkout amazon-ion v${{ env.AMAZON_ION_VERSION }}
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: amazon-ion/ion-python
ref: v${{ env.AMAZON_ION_VERSION }}
submodules: true
persist-credentials: false

# ion-c derives its version via `git describe --match "v*"`; submodule
# checkouts fetch no tags, which leaves the version macros empty and breaks
# the ion_version.c compile.
- name: Fetch ion-c tags
run: git -C src/ion-c fetch --tags --unshallow

- name: Checkout python-wheels
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: python-wheels
persist-credentials: false

- name: Patch amazon-ion source
run: git apply python-wheels/patches/amazon-ion/${{ env.AMAZON_ION_VERSION }}/*.patch

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
only: ${{ matrix.python }}-manylinux_riscv64
env:
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# jsonconversion pulls in numpy, which has no riscv64 wheel on PyPI.
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
CIBW_TEST_EXTRAS: test
# test_vectors.py resolves its data as <rootdir>/vectors/iontestdata.
CIBW_TEST_SOURCES: tests vectors pyproject.toml
# The suite silently falls back to the pure-Python reader when the
# extension is missing, and the licence files come from our patch, so
# assert both before running upstream's own command.
CIBW_TEST_COMMAND: >-
python -c "from amazon.ion.simpleion import c_ext; assert c_ext, 'C extension not loaded'" &&
python -c "import importlib.metadata as m; f = sorted(str(p).split('licenses/', 1)[1] for p in m.files('amazon-ion') if '.dist-info/licenses/' in str(p)); assert f == ['LICENSE', 'NOTICE', 'src/ion-c/LICENSE', 'src/ion-c/NOTICE', 'src/ion-c/decNumber/ICU-license.html'], f" &&
py.test --ignore tests/test_benchmark_cli.py --ignore tests/test_benchmark_spec.py

- name: Check the extension 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.endswith(".so") for n in names), whl
print(whl, "ok")
EOF

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: amazon-ion-${{ env.AMAZON_ION_VERSION }}-${{ matrix.python }}-manylinux_riscv64
path: wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish amazon-ion ${{ inputs.version || '0.14.6' }} to GitLab
needs: [build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: amazon-ion-${{ env.AMAZON_ION_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 27 Aug 2026 08:00:00 +0200
Subject: [PATCH] Package the NOTICE and vendored ion-c/decNumber licences

The extension statically links the whole of ion-c (Apache-2.0, with its own
NOTICE) and IBM's decNumber (ICU licence), yet the built wheel carries only
ion-python's own LICENSE. Apache-2.0 section 4(d) requires the NOTICE files of
the redistributed work to travel with the binary, and the ICU licence requires
its copyright notice to accompany binary redistributions, so every published
wheel is short four files.

py-build-cmake copies `project.license-files` into `.dist-info/licenses/`, but
rejects the key unless `project.license` is an SPDX expression, so declare the
expression as well. That is the PEP 639 form and moves the licence text out of
METADATA's `License:` field into `License-Expression:`/`License-File:`.

Upstream-Status: To upstream [not yet submitted; the same gap exists in every amazon-ion wheel on PyPI, so it needs a maintainer discussion rather than a drive-by PR]
---
pyproject.toml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 7cb34c5..c6045f6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,7 +2,8 @@
name = "amazon-ion"
readme = "README.md"
requires-python = ">=3.9"
-license = { "file" = "LICENSE" }
+license = "Apache-2.0"
+license-files = ["LICENSE", "NOTICE", "src/ion-c/LICENSE", "src/ion-c/NOTICE", "src/ion-c/decNumber/ICU-license.html"]
authors = [{ "name" = "Amazon Ion Team", "email" = "ion-team@amazon.com" }]
keywords = []
classifiers = []
--
2.50.1 (Apple Git-155)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 27 Aug 2026 10:00:00 +0200
Subject: [PATCH] Require CMake 3.30 so free-threaded builds configure

CMake grew free-threaded support in FindPython in 3.30, and py-build-cmake
only adds the `t` flag to `Python3_FIND_ABI` when `cmake.minimum_version`
allows it to assume that release. The project leaves the key at its 3.15
default, so under a free-threaded interpreter py-build-cmake logs

CMake version 3.15 does not support the free-threaded ABI, but the current
interpreter requires it.

and configuration then fails with `Could NOT find Python3 (missing:
Development.Module)`, because CMake looks for the default ABI's headers and
library rather than the `t` ones.

The key only gates that ABI flag and the CMake version py-build-cmake will
provision, so non-free-threaded builds are unaffected: they already resolve
to an all-OFF ABI tuple that is never passed to CMake.

Upstream-Status: To upstream [not yet submitted; upstream builds no free-threaded wheels today, so this needs a maintainer discussion about supporting them rather than a drive-by PR]
---
pyproject.toml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/pyproject.toml b/pyproject.toml
index c6045f6..7a1f0e1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -50,6 +50,9 @@ directory = "src-python"
include = ["CMakeLists.txt", "src/*"]

[tool.py-build-cmake.cmake]
+# 3.30 is the first CMake release whose FindPython supports the free-threaded
+# ABI; py-build-cmake only passes the `t` ABI flag when it may assume that version.
+minimum_version = "3.30"
build_type = "Release"
source_path = "src"
build_args = []
--
2.50.1 (Apple Git-155)
Loading