From 4a73cb6153f38ca9f1ce7e99061211eb74051ee4 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 21 Sep 2026 15:48:57 +0000 Subject: [PATCH] iterfzf: Add version 1.9.0.67.0 iterfzf is a pure-Python wrapper that bundles the prebuilt fzf binary junegunn/fzf publishes per platform; its PEP 517 backend picks the asset and the wheel's platform tag from two tables that have no riscv64 row. fzf 0.67.0, the version this release bundles, is the first to publish a linux_riscv64 asset, so the port is those two rows plus upstream's own GOOS/GOARCH wheel build narrowed to riscv64. --- .github/workflows/build-iterfzf.yml | 177 ++++++++++++++++++ docs/packages/iterfzf.yaml | 6 + ...t-add-riscv64-to-the-platform-tables.patch | 47 +++++ 3 files changed, 230 insertions(+) create mode 100644 .github/workflows/build-iterfzf.yml create mode 100644 docs/packages/iterfzf.yaml create mode 100644 patches/iterfzf/1.9.0.67.0/0001-build_dist-add-riscv64-to-the-platform-tables.patch diff --git a/.github/workflows/build-iterfzf.yml b/.github/workflows/build-iterfzf.yml new file mode 100644 index 00000000000..485e96217ba --- /dev/null +++ b/.github/workflows/build-iterfzf.yml @@ -0,0 +1,177 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on: https://github.com/dahlia/iterfzf/blob/1.9.0.67.0/.github/workflows/release.yaml +# and https://github.com/dahlia/iterfzf/blob/1.9.0.67.0/.github/workflows/test.yaml +name: Build iterfzf wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/iterfzf.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-iterfzf.yml' + - 'docs/packages/iterfzf.yaml' + - 'patches/iterfzf/**' + push: + branches: [main] + paths: + - '.github/workflows/build-iterfzf.yml' + - 'docs/packages/iterfzf.yaml' + - 'patches/iterfzf/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: iterfzf + version: ${{ inputs.version }} + + build_wheel: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Build iterfzf ${{ matrix.version }} py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 30 + + env: + ITERFZF_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout iterfzf ${{ matrix.version }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: dahlia/iterfzf + ref: ${{ env.ITERFZF_VERSION }} + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Apply patches + run: git apply -v python-wheels/patches/iterfzf/${{ env.ITERFZF_VERSION }}/*.patch + + - name: Install Python + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + python-version: '3.12' + activate-environment: true + enable-cache: false + + - name: Install build + run: uv pip install build + + # GITHUB_TOKEN lifts the anonymous rate limit on the release lookup + # build_dist.py makes to resolve the fzf asset, as upstream's own jobs do. + - name: Build wheel + env: + GITHUB_TOKEN: ${{ github.token }} + run: GOOS=linux GOARCH=riscv64 python -m build --wheel . + + - name: Verify the wheel ships the riscv64 fzf binary + run: | + python - dist/*.whl <<'EOF' + import sys, zipfile + with zipfile.ZipFile(sys.argv[1]) as zf: + names = zf.namelist() + print("\n".join(names)) + assert sys.argv[1].endswith("-py3-none-manylinux_2_39_riscv64.whl"), sys.argv[1] + assert "iterfzf/fzf" in names, names + assert "iterfzf/fzf.exe" not in names, names + licenses = sorted(n.rsplit("/", 1)[-1] for n in names if ".dist-info/licenses/" in n) + assert licenses == ["LICENSE"], licenses + header = zf.read("iterfzf/fzf")[:20] + assert header[:4] == b"\x7fELF", header + assert header[18] == 0xF3, header + EOF + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: iterfzf-${{ env.ITERFZF_VERSION }}-py3-none-manylinux_riscv64 + path: dist/*.whl + if-no-files-found: error + + test_wheel: + name: Test iterfzf ${{ matrix.version }} on Python ${{ matrix.python-version }} + needs: [setup, build_wheel] + if: needs.setup.outputs.versions != '[]' + runs-on: ubuntu-24.04-riscv + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + python-version: ['3.12', '3.13', '3.14', '3.14t'] + + env: + ITERFZF_VERSION: ${{ matrix.version }} + + steps: + - name: Download wheel + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: iterfzf-${{ env.ITERFZF_VERSION }}-py3-none-manylinux_riscv64 + + - name: Install Python + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + python-version: ${{ matrix.python-version }} + activate-environment: true + enable-cache: false + + - name: Install the wheel + run: | + uv pip install --reinstall --no-index --find-links . iterfzf + uv pip install pytest + + # tox.ini's first two commands; the other two assert that iterfzf([]) + # returns None, which raises AttributeError at this tag on every platform. + - name: Run upstream's wheel checks + run: | + python -c "import sys; sys.path.remove(''); from iterfzf import BUNDLED_EXECUTABLE as e; assert e" + python -c "import sys; sys.path.remove(''); from iterfzf import BUNDLED_EXECUTABLE as e; import os; assert os.execl(e, e, '--version') == 0" + + # The suite resolves fzf from PATH, so it runs the wheel's own binary. + # The three deselected cases open the full-screen picker and need an + # interactive terminal, which is why upstream's CI runs tox and not this. + - name: Run upstream's tests + run: | + PATH="$(python -c 'import iterfzf, os; print(os.path.dirname(iterfzf.__file__))'):$PATH" \ + python -m pytest --pyargs iterfzf.test_iterfzf -v \ + -k 'not test_no_query and not test_supports_color_kwarg and not test_select_one_ambiguous' + + publish: + name: Publish iterfzf ${{ matrix.version }} + needs: [setup, build_wheel, test_wheel] + 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: iterfzf-${{ matrix.version }}-py3-none-manylinux_riscv64 diff --git a/docs/packages/iterfzf.yaml b/docs/packages/iterfzf.yaml new file mode 100644 index 00000000000..aeb339b6e8a --- /dev/null +++ b/docs/packages/iterfzf.yaml @@ -0,0 +1,6 @@ +package-name: iterfzf +source-code: https://github.com/dahlia/iterfzf +license: GPL-3.0-or-later +versions: +- version: 1.9.0.67.0 + patched: true diff --git a/patches/iterfzf/1.9.0.67.0/0001-build_dist-add-riscv64-to-the-platform-tables.patch b/patches/iterfzf/1.9.0.67.0/0001-build_dist-add-riscv64-to-the-platform-tables.patch new file mode 100644 index 00000000000..97c3ee23963 --- /dev/null +++ b/patches/iterfzf/1.9.0.67.0/0001-build_dist-add-riscv64-to-the-platform-tables.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 21 Sep 2026 14:05:00 +0000 +Subject: [PATCH] build_dist: add riscv64 to the platform tables + +Upstream-Status: To upstream [not yet submitted; python-wheels does not open issues/PRs on third-party repos] + +build_dist.py bundles the fzf binary published by junegunn/fzf and names the +wheel from two parallel tables. Neither has a riscv64 row, so the build stops +before it downloads anything: + + KeyError: ('linux', 'riscv64') # GOOS/GOARCH given + RuntimeError: unsupported platform: ('linux', 'riscv64') # native build + +fzf 0.67.0, the version this release bundles, is the first to publish +fzf-0.67.0-linux_riscv64.tar.gz, so only the tables are missing. +goos_goarch_platform_tag_map names the wheel; +manylinux_2_39 is the oldest manylinux profile that exists for riscv64 (glibc +2.39, Rocky 10). platform_machine_goos_goarch_map is the native-detection half +that `pip install iterfzf` from the sdist goes through on a riscv64 host; the +two tables are documented as sharing their key order, so both get the row. + +Signed-off-by: Ludovic Henry +--- + build_dist.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/build_dist.py b/build_dist.py +index 6e5f1ae..dda139c 100644 +--- a/build_dist.py ++++ b/build_dist.py +@@ -206,6 +206,7 @@ goos_goarch_platform_tag_map = { + ("linux", "armv6"): "manylinux_1_2_armv6l", + ("linux", "armv7"): "manylinux_1_2_armv7l", + ("linux", "ppc64le"): "manylinux_2_17_ppc64le.manylinux2014_ppc64le", ++ ("linux", "riscv64"): "manylinux_2_39_riscv64", + ("linux", "s390x"): "manylinux_2_17_s390x.manylinux2014_s390x", + ("windows", "amd64"): "win_amd64", + ("windows", "arm64"): "win_arm64", +@@ -227,6 +228,7 @@ platform_machine_goos_goarch_map = { + ("linux", "armv6l"): ("linux", "armv6"), + ("linux", "armv7l"): ("linux", "armv7"), + ("linux", "ppc64le"): ("linux", "ppc64le"), ++ ("linux", "riscv64"): ("linux", "riscv64"), + ("linux", "s390x"): ("linux", "s390x"), + ("win32", "AMD64"): ("windows", "amd64"), + ("win32", "aarch64"): ("windows", "arm64"),