ci: open the nightly PRs as the riseproject-dev github app #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-FileCopyrightText: 2026 The RISE Project | |
| # SPDX-License-Identifier: MIT | |
| --- | |
| # This workflow is based on: https://github.com/xrootd/xrootd/blob/master/.github/workflows/python.yml | |
| name: Build xrootd wheels (riscv64) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version glob to (re)build; empty builds every version of docs/packages/xrootd.yaml not released yet' | |
| required: false | |
| default: '' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-xrootd.yml' | |
| - 'docs/packages/xrootd.yaml' | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-xrootd.yml' | |
| - 'docs/packages/xrootd.yaml' | |
| 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: xrootd | |
| version: ${{ inputs.version }} | |
| build_wheels: | |
| needs: [setup] | |
| if: needs.setup.outputs.versions != '[]' | |
| name: Build xrootd ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 | |
| runs-on: ubuntu-24.04-riscv | |
| timeout-minutes: 120 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| version: ${{ fromJSON(needs.setup.outputs.versions) }} | |
| python: ["cp312", "cp313", "cp314", "cp314t"] | |
| env: | |
| XROOTD_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Checkout xrootd v${{ env.XROOTD_VERSION }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: xrootd/xrootd | |
| ref: v${{ env.XROOTD_VERSION }} | |
| persist-credentials: false | |
| # The tag's VERSION file is an unexpanded `git-archive` export-subst | |
| # placeholder (`$Format:%(describe)$`); setup.py and CMake both fall | |
| # back to `git describe`, which a shallow single-ref checkout can't | |
| # answer. Writing the real version here is the officially supported | |
| # override (cmake/XRootDVersion.cmake reads this file first). | |
| - name: Set version from tag | |
| run: echo -n '${{ env.XROOTD_VERSION }}' > VERSION | |
| - 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 the XRootD | |
| # client libraries (OpenSSL, Kerberos, libuuid and their closure). | |
| # setuptools' default LICENSE* glob copies them into the wheel. | |
| set -euo pipefail | |
| project="${1:?usage: collect-licenses.sh <project-dir>}" | |
| # ldd is transitive, so these roots cover their whole closure; ldd | |
| # does not list the roots themselves, so resolve those too. libcrypt | |
| # is not pulled in by any -devel package above: XrdUtils' own CMake | |
| # probes for crypt() directly and links libc-adjacent libxcrypt, | |
| # which the base image already ships. | |
| mapfile -t libs < <( | |
| { | |
| for root in libssl.so libcrypto.so libkrb5.so libuuid.so libcrypt.so; do | |
| path="/usr/lib64/${root}" | |
| [ -e "${path}" ] || continue | |
| ldd "${path}" | tr ' ' '\n' | grep '^/' | |
| readlink -f "${path}" | |
| done | |
| } | sort -u | |
| ) | |
| # `rpm -qf` reports unowned files on stdout, so keep only bare package names. | |
| # glibc, the gcc runtime and zlib are on auditwheel's manylinux allowlist | |
| # (confirmed against the upstream x86_64 wheel's auditwheel-vendored set) | |
| # and are never vendored into the wheel; zlib-ng-compat also ships no | |
| # licence file via any rpm metadata path, so it would break the loop below. | |
| 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|zlib-ng-compat)$' | |
| ) | |
| 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/ | |
| only: ${{ matrix.python }}-manylinux_riscv64 | |
| env: | |
| CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} | |
| CIBW_BEFORE_ALL_LINUX: >- | |
| dnf install -y krb5-devel libuuid-devel openssl-devel && | |
| bash {project}/collect-licenses.sh {project} | |
| CIBW_ENVIRONMENT: CMAKE_ARGS=-DCMAKE_BUILD_TYPE=Release | |
| # Upstream's own manylinux job test step (python.yml): import the | |
| # extension and the pure-Python client, then build a FileSystem | |
| # object (no network I/O, so no server needed). | |
| CIBW_TEST_COMMAND: | | |
| python -m pip show xrootd && | |
| python -c "import XRootD; print(XRootD)" && | |
| python -c "import pyxrootd; print(pyxrootd)" && | |
| python -c "from XRootD import client; help(client)" && | |
| python -c "from XRootD import client; print(client.FileSystem('root://localhost'))" | |
| - name: Verify the wheel ships the compiled extension and licences | |
| run: | | |
| python3 - wheelhouse/*.whl <<'EOF' | |
| import sys, zipfile | |
| names = zipfile.ZipFile(sys.argv[1]).namelist() | |
| sos = sorted(n for n in names if n.endswith(".so")) | |
| print("\n".join(sos)) | |
| assert any("/client.cpython" in "/" + n for n in sos), sos | |
| lic = sorted(n.split("/")[-1] for n in names if ".dist-info/licenses/" in n and not n.endswith("/")) | |
| print("\n".join(lic)) | |
| expected_pkgs = {"openssl-libs", "krb5-libs", "libuuid", "libxcrypt"} | |
| have_pkgs = {f.split(".", 2)[1] for f in lic if f.startswith("LICENSE.")} | |
| assert expected_pkgs <= have_pkgs, expected_pkgs - have_pkgs | |
| EOF | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: xrootd-${{ env.XROOTD_VERSION }}-${{ matrix.python }}-manylinux_riscv64 | |
| path: wheelhouse/*.whl | |
| if-no-files-found: error | |
| publish: | |
| name: Publish xrootd ${{ 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: xrootd-${{ matrix.version }}-*-manylinux_riscv64 |