Skip to content
Open
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
206 changes: 206 additions & 0 deletions .github/workflows/build-cryptography.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
#
# Based on upstream's wheel builder:
# https://github.com/pyca/cryptography/blob/50.0.0/.github/workflows/wheel-builder.yml
# cryptography is a PyO3/Rust extension built with maturin (not setuptools-rust)
# and links OpenSSL. Upstream links a statically-built OpenSSL from their own
# pyca/infra images, which don't exist for riscv64; we link the manylinux
# image's system OpenSSL dynamically instead (gotcha 16) and let auditwheel
# vendor libssl/libcrypto into the wheel.
name: Build cryptography wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'cryptography version to build (git tag, e.g. 50.0.0)'
required: true
default: '50.0.0'
pull_request:
paths:
- '.github/workflows/build-cryptography.yml'

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

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

env:
CRYPTOGRAPHY_VERSION: ${{ inputs.version || '50.0.0' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
# abi3 floor: cp312 is RISE's min Python, and it's also the interpreter we
# build with, so a plain `abi3` feature already floors here with no
# explicit pyo3/abi3-pyNN override (unlike upstream, which builds two
# different floors from one cp311 interpreter).
ABI3_FLOOR: cp312

jobs:
# Build the sdist ourselves from the tag (never the prebuilt PyPI sdist); it's
# arch-independent, so build it once on x86 (gotcha 4).
build_sdist:
name: Build cryptography ${{ inputs.version || '50.0.0' }} sdist
runs-on: ubuntu-latest
outputs:
sdist_name: ${{ steps.sdist.outputs.sdist_name }}
package_version: ${{ steps.sdist.outputs.package_version }}
steps:
- name: Checkout cryptography ${{ env.CRYPTOGRAPHY_VERSION }}
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: pyca/cryptography
ref: ${{ env.CRYPTOGRAPHY_VERSION }}
persist-credentials: false

- name: Install Python
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
python-version: '3.12'
activate-environment: true
enable-cache: false

- name: Build sdist
id: sdist
run: |
set -euo pipefail
rm -rf dist
uv pip install build twine
python -m build --sdist --outdir dist
twine check dist/*

sdist_name="$(ls dist)"
{
echo "sdist_name=${sdist_name}"
echo "package_version=$(echo "${sdist_name}" | sed -En 's/cryptography-(.+)\.tar\.gz/\1/p')"
} >> "$GITHUB_OUTPUT"

- name: Upload sdist artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.sdist.outputs.sdist_name }}
path: dist/${{ steps.sdist.outputs.sdist_name }}
if-no-files-found: error

# One cp312-abi3 wheel: cibuildwheel builds it once and reuses+tests it on
# cp313/cp314 (find_compatible_wheel), so all three tags share one wheel.
build_abi3:
needs: [build_sdist]
name: Build cryptography ${{ inputs.version || '50.0.0' }} cp312-abi3-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 90
steps:
- name: Download sdist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.build_sdist.outputs.sdist_name }}
path: dist/

- name: Build and test wheel
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
package-dir: dist/${{ needs.build_sdist.outputs.sdist_name }}
env:
CIBW_ARCHS: riscv64
CIBW_BUILD: 'cp312-* cp313-* cp314-*'
CIBW_SKIP: '*-musllinux_*' # rustup.rs has no riscv64 musl toolchain
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# No Rust and no OpenSSL dev headers in the manylinux image; install
# them. openssl-sys finds the (dynamic-only, gotcha 16) system
# OpenSSL via pkg-config, so no OPENSSL_STATIC/OPENSSL_DIR needed.
# The manylinux image's system OpenSSL is RHEL-patched to reject
# SHA1 signing/verification unless `rh-allow-sha1-signatures = yes`
# is set (openssl/openssl#17662); upstream's own unrestricted
# static OpenSSL build never hits this. OPENSSL_CONF=/dev/null
# does NOT fix it - the patch denies SHA1 by default when the
# option is absent from config entirely, so write a minimal config
# that opts back in for the test phase only. It isn't bundled by
# auditwheel (only the .so is), so it never reaches the shipped
# wheel.
CIBW_BEFORE_ALL_LINUX: |
dnf install -y openssl-devel pkgconfig
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
printf 'openssl_conf = openssl_init\n\n[openssl_init]\nalg_section = evp_properties\n\n[evp_properties]\nrh-allow-sha1-signatures = yes\n' > /tmp/rise-allow-sha1.cnf
CIBW_ENVIRONMENT: >-
PATH="$PATH:$HOME/.cargo/bin"
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
# cryptography_vectors is pure-Python and already published on
# public PyPI for this version, so install it directly instead of
# building it from upstream's vectors/ subdir. --wycheproof-root
# and --x509-limbo-root are left unset, which upstream's own
# conftest treats as "skip" (external vector repos, gotcha:
# justified skip - large external downloads).
CIBW_TEST_REQUIRES: >-
cryptography_vectors==${{ needs.build_sdist.outputs.package_version }}
pytest>=7.4.0 pytest-benchmark>=4.0 pytest-xdist>=3.5.0 pretend>=0.7 certifi>=2024
CIBW_TEST_ENVIRONMENT: OPENSSL_CONF=/tmp/rise-allow-sha1.cnf
CIBW_TEST_COMMAND: cd {package} && python -m pytest -n auto --dist=worksteal tests

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cryptography-${{ env.CRYPTOGRAPHY_VERSION }}-cp312-abi3-manylinux_riscv64
path: ./wheelhouse/*.whl
if-no-files-found: error

# Free-threaded wheel: per-interpreter, no abi3 tag (matches upstream's own
# cp314-cp314t wheel). Only cp314t - the riscv64 image has no cp313t.
build_freethreaded:
needs: [build_sdist]
name: Build cryptography ${{ inputs.version || '50.0.0' }} cp314t-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 90
steps:
- name: Download sdist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.build_sdist.outputs.sdist_name }}
path: dist/

- name: Build and test wheel
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
package-dir: dist/${{ needs.build_sdist.outputs.sdist_name }}
env:
CIBW_ARCHS: riscv64
CIBW_BUILD: 'cp314t-*'
CIBW_SKIP: '*-musllinux_*'
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# See the abi3 job above for why this writes an opt-in SHA1 config
# instead of nulling OPENSSL_CONF.
CIBW_BEFORE_ALL_LINUX: |
dnf install -y openssl-devel pkgconfig
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
printf 'openssl_conf = openssl_init\n\n[openssl_init]\nalg_section = evp_properties\n\n[evp_properties]\nrh-allow-sha1-signatures = yes\n' > /tmp/rise-allow-sha1.cnf
CIBW_ENVIRONMENT: >-
PATH="$PATH:$HOME/.cargo/bin"
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
CIBW_TEST_REQUIRES: >-
cryptography_vectors==${{ needs.build_sdist.outputs.package_version }}
pytest>=7.4.0 pytest-benchmark>=4.0 pytest-xdist>=3.5.0 pretend>=0.7 certifi>=2024
CIBW_TEST_ENVIRONMENT: OPENSSL_CONF=/tmp/rise-allow-sha1.cnf
CIBW_TEST_COMMAND: cd {package} && python -m pytest -n auto --dist=worksteal tests

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cryptography-${{ env.CRYPTOGRAPHY_VERSION }}-cp314t-manylinux_riscv64
path: ./wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish cryptography ${{ inputs.version || '50.0.0' }} to GitLab
needs: [build_sdist, build_abi3, build_freethreaded]
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: cryptography-${{ needs.build_sdist.outputs.package_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 }}
Loading