From 0e9aedcb52692bc6ee7c911f373ac47580c63874 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 13 Oct 2026 17:59:14 +0000 Subject: [PATCH 1/3] Add pixeltable-pgserver riscv64 wheel build pixeltable-pgserver compiles PostgreSQL 16.14 and 18.4 plus pgvector 0.8.5 from source in its own before-all and bundles them into each wheel. Build from the upstream v0.6.0 tag with cibuildwheel, add the PostgreSQL/pgvector licence texts (patch), stage the licence texts of the grafted image readline/ncurses libraries, and publish the readline source RPM alongside the wheels. --- .../workflows/build-pixeltable-pgserver.yml | 174 ++++++++++++++++++ docs/packages/pixeltable-pgserver.yaml | 6 + ...gresql-and-LICENSE.pgvector-matching.patch | 85 +++++++++ 3 files changed, 265 insertions(+) create mode 100644 .github/workflows/build-pixeltable-pgserver.yml create mode 100644 docs/packages/pixeltable-pgserver.yaml create mode 100644 patches/pixeltable-pgserver/0.6.0/0001-Add-LICENSE.postgresql-and-LICENSE.pgvector-matching.patch diff --git a/.github/workflows/build-pixeltable-pgserver.yml b/.github/workflows/build-pixeltable-pgserver.yml new file mode 100644 index 00000000000..9e47d96e309 --- /dev/null +++ b/.github/workflows/build-pixeltable-pgserver.yml @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on the `build_wheels` job of +# https://github.com/pixeltable/pixeltable-pgserver/blob/v0.6.0/.github/workflows/build-and-test.yml +name: Build pixeltable-pgserver wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/pixeltable-pgserver.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-pixeltable-pgserver.yml' + - 'docs/packages/pixeltable-pgserver.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-pixeltable-pgserver.yml' + - 'docs/packages/pixeltable-pgserver.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: pixeltable-pgserver + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build pixeltable-pgserver ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 300 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # Upstream skips cp314t*. + python: ["cp312", "cp313", "cp314"] + + env: + PIXELTABLE_PGSERVER_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout pixeltable-pgserver v${{ env.PIXELTABLE_PGSERVER_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: pixeltable/pixeltable-pgserver + ref: v${{ env.PIXELTABLE_PGSERVER_VERSION }} + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Patch pixeltable-pgserver source + run: git apply python-wheels/patches/pixeltable-pgserver/${{ env.PIXELTABLE_PGSERVER_VERSION }}/00*.patch + + - 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 }} + # initdb/postgres are non-PIE; keep their base above vm.mmap_min_addr once auditwheel's patchelf prepends a segment (gotcha 595). + CIBW_ENVIRONMENT: >- + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + LDFLAGS="-Wl,-Ttext-segment=0x200000" + # auditwheel grafts the image's libreadline/libtinfo (psql links them); ship their licence texts. + CIBW_BEFORE_BUILD: >- + for p in readline ncurses-libs; do + srpm=$(rpm -q --qf '%{SOURCERPM}' $p); + f=$(rpm -qa --qf '%{SOURCERPM} %{NAME}\n' | awk -v s=$srpm '$1==s{print $2}' | xargs rpm -q --licensefiles | grep -m1 -E '/(COPYING|LICENSE)[^/]*$'); + cp -v "$f" {project}/LICENSE.${p%-libs}; + done + + - name: Verify the wheel ships both postgres servers, pgvector and their licences + run: | + python3 - wheelhouse/*.whl <<'EOF' + import re, sys, zipfile + names = zipfile.ZipFile(sys.argv[1]).namelist() + for inst in ("pginstall", "pginstall18"): + assert f"pixeltable_pgserver/{inst}/bin/postgres" in names, inst + assert f"pixeltable_pgserver/{inst}/lib/postgresql/vector.so" in names, inst + + grafted = {n.split("/")[-1] for n in names if n.startswith("pixeltable_pgserver.libs/") and not n.endswith("/")} + unexpected = {g for g in grafted if not re.match(r"lib(pq|ecpg|ecpg_compat|pgtypes|readline|tinfo|ncursesw?)-", g)} + assert not unexpected, unexpected + + lic = {n.split("/")[-1] for n in names if ".dist-info/licenses/" in n and not n.endswith("/")} + assert {"LICENSE", "LICENSE.postgresql", "LICENSE.pgvector", "LICENSE.readline", "LICENSE.ncurses"} <= lic, lic + EOF + mkdir wheel-check + python3 -m zipfile -e wheelhouse/*.whl wheel-check + for inst in pginstall pginstall18; do + for exe in initdb postgres pg_ctl psql; do + chmod +x "wheel-check/pixeltable_pgserver/$inst/bin/$exe" + "wheel-check/pixeltable_pgserver/$inst/bin/$exe" --version + done + done + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: pixeltable-pgserver-${{ env.PIXELTABLE_PGSERVER_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + gpl_sources: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Collect GPL sources (readline) for pixeltable-pgserver ${{ matrix.version }} + runs-on: ubuntu-24.04-riscv + + env: + PIXELTABLE_PGSERVER_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: ./actions/collect-gpl-sources + with: + image: ${{ env.MANYLINUX_RISCV64_IMAGE }} + packages: readline + output: gpl-sources.tar + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: pixeltable-pgserver-${{ env.PIXELTABLE_PGSERVER_VERSION }}-gpl-sources + path: gpl-sources.tar + if-no-files-found: error + + publish: + name: Publish pixeltable-pgserver ${{ matrix.version }} + needs: [setup, build_wheels, gpl_sources] + 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: pixeltable-pgserver-${{ matrix.version }}-*-manylinux_riscv64 + gpl-sources-artifact: pixeltable-pgserver-${{ matrix.version }}-gpl-sources + gpl-sources-description: readline diff --git a/docs/packages/pixeltable-pgserver.yaml b/docs/packages/pixeltable-pgserver.yaml new file mode 100644 index 00000000000..e389db057d4 --- /dev/null +++ b/docs/packages/pixeltable-pgserver.yaml @@ -0,0 +1,6 @@ +package-name: pixeltable-pgserver +source-code: https://github.com/pixeltable/pixeltable-pgserver +license: Apache-2.0 +versions: +- version: 0.6.0 + patched: true diff --git a/patches/pixeltable-pgserver/0.6.0/0001-Add-LICENSE.postgresql-and-LICENSE.pgvector-matching.patch b/patches/pixeltable-pgserver/0.6.0/0001-Add-LICENSE.postgresql-and-LICENSE.pgvector-matching.patch new file mode 100644 index 00000000000..7d9eff008c6 --- /dev/null +++ b/patches/pixeltable-pgserver/0.6.0/0001-Add-LICENSE.postgresql-and-LICENSE.pgvector-matching.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Tue, 13 Oct 2026 18:00:00 +0000 +Subject: [PATCH] Add LICENSE.postgresql and LICENSE.pgvector matching + setuptools' default glob + +pyproject.toml declares no license-files, so setuptools' default +LICEN[CS]E*/COPYING*/NOTICE*/AUTHORS* glob applies at the project root +only. pixeltable-pgserver's build compiles PostgreSQL 16.14 and 18.4 +and the pgvector 0.8.5 extension from source (pgbuild/Makefile, +fetched at build time from ftp.postgresql.org and +github.com/pgvector/pgvector) and bundles the resulting binaries and +libraries into every wheel, but the checkout carries no license text +for either project, so neither one lands in dist-info/licenses/. + +Add a copy of each project's own license text at the root as +LICENSE.postgresql (PostgreSQL's COPYRIGHT, identical for REL_16_14 +and REL_18_4) and LICENSE.pgvector, which the existing default glob +already matches with no pyproject.toml change. Both are the permissive +PostgreSQL License. + +Upstream-Status: To upstream [not submitted from this automated port run; needs a pull request against pixeltable/pixeltable-pgserver] +--- + LICENSE.pgvector | 20 ++++++++++++++++++++ + LICENSE.postgresql | 23 +++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/LICENSE.pgvector b/LICENSE.pgvector +new file mode 100644 +index 0000000000000000000000000000000000000000..fc5f177fa5d9c0d20a949f4b4faa028999977008 +--- /dev/null ++++ b/LICENSE.pgvector +@@ -0,0 +1,20 @@ ++Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group ++ ++Portions Copyright (c) 1994, The Regents of the University of California ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose, without fee, and without a written agreement ++is hereby granted, provided that the above copyright notice and this ++paragraph and the following two paragraphs appear in all copies. ++ ++IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR ++DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING ++LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS ++DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGE. ++ ++THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, ++INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY ++AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO ++PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +diff --git a/LICENSE.postgresql b/LICENSE.postgresql +new file mode 100644 +index 0000000000000000000000000000000000000000..0a397648dcd3c2177acc58bd7daecd11ad64be62 +--- /dev/null ++++ b/LICENSE.postgresql +@@ -0,0 +1,23 @@ ++PostgreSQL Database Management System ++(also known as Postgres, formerly known as Postgres95) ++ ++Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group ++ ++Portions Copyright (c) 1994, The Regents of the University of California ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose, without fee, and without a written agreement ++is hereby granted, provided that the above copyright notice and this ++paragraph and the following two paragraphs appear in all copies. ++ ++IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR ++DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING ++LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS ++DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGE. ++ ++THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, ++INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY ++AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO ++PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +-- +2.43.0 + From 5e118ca82fa856eb1c43eb156fa433338bf3554b Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 24 Oct 2026 04:30:31 +0000 Subject: [PATCH 2/3] pixeltable-pgserver: install full perl for the PostgreSQL 18 build The PostgreSQL 18.4 release tarball no longer ships the generated catalog headers, so the build runs genbki.pl, which needs FindBin. The riscv64 manylinux image only carries the minimal perl-interpreter, and every cp312/cp313/cp314 job died with "Can't locate FindBin.pm in @INC" right after PostgreSQL 16.14 had built. Override upstream's before-all with the same yum line plus perl. --- .github/workflows/build-pixeltable-pgserver.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-pixeltable-pgserver.yml b/.github/workflows/build-pixeltable-pgserver.yml index 9e47d96e309..30510b12ae9 100644 --- a/.github/workflows/build-pixeltable-pgserver.yml +++ b/.github/workflows/build-pixeltable-pgserver.yml @@ -80,6 +80,10 @@ jobs: only: ${{ matrix.python }}-manylinux_riscv64 env: CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # Upstream's [tool.cibuildwheel.linux] before-all plus `perl`: the PG18 tarball no + # longer ships the generated catalog headers, so genbki.pl runs and needs FindBin, + # which the image's minimal perl-interpreter lacks (gotcha 46). + CIBW_BEFORE_ALL_LINUX: yum install -y flex bison readline-devel perl && make # initdb/postgres are non-PIE; keep their base above vm.mmap_min_addr once auditwheel's patchelf prepends a segment (gotcha 595). CIBW_ENVIRONMENT: >- PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ From 4bd63600febf7e3b050189bab4fe75a39e364555 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 25 Oct 2026 17:56:45 +0000 Subject: [PATCH 3/3] pixeltable-pgserver: build with a newer setuptools so licence files land Upstream's pyproject.toml pins setuptools==73.0.1, which predates PEP 639 entirely -- it has no dist-info/licenses/ directory at all, so the default LICENSE*/COPYING* glob that LICENSE.postgresql, LICENSE.pgvector, LICENSE.readline and LICENSE.ncurses rely on (gotcha 44) is a no-op. Every cp312/cp313/cp314 leg failed identically on the "Verify the wheel ships ... licences" step with AssertionError: set() -- the wheel shipped no licence files whatsoever. setuptools 77.0.3 is the earliest release with that default glob (verified locally: 76.0.0 produces no dist-info/licenses/ entries, 77.0.3 does, for the same root LICENSE files). Preinstall it via CIBW_BEFORE_BUILD and switch to the pip build frontend with --no-build-isolation (gotcha 76) so the preinstalled version is actually used instead of the isolated build env re-resolving upstream's exact pin. --- .github/workflows/build-pixeltable-pgserver.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build-pixeltable-pgserver.yml b/.github/workflows/build-pixeltable-pgserver.yml index 30510b12ae9..8e009f15880 100644 --- a/.github/workflows/build-pixeltable-pgserver.yml +++ b/.github/workflows/build-pixeltable-pgserver.yml @@ -88,8 +88,17 @@ jobs: CIBW_ENVIRONMENT: >- PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ LDFLAGS="-Wl,-Ttext-segment=0x200000" + # Upstream's pyproject.toml pins setuptools==73.0.1, which predates PEP 639 -- + # it has no dist-info/licenses/ concept at all, so the default LICENSE*/COPYING* + # glob that LICENSE.postgresql/LICENSE.pgvector/LICENSE.readline/LICENSE.ncurses + # rely on (gotcha 44) is a no-op and the wheel ships no licence files whatsoever. + # setuptools 77.0.3 is the earliest release with that default glob; preinstall it + # and build with pip's `--no-build-isolation` (gotcha 76) so the preinstalled + # version is actually used instead of the isolated env re-resolving the pin. + CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation" # auditwheel grafts the image's libreadline/libtinfo (psql links them); ship their licence texts. CIBW_BEFORE_BUILD: >- + pip install "setuptools>=77.0.3" "wheel==0.44.0"; for p in readline ncurses-libs; do srpm=$(rpm -q --qf '%{SOURCERPM}' $p); f=$(rpm -qa --qf '%{SOURCERPM} %{NAME}\n' | awk -v s=$srpm '$1==s{print $2}' | xargs rpm -q --licensefiles | grep -m1 -E '/(COPYING|LICENSE)[^/]*$');