From d345ac36a8180206b37dbab5be06aec26f7ab8a5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 06:49:54 +0200 Subject: [PATCH 1/2] sdbus: add build-sdbus.yml for riscv64 wheels --- .github/workflows/build-sdbus.yml | 274 ++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 .github/workflows/build-sdbus.yml diff --git a/.github/workflows/build-sdbus.yml b/.github/workflows/build-sdbus.yml new file mode 100644 index 000000000..fc8bfaa30 --- /dev/null +++ b/.github/workflows/build-sdbus.yml @@ -0,0 +1,274 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on the CI/wheel-build steps of +# https://github.com/python-sdbus/python-sdbus/blob/0.14.3/.github/workflows/ci.yml +# Upstream's own release process statically links a from-source libsystemd for +# manylinux1-era portability; manylinux_2_39_riscv64 already ships systemd-devel, +# so this links libsystemd dynamically instead, like build-cysystemd.yml. +name: Build sdbus wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'sdbus version to build (git tag, e.g. 0.14.3)' + required: true + default: '0.14.3' + pull_request: + paths: + - '.github/workflows/build-sdbus.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '0.14.3' }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + SDBUS_VERSION: ${{ inputs.version || '0.14.3' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + # setup.py only sets Extension(py_limited_api=...); the bdist_wheel floor + # tag comes from us via --py-limited-api, so we pick our own (RISE's min). + ABI3_FLOOR: cp312 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + + build_abi3: + needs: [setup] + name: Build sdbus ${{ inputs.version || '0.14.3' }} cp312-abi3-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 60 + steps: + - name: Checkout sdbus ${{ env.SDBUS_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: python-sdbus/python-sdbus + ref: ${{ env.SDBUS_VERSION }} + persist-credentials: false + + - name: Stage the licence-collection script + run: | + cat > collect-licenses.sh <<'COLLECT_EOF' + #!/bin/bash + # SPDX-FileCopyrightText: 2026 The RISE Project + # SPDX-License-Identifier: MIT + # + # Stage, at the project root, the licence of every shared library + # auditwheel vendors out of the build image alongside libsystemd. + # setuptools' default LICENSE* glob copies them into the wheel. + set -euo pipefail + + project="${1:?usage: collect-licenses.sh }" + + # ldd is transitive, so libsystemd alone covers its whole closure; + # ldd does not list the root itself, so resolve that too. + mapfile -t libs < <( + { + ldd /usr/lib64/libsystemd.so.0 | tr ' ' '\n' | grep '^/' + readlink -f /usr/lib64/libsystemd.so.0 + } | sort -u + ) + + # `rpm -qf` reports unowned files on stdout, so keep only bare package names. + # glibc and the gcc runtime are on auditwheel's manylinux allowlist and + # are never vendored into the wheel. + mapfile -t pkgs < <( + rpm -qf --qf '%{NAME}\n' "${libs[@]}" 2>/dev/null | + grep -E '^[A-Za-z0-9._+-]+$' | sort -u | + grep -vE '^(glibc|libgcc|libstdc\+\+|gcc)$' + ) + + for pkg in "${pkgs[@]}"; do + mapfile -t files < <(rpm -q --licensefiles "$pkg" 2>/dev/null || true) + + # Some subpackages leave the licence to a sibling of the same source RPM. + if [ -z "${files[0]:-}" ]; then + srpm=$(rpm -q --qf '%{SOURCERPM}\n' "$pkg") + mapfile -t files < <( + rpm -qa --qf '%{SOURCERPM} %{NAME}\n' | + awk -v s="$srpm" '$1 == s { print $2 }' | + xargs -r rpm -q --licensefiles 2>/dev/null | sort -u + ) + fi + + # Others mark it %doc rather than %license, and the image installs no docs. + if [ -z "${files[0]:-}" ]; then + dnf -y --disablerepo=extras reinstall --setopt=tsflags= "$pkg" >/dev/null + mapfile -t files < <(rpm -qd "$pkg" | grep -iE '/(LICEN[CS]E|COPYING|NOTICE)') + fi + + for f in "${files[@]}"; do + [ -f "$f" ] || continue + cp "$f" "$project/LICENSE.${pkg}.$(basename "$f")" + done + compgen -G "$project/LICENSE.$pkg.*" >/dev/null || + { echo "no licence file found for $pkg" >&2; exit 1; } + done + + ls -1 "$project"/LICENSE.* | sed "s|$project/||" + COLLECT_EOF + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + env: + CIBW_ARCHS: riscv64 + CIBW_BUILD: >- + cp312-manylinux_riscv64 cp313-manylinux_riscv64 + cp314-manylinux_riscv64 + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_BEFORE_ALL_LINUX: >- + dnf install -y systemd-devel dbus-daemon && + bash {project}/collect-licenses.sh {project} + CIBW_ENVIRONMENT: PYTHON_SDBUS_USE_LIMITED_API=1 + # setup.py only calls Extension(py_limited_api=True); it never sets + # the bdist_wheel option itself (gotcha 34 does not apply here), so + # the abi3 tag has to be injected via config-settings (gotcha 11). + CIBW_CONFIG_SETTINGS: --build-option=--py-limited-api=${{ env.ABI3_FLOOR }} + CIBW_TEST_REQUIRES: jinja2 + CIBW_TEST_COMMAND: >- + python3 -m unittest discover --start-directory {package}/test --verbose + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sdbus-${{ env.SDBUS_VERSION }}-cp312-abi3-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + build_freethreaded: + needs: [setup] + name: Build sdbus ${{ inputs.version || '0.14.3' }} cp314t-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 60 + steps: + - name: Checkout sdbus ${{ env.SDBUS_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: python-sdbus/python-sdbus + ref: ${{ env.SDBUS_VERSION }} + persist-credentials: false + + - name: Stage the licence-collection script + run: | + cat > collect-licenses.sh <<'COLLECT_EOF' + #!/bin/bash + # SPDX-FileCopyrightText: 2026 The RISE Project + # SPDX-License-Identifier: MIT + # + # Stage, at the project root, the licence of every shared library + # auditwheel vendors out of the build image alongside libsystemd. + # setuptools' default LICENSE* glob copies them into the wheel. + set -euo pipefail + + project="${1:?usage: collect-licenses.sh }" + + # ldd is transitive, so libsystemd alone covers its whole closure; + # ldd does not list the root itself, so resolve that too. + mapfile -t libs < <( + { + ldd /usr/lib64/libsystemd.so.0 | tr ' ' '\n' | grep '^/' + readlink -f /usr/lib64/libsystemd.so.0 + } | sort -u + ) + + # `rpm -qf` reports unowned files on stdout, so keep only bare package names. + # glibc and the gcc runtime are on auditwheel's manylinux allowlist and + # are never vendored into the wheel. + mapfile -t pkgs < <( + rpm -qf --qf '%{NAME}\n' "${libs[@]}" 2>/dev/null | + grep -E '^[A-Za-z0-9._+-]+$' | sort -u | + grep -vE '^(glibc|libgcc|libstdc\+\+|gcc)$' + ) + + for pkg in "${pkgs[@]}"; do + mapfile -t files < <(rpm -q --licensefiles "$pkg" 2>/dev/null || true) + + # Some subpackages leave the licence to a sibling of the same source RPM. + if [ -z "${files[0]:-}" ]; then + srpm=$(rpm -q --qf '%{SOURCERPM}\n' "$pkg") + mapfile -t files < <( + rpm -qa --qf '%{SOURCERPM} %{NAME}\n' | + awk -v s="$srpm" '$1 == s { print $2 }' | + xargs -r rpm -q --licensefiles 2>/dev/null | sort -u + ) + fi + + # Others mark it %doc rather than %license, and the image installs no docs. + if [ -z "${files[0]:-}" ]; then + dnf -y --disablerepo=extras reinstall --setopt=tsflags= "$pkg" >/dev/null + mapfile -t files < <(rpm -qd "$pkg" | grep -iE '/(LICEN[CS]E|COPYING|NOTICE)') + fi + + for f in "${files[@]}"; do + [ -f "$f" ] || continue + cp "$f" "$project/LICENSE.${pkg}.$(basename "$f")" + done + compgen -G "$project/LICENSE.$pkg.*" >/dev/null || + { echo "no licence file found for $pkg" >&2; exit 1; } + done + + ls -1 "$project"/LICENSE.* | sed "s|$project/||" + COLLECT_EOF + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + env: + CIBW_ARCHS: riscv64 + CIBW_BUILD: cp314t-manylinux_riscv64 + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_BEFORE_ALL_LINUX: >- + dnf install -y systemd-devel dbus-daemon && + bash {project}/collect-licenses.sh {project} + CIBW_TEST_REQUIRES: jinja2 + CIBW_TEST_COMMAND: >- + python3 -m unittest discover --start-directory {package}/test --verbose + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sdbus-${{ env.SDBUS_VERSION }}-cp314t-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + gpl_sources: + needs: [setup] + name: Collect GPL sources for sdbus ${{ inputs.version || '0.14.3' }} + runs-on: ubuntu-24.04-riscv + + steps: + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + # libcap/systemd-libs are the copyleft (GPL/LGPL) libraries auditwheel + # vendors out of the build image alongside libsystemd. + - uses: ./actions/collect-gpl-sources + with: + image: ${{ env.MANYLINUX_RISCV64_IMAGE }} + packages: gcc libcap systemd-libs + output: gpl-sources.tar + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sdbus-${{ env.SDBUS_VERSION }}-gpl-sources + path: gpl-sources.tar + if-no-files-found: error + + publish: + name: Publish sdbus ${{ inputs.version || '0.14.3' }} + needs: [setup, build_abi3, build_freethreaded, gpl_sources] + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + with: + artifact-pattern: sdbus-${{ inputs.version || '0.14.3' }}-*-manylinux_riscv64 + gpl-sources-artifact: sdbus-${{ inputs.version || '0.14.3' }}-gpl-sources + gpl-sources-description: gcc and the copyleft libraries bundled in the wheel From 74c889abe3881d28a5871cfa55979977fd2f0405 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 08:00:27 +0200 Subject: [PATCH 2/2] sdbus: populate D-Bus machine-id and fix test discovery for relative imports --- .github/workflows/build-sdbus.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-sdbus.yml b/.github/workflows/build-sdbus.yml index fc8bfaa30..db1606b2c 100644 --- a/.github/workflows/build-sdbus.yml +++ b/.github/workflows/build-sdbus.yml @@ -130,9 +130,19 @@ jobs: # the bdist_wheel option itself (gotcha 34 does not apply here), so # the abi3 tag has to be injected via config-settings (gotcha 11). CIBW_CONFIG_SETTINGS: --build-option=--py-limited-api=${{ env.ABI3_FLOOR }} + # Matches build-pygame.yml's fix for the same "D-Bus library appears + # to be incorrectly set up" error: the image ships no machine-id. + CIBW_BEFORE_TEST: | + mkdir -p /var/lib/dbus + if [ ! -f /var/lib/dbus/machine-id ]; then + dbus-uuidgen > /var/lib/dbus/machine-id + fi CIBW_TEST_REQUIRES: jinja2 - CIBW_TEST_COMMAND: >- - python3 -m unittest discover --start-directory {package}/test --verbose + # {package}/test is a package (has __init__.py) with relative + # imports, so it must be discovered as a subpackage of {package}, + # not passed as the start directory itself (gotcha: bare + # `--start-directory {package}/test` makes __package__ = ""). + CIBW_TEST_COMMAND: cd {package} && python3 -m unittest discover --verbose - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -226,9 +236,13 @@ jobs: CIBW_BEFORE_ALL_LINUX: >- dnf install -y systemd-devel dbus-daemon && bash {project}/collect-licenses.sh {project} + CIBW_BEFORE_TEST: | + mkdir -p /var/lib/dbus + if [ ! -f /var/lib/dbus/machine-id ]; then + dbus-uuidgen > /var/lib/dbus/machine-id + fi CIBW_TEST_REQUIRES: jinja2 - CIBW_TEST_COMMAND: >- - python3 -m unittest discover --start-directory {package}/test --verbose + CIBW_TEST_COMMAND: cd {package} && python3 -m unittest discover --verbose - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: