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
123 changes: 123 additions & 0 deletions .github/workflows/build-ssh2-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# Based on the `build-manylinux`/`build-wheels` steps of
# https://github.com/ParallelSSH/ssh2-python/blob/1.2.0.post1/ci/build-manylinux.sh
name: Build ssh2-python wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'ssh2-python version (git tag, e.g. 1.2.0.post1)'
required: true
default: '1.2.0.post1'
pull_request:
paths:
- '.github/workflows/build-ssh2-python.yml'
- 'patches/ssh2-python/**'

concurrency:
group: ${{ github.workflow }}-${{ inputs.version || '1.2.0.post1' }}-${{ 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 1.2.0.post1 there.
SSH2_PYTHON_VERSION: ${{ inputs.version || '1.2.0.post1' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

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

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

steps:
- name: Checkout ssh2-python ${{ env.SSH2_PYTHON_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ParallelSSH/ssh2-python
ref: ${{ env.SSH2_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 ssh2-python source
run: |
git apply python-wheels/patches/ssh2-python/${{ env.SSH2_PYTHON_VERSION }}/*.patch
# versioneer's `git describe --tags --dirty` has no pretend-version escape
# hatch the way setuptools_scm does (gotcha 315); hide just the patched
# file from dirty-detection instead of poisoning the wheel version.
git update-index --skip-worktree setup.py

- 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 }}
# setup.py's build_ssh2() always cmake-builds the libssh2 tree checked
# into libssh2/ against CRYPTO_BACKEND=OpenSSL (the SYSTEM_LIBSSH2 escape
# is unused here); upstream's own manylinux image builds OpenSSL 3.4.0
# from source first, which fails on riscv64 (no FindBin.pm, gotcha 46).
# Rocky 10's own openssl-devel is already current, so use that instead
# (mirrors build-uamqp.yml/build-pylibsrtp.yml).
CIBW_BEFORE_ALL_LINUX: >-
dnf -y install openssl-devel zlib-devel &&
cp libssh2/COPYING {project}/LICENSE.libssh2 &&
cp /usr/share/licenses/openssl-libs/LICENSE.txt {project}/LICENSE.openssl
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
CIBW_TEST_REQUIRES: pytest pytest-rerunfailures
# tests/ is a package (has __init__.py); {project}/tests would run pytest
# against the checkout, whose sibling ssh2/ source dir (no .so files, only
# .py/.pxd) shadows the installed wheel (gotcha 25). test-sources copies
# just tests/ into an otherwise-empty cwd, so a path relative to it imports
# the wheel instead.
CIBW_TEST_SOURCES: tests
CIBW_TEST_COMMAND: python -m pytest tests

- name: Check the wheel ships the extensions, libssh2 and both licences
run: |
python3 - wheelhouse/*.whl <<'EOF'
import sys, zipfile
for whl in sys.argv[1:]:
names = zipfile.ZipFile(whl).namelist()
assert any(n.startswith("ssh2/session") and n.endswith(".so") for n in names), names
assert any(n.startswith("ssh2/libssh2.so") for n in names), names
licences = {n.rsplit("/", 1)[1]
for n in names if ".dist-info/licenses/" in n} - {""}
assert licences == {"LICENSE", "COPYING", "LICENSE.libssh2", "LICENSE.openssl"}, (whl, licences)
print(whl, "ok")
EOF

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

publish:
name: Publish ssh2-python ${{ inputs.version || '1.2.0.post1' }}
needs: [setup, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: ssh2-python-${{ inputs.version || '1.2.0.post1' }}-*-manylinux_riscv64
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Sun, 7 Sep 2026 00:00:00 +0200
Subject: [PATCH] Widen license-files to cover bundled third-party licences

`license_files=['LICENSE', 'COPYING']` is an explicit setuptools list, so
it does not fall back to the `LICEN[CS]E*` auto-discovery glob: a
`LICENSE.<dep>` dropped at the project root to cover a library
`auditwheel repair` vendors into the wheel (libssh2, statically checked
in under `libssh2/` and built from source, and OpenSSL, linked from the
build image) is silently ignored. Widening the list to also match
`LICENSE.*` picks those up with no other packaging change.

Upstream's own wheels (manylinux2014/manylinux_2_28 x86_64/aarch64) carry
the same gap: only LICENSE/COPYING ship in dist-info/licenses, with no
notice for libssh2 or OpenSSL.

Upstream-Status: To upstream [not submitted from this automated port run; needs a pull request against ParallelSSH/ssh2-python]
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index 04dafae..4971ce3 100644
--- a/setup.py
+++ b/setup.py
@@ -117,7 +117,7 @@ setup(
cmdclass=cmdclass,
url='https://github.com/ParallelSSH/ssh2-python',
license='LGPL-2.1-only',
- license_files=['LICENSE', 'COPYING'],
+ license_files=['LICENSE', 'COPYING', 'LICENSE.*'],
author='Panos Kittenis',
author_email='danst@tutanota.com',
description='Bindings for libssh2 C library',
--
2.43.0