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

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

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

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

build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
name: Build mjml-python ${{ matrix.version }} ${{ matrix.tag }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
include:
# Cargo.toml hardcodes pyo3's abi3-py38 feature unconditionally;
# the riscv64 manylinux image's oldest interpreter is cp39 (no
# cp38), so patches/ bumps it to abi3-py39 -- gotcha 96. Built on
# cp39 and re-tested on the newer ones via find_compatible_wheel.
- tag: cp39-abi3
build: >-
cp39-manylinux_riscv64 cp310-manylinux_riscv64
cp311-manylinux_riscv64 cp312-manylinux_riscv64
cp313-manylinux_riscv64 cp314-manylinux_riscv64
- tag: cp314t
build: cp314t-manylinux_riscv64

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

steps:
- name: Checkout mjml-python v${{ env.MJML_PYTHON_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: mgd020/mjml-python
ref: v${{ env.MJML_PYTHON_VERSION }}
persist-credentials: false

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

- name: Patch mjml-python source
run: git apply python-wheels/patches/mjml-python/${{ env.MJML_PYTHON_VERSION }}/00*.patch

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
env:
# musllinux is dropped: rustup.rs ships no riscv64 musl toolchain.
CIBW_BUILD: ${{ matrix.build }}
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# mjml-python ships no [tool.cibuildwheel], so the Rust toolchain
# its maturin backend needs is installed in-container here.
CIBW_BEFORE_ALL_LINUX: >-
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
CIBW_ENVIRONMENT_LINUX: PATH="$PATH:$HOME/.cargo/bin"
CIBW_TEST_SOURCES: tests
CIBW_TEST_COMMAND: >-
python -c "import mjml.mjml as m; assert m.__file__.endswith('.so'), m.__file__" &&
python -m unittest -v

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

publish:
name: Publish mjml-python ${{ matrix.version }}
needs: [setup, build_wheels]
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: mjml-python-${{ matrix.version }}-*-manylinux_riscv64
5 changes: 5 additions & 0 deletions docs/packages/mjml-python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package-name: mjml-python
source-code: https://github.com/mgd020/mjml-python
license: MIT
versions:
- version: 1.4.1
29 changes: 29 additions & 0 deletions patches/mjml-python/1.4.1/0001-Cargo-bump-abi3-floor-to-py39.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Fri, 25 Sep 2026 00:00:00 +0000
Subject: [PATCH] Cargo: bump abi3 floor to py39

Upstream-Status: Inappropriate [manylinux_2_39_riscv64 ships no cp38 interpreter]

The riscv64 manylinux image's oldest available CPython is cp39 (no cp38),
so a wheel built here and tagged cp38-abi3 (this crate's abi3-py38
feature) would never actually be compiled or tested against its own
declared floor -- gotcha 96. Bump the pyo3 abi3 feature to abi3-py39 to
make the riscv64 wheel's tag match the oldest interpreter this repo can
build and test it on; every other platform's wheel is unaffected.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
Cargo.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index c3f55b0..26e8f79 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,4 +10,4 @@ crate-type = ["cdylib"]

[dependencies]
mrml = "5.0.0"
-pyo3 = { version = "~0.29.0", features = ["abi3-py38", "extension-module"] }
+pyo3 = { version = "~0.29.0", features = ["abi3-py39", "extension-module"] }
Loading