RFC 0035: a Python-free type layer #1271
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
| name: Build, test, and publish Python distributions | |
| on: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - "*.*.*" | |
| pull_request: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| actions: read | |
| contents: read | |
| env: | |
| GCC_VERSION: "14" | |
| SCCACHE_GHA_ENABLED: "true" | |
| jobs: | |
| validate-release: | |
| name: Validate release metadata | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Validate package metadata | |
| run: | | |
| python -m pip install --upgrade --only-binary=:all: \ | |
| "packaging==26.3" "trove-classifiers==2026.6.1.19" | |
| python python/tests/test_packaging.py | |
| - name: Validate release tag | |
| if: github.ref_type == 'tag' | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/validate_release.py "$RELEASE_TAG" | |
| reuse-build: | |
| name: Find tested distributions for this commit | |
| needs: validate-release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run-id: ${{ steps.find.outputs.run-id }} | |
| steps: | |
| - name: Find successful build by commit SHA | |
| id: find | |
| if: github.ref_type == 'tag' | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 | |
| with: | |
| script: | | |
| const requiredArtifacts = new Set([ | |
| "distribution-sdist", | |
| "distribution-wheel-macos-26", | |
| "distribution-wheel-ubuntu-latest", | |
| "distribution-wheel-windows-latest", | |
| "kafka-distribution-sdist", | |
| "kafka-distribution-wheel-macos-26", | |
| "kafka-distribution-wheel-ubuntu-latest", | |
| "kafka-distribution-wheel-windows-latest", | |
| "analytics-distribution-sdist", | |
| "analytics-distribution-wheel-macos-26", | |
| "analytics-distribution-wheel-ubuntu-latest", | |
| "analytics-distribution-wheel-windows-latest", | |
| "persistence-distribution-sdist", | |
| "persistence-distribution-wheel-macos-26", | |
| "persistence-distribution-wheel-ubuntu-latest", | |
| "persistence-distribution-wheel-windows-latest", | |
| "fabric-distribution-sdist", | |
| "fabric-distribution-wheel-macos-26", | |
| "fabric-distribution-wheel-ubuntu-latest", | |
| "fabric-distribution-wheel-windows-latest", | |
| "web-distribution-sdist", | |
| "web-distribution-wheel-macos-26", | |
| "web-distribution-wheel-ubuntu-latest", | |
| "web-distribution-wheel-windows-latest", | |
| ]); | |
| const runs = await github.paginate( | |
| github.rest.actions.listWorkflowRuns, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| workflow_id: "release-wheels.yml", | |
| event: "push", | |
| head_sha: context.sha, | |
| status: "success", | |
| per_page: 100, | |
| }, | |
| ); | |
| for (const run of runs) { | |
| if (run.head_sha !== context.sha || run.id === context.runId) { | |
| continue; | |
| } | |
| const artifacts = await github.paginate( | |
| github.rest.actions.listWorkflowRunArtifacts, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: run.id, | |
| per_page: 100, | |
| }, | |
| ); | |
| const availableArtifacts = new Set( | |
| artifacts | |
| .filter((artifact) => !artifact.expired) | |
| .map((artifact) => artifact.name), | |
| ); | |
| if ([...requiredArtifacts].every((name) => availableArtifacts.has(name))) { | |
| core.notice(`Reusing tested distributions from workflow run ${run.id}`); | |
| core.setOutput("run-id", String(run.id)); | |
| return; | |
| } | |
| } | |
| core.notice(`No reusable distributions found for commit ${context.sha}`); | |
| core.setOutput("run-id", ""); | |
| build-windows-wheel: | |
| name: Build Windows wheel artifacts | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| if: needs.reuse-build.outputs.run-id == '' | |
| uses: ./.github/workflows/release-platform-wheel.yml | |
| with: | |
| os: windows-latest | |
| parallel: "4" | |
| # Ninja (not the Visual Studio generator): MSBuild ignores | |
| # CMAKE_CXX_COMPILER_LAUNCHER, so sccache never fires under the VS | |
| # generator. /Z7 keeps debug-carrying configurations cacheable because | |
| # sccache cannot cache /Zi's shared PDB. | |
| cmake_args: >- | |
| -DHGRAPH_WARNINGS_AS_ERRORS=OFF | |
| -DCMAKE_POLICY_DEFAULT_CMP0141=NEW | |
| "-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>" | |
| build-macos-wheel: | |
| name: Build macOS wheel artifacts | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| if: needs.reuse-build.outputs.run-id == '' | |
| uses: ./.github/workflows/release-platform-wheel.yml | |
| with: | |
| os: macos-26 | |
| parallel: "1" | |
| cmake_args: -DHGRAPH_WARNINGS_AS_ERRORS=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 | |
| build-linux-wheel: | |
| name: Build manylinux 2.28 / GCC 14 wheel | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| if: needs.reuse-build.outputs.run-id == '' | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: quay.io/pypa/manylinux_2_28_x86_64:latest | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - name: Enable shared compiler cache | |
| uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 | |
| with: | |
| version: v0.15.0 | |
| - name: Verify official build toolchain | |
| shell: bash | |
| run: | | |
| g++ --version | |
| test "$(g++ -dumpfullversion -dumpversion | cut -d. -f1)" -eq "$GCC_VERSION" | |
| echo "CC=$(command -v gcc)" >> "$GITHUB_ENV" | |
| echo "CXX=$(command -v g++)" >> "$GITHUB_ENV" | |
| /opt/python/cp312-cp312/bin/python --version | |
| - name: Install wheel build tools | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python -m pip install --upgrade | |
| --only-binary=:all: "build==1.5.0" "abi3audit==0.0.26" | |
| "auditwheel==6.7.0" | |
| - name: Build stable ABI wheel | |
| env: | |
| CMAKE_GENERATOR: Ninja | |
| CMAKE_ARGS: -DHGRAPH_WARNINGS_AS_ERRORS=ON | |
| CMAKE_BUILD_PARALLEL_LEVEL: "2" | |
| run: /opt/python/cp312-cp312/bin/python -m build --wheel | |
| - name: Audit wheel contents | |
| run: /opt/python/cp312-cp312/bin/python tools/audit_distribution.py "dist/*.whl" | |
| - name: Repair for the glibc 2.28 floor | |
| run: | | |
| mkdir wheelhouse | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir wheelhouse \ | |
| dist/*.whl | |
| rm dist/*.whl | |
| mv wheelhouse/*.whl dist/ | |
| - name: Verify wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: distribution-wheel-ubuntu-latest | |
| path: dist/*.whl | |
| if-no-files-found: error | |
| - name: Install the matching core SDK | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python -m pip install | |
| --only-binary=:all: dist/*.whl | |
| - name: Install Kafka wheel build tools | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python -m pip install --upgrade | |
| --only-binary=:all: "scikit-build-core==1.0.3" | |
| "nanobind==2.13.0" "ninja==1.13.0" "pyarrow==25.0.0" | |
| - name: Build Kafka stable ABI wheel | |
| shell: bash | |
| run: | | |
| hgraph_sdk="$(/opt/python/cp312-cp312/bin/python -c 'import site; print(site.getsitepackages()[0])')" | |
| CMAKE_GENERATOR=Ninja \ | |
| CMAKE_ARGS=-DHGRAPH_WARNINGS_AS_ERRORS=ON \ | |
| CMAKE_BUILD_PARALLEL_LEVEL=2 \ | |
| CMAKE_PREFIX_PATH="$hgraph_sdk" \ | |
| /opt/python/cp312-cp312/bin/python -m build \ | |
| --wheel --no-isolation --skip-dependency-check \ | |
| --outdir kafka-dist-raw extensions/kafka | |
| - name: Repair Kafka wheel for the glibc 2.28 floor | |
| run: | | |
| mkdir kafka-dist | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir kafka-dist \ | |
| kafka-dist-raw/*.whl | |
| - name: Verify Kafka wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("kafka-dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| assert wheel.name.startswith("hgraph_kafka-"), wheel.name | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - name: Audit Kafka wheel contents | |
| run: /opt/python/cp312-cp312/bin/python extensions/kafka/tools/audit_distribution.py "kafka-dist/*.whl" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: kafka-distribution-wheel-ubuntu-latest | |
| path: kafka-dist/*.whl | |
| if-no-files-found: error | |
| - name: Build analytics stable ABI wheel | |
| shell: bash | |
| run: | | |
| hgraph_sdk="$(/opt/python/cp312-cp312/bin/python -c 'import site; print(site.getsitepackages()[0])')" | |
| CMAKE_GENERATOR=Ninja \ | |
| CMAKE_ARGS=-DHGRAPH_WARNINGS_AS_ERRORS=ON \ | |
| CMAKE_BUILD_PARALLEL_LEVEL=2 \ | |
| CMAKE_PREFIX_PATH="$hgraph_sdk" \ | |
| /opt/python/cp312-cp312/bin/python -m build \ | |
| --wheel --no-isolation --skip-dependency-check \ | |
| --outdir analytics-dist-raw extensions/analytics | |
| - name: Repair analytics wheel for the glibc 2.28 floor | |
| run: | | |
| mkdir analytics-dist | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir analytics-dist \ | |
| analytics-dist-raw/*.whl | |
| - name: Verify analytics wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("analytics-dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| assert wheel.name.startswith("hgraph_analytics-"), wheel.name | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - name: Audit analytics wheel contents | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python | |
| extensions/analytics/tools/audit_distribution.py | |
| "analytics-dist/*.whl" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: analytics-distribution-wheel-ubuntu-latest | |
| path: analytics-dist/*.whl | |
| if-no-files-found: error | |
| - name: Install persistence wheel TLS dependency | |
| # The shared persistence SDK carries the pinned curl used for S3 | |
| # conditional writes; auditwheel vendors its TLS runtime libraries. | |
| shell: bash | |
| run: dnf install -y openssl-devel | |
| - name: Build persistence stable ABI wheel | |
| shell: bash | |
| run: | | |
| hgraph_sdk="$(/opt/python/cp312-cp312/bin/python -c 'import site; print(site.getsitepackages()[0])')" | |
| CMAKE_GENERATOR=Ninja \ | |
| CMAKE_ARGS=-DHGRAPH_WARNINGS_AS_ERRORS=ON \ | |
| CMAKE_BUILD_PARALLEL_LEVEL=2 \ | |
| CMAKE_PREFIX_PATH="$hgraph_sdk" \ | |
| /opt/python/cp312-cp312/bin/python -m build \ | |
| --wheel --no-isolation --skip-dependency-check \ | |
| --outdir persistence-dist-raw extensions/persistence | |
| - name: Repair persistence wheel for the glibc 2.28 floor | |
| run: | | |
| mkdir persistence-dist | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libparquet.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir persistence-dist \ | |
| persistence-dist-raw/*.whl | |
| - name: Verify persistence wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("persistence-dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| assert wheel.name.startswith("hgraph_persistence-"), wheel.name | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - name: Audit persistence wheel contents | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python | |
| extensions/persistence/tools/audit_distribution.py | |
| "persistence-dist/*.whl" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: persistence-distribution-wheel-ubuntu-latest | |
| path: persistence-dist/*.whl | |
| if-no-files-found: error | |
| - name: Install the matching persistence SDK | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python -m pip install | |
| --no-deps persistence-dist/*.whl | |
| - name: Build Fabric stable ABI wheel | |
| shell: bash | |
| run: | | |
| hgraph_sdk="$(/opt/python/cp312-cp312/bin/python -c 'import site; print(site.getsitepackages()[0])')" | |
| CMAKE_GENERATOR=Ninja \ | |
| CMAKE_ARGS=-DHGRAPH_WARNINGS_AS_ERRORS=ON \ | |
| CMAKE_BUILD_PARALLEL_LEVEL=2 \ | |
| CMAKE_PREFIX_PATH="$hgraph_sdk" \ | |
| /opt/python/cp312-cp312/bin/python -m build \ | |
| --wheel --no-isolation --skip-dependency-check \ | |
| --outdir fabric-dist-raw extensions/fabric | |
| - name: Repair Fabric wheel for the glibc 2.28 floor | |
| run: | | |
| mkdir fabric-dist | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libparquet.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libhgraph_persistence.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir fabric-dist \ | |
| fabric-dist-raw/*.whl | |
| - name: Verify Fabric wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("fabric-dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| assert wheel.name.startswith("hgraph_fabric-"), wheel.name | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - name: Audit Fabric wheel contents | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python | |
| extensions/fabric/tools/audit_distribution.py | |
| "fabric-dist/*.whl" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: fabric-distribution-wheel-ubuntu-latest | |
| path: fabric-dist/*.whl | |
| if-no-files-found: error | |
| - name: Install web wheel system dependencies | |
| # The web extension's TLS stack builds against the container's | |
| # OpenSSL headers; auditwheel then vendors the shared libraries | |
| # (RFC 0024, packaging). | |
| run: dnf install -y openssl-devel | |
| - name: Build web stable ABI wheel | |
| shell: bash | |
| run: | | |
| hgraph_sdk="$(/opt/python/cp312-cp312/bin/python -c 'import site; print(site.getsitepackages()[0])')" | |
| CMAKE_GENERATOR=Ninja \ | |
| CMAKE_ARGS=-DHGRAPH_WARNINGS_AS_ERRORS=ON \ | |
| CMAKE_BUILD_PARALLEL_LEVEL=2 \ | |
| CMAKE_PREFIX_PATH="$hgraph_sdk" \ | |
| /opt/python/cp312-cp312/bin/python -m build \ | |
| --wheel --no-isolation --skip-dependency-check \ | |
| --outdir web-dist-raw extensions/web | |
| - name: Repair web wheel for the glibc 2.28 floor | |
| run: | | |
| mkdir web-dist | |
| auditwheel repair \ | |
| --plat manylinux_2_28_x86_64 \ | |
| --exclude libarrow.so.2500 \ | |
| --exclude libarrow_compute.so.2500 \ | |
| --exclude libarrow_acero.so.2500 \ | |
| --exclude libhgraph_runtime.so \ | |
| --exclude libhgraph_wiring.so \ | |
| --exclude libhgraph_stdlib.so \ | |
| --exclude libnanobind-abi3.so \ | |
| --wheel-dir web-dist \ | |
| web-dist-raw/*.whl | |
| - name: Verify web wheel ABI and platform tag | |
| run: | | |
| /opt/python/cp312-cp312/bin/python - <<'PY' | |
| from pathlib import Path | |
| import subprocess | |
| from packaging.tags import Tag | |
| from packaging.utils import parse_wheel_filename | |
| wheels = list(Path("web-dist").glob("*.whl")) | |
| assert len(wheels) == 1, wheels | |
| wheel = wheels[0] | |
| assert wheel.name.startswith("hgraph_web-"), wheel.name | |
| tags = parse_wheel_filename(wheel.name)[3] | |
| expected = Tag("cp312", "abi3", "manylinux_2_28_x86_64") | |
| assert expected in tags, (wheel.name, tags) | |
| subprocess.check_call(["abi3audit", "--strict", str(wheel)]) | |
| PY | |
| - name: Audit web wheel contents | |
| run: >- | |
| /opt/python/cp312-cp312/bin/python | |
| extensions/web/tools/audit_distribution.py | |
| "web-dist/*.whl" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: web-distribution-wheel-ubuntu-latest | |
| path: web-dist/*.whl | |
| if-no-files-found: error | |
| build-sdist: | |
| name: Build source distribution | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| if: needs.reuse-build.outputs.run-id == '' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Build source distribution | |
| run: | | |
| python -m pip install --upgrade --only-binary=:all: \ | |
| "build==1.5.0" "scikit-build-core==1.0.3" \ | |
| "nanobind==2.13.0" "pyarrow==25.0.0" | |
| python -m build --sdist | |
| - name: Audit source distribution contents | |
| run: python tools/audit_distribution.py "dist/*.tar.gz" | |
| - name: Verify source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tomllib | |
| version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"] | |
| archives = list(Path("dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| assert archives[0].name == f"hgraph-{version}.tar.gz", archives[0].name | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: distribution-sdist | |
| path: dist/*.tar.gz | |
| if-no-files-found: error | |
| - name: Build Kafka source distribution | |
| run: >- | |
| python -m build --sdist --no-isolation --skip-dependency-check | |
| --outdir kafka-dist extensions/kafka | |
| - name: Verify Kafka source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tarfile | |
| import tomllib | |
| version = tomllib.loads( | |
| Path("extensions/kafka/pyproject.toml").read_text() | |
| )["project"]["version"] | |
| archives = list(Path("kafka-dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| archive = archives[0] | |
| assert archive.name == f"hgraph_kafka-{version}.tar.gz", archive.name | |
| with tarfile.open(archive) as package: | |
| names = set(package.getnames()) | |
| root = f"hgraph_kafka-{version}" | |
| for required in ( | |
| "CMakeLists.txt", | |
| "include/hgraph/kafka/service.h", | |
| "python/hgraph_kafka/__init__.py", | |
| ): | |
| assert f"{root}/{required}" in names, required | |
| - name: Audit Kafka source distribution contents | |
| run: python extensions/kafka/tools/audit_distribution.py "kafka-dist/*.tar.gz" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: kafka-distribution-sdist | |
| path: kafka-dist/*.tar.gz | |
| if-no-files-found: error | |
| - name: Build analytics source distribution | |
| run: >- | |
| python -m build --sdist --no-isolation --skip-dependency-check | |
| --outdir analytics-dist extensions/analytics | |
| - name: Verify analytics source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tarfile | |
| import tomllib | |
| version = tomllib.loads( | |
| Path("extensions/analytics/pyproject.toml").read_text() | |
| )["project"]["version"] | |
| archives = list(Path("analytics-dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| archive = archives[0] | |
| assert archive.name == f"hgraph_analytics-{version}.tar.gz", archive.name | |
| with tarfile.open(archive) as package: | |
| names = set(package.getnames()) | |
| root = f"hgraph_analytics-{version}" | |
| for required in ( | |
| "CMakeLists.txt", | |
| "include/hgraph/analytics/operators.h", | |
| "python/hgraph_analytics/__init__.py", | |
| ): | |
| assert f"{root}/{required}" in names, required | |
| - name: Audit analytics source distribution contents | |
| run: >- | |
| python extensions/analytics/tools/audit_distribution.py | |
| "analytics-dist/*.tar.gz" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: analytics-distribution-sdist | |
| path: analytics-dist/*.tar.gz | |
| if-no-files-found: error | |
| - name: Build persistence source distribution | |
| run: >- | |
| python -m build --sdist --no-isolation --skip-dependency-check | |
| --outdir persistence-dist extensions/persistence | |
| - name: Verify persistence source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tarfile | |
| import tomllib | |
| version = tomllib.loads( | |
| Path("extensions/persistence/pyproject.toml").read_text() | |
| )["project"]["version"] | |
| archives = list(Path("persistence-dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| archive = archives[0] | |
| assert archive.name == f"hgraph_persistence-{version}.tar.gz", archive.name | |
| with tarfile.open(archive) as package: | |
| names = set(package.getnames()) | |
| root = f"hgraph_persistence-{version}" | |
| for required in ( | |
| "CMakeLists.txt", | |
| "include/hgraph/persistence/frame_store.h", | |
| "include/hgraph/persistence/recording_store.h", | |
| "python/hgraph_persistence/__init__.py", | |
| ): | |
| assert f"{root}/{required}" in names, required | |
| - name: Audit persistence source distribution contents | |
| run: >- | |
| python extensions/persistence/tools/audit_distribution.py | |
| "persistence-dist/*.tar.gz" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: persistence-distribution-sdist | |
| path: persistence-dist/*.tar.gz | |
| if-no-files-found: error | |
| - name: Build Fabric source distribution | |
| run: >- | |
| python -m build --sdist --no-isolation --skip-dependency-check | |
| --outdir fabric-dist extensions/fabric | |
| - name: Verify Fabric source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tarfile | |
| import tomllib | |
| version = tomllib.loads( | |
| Path("extensions/fabric/pyproject.toml").read_text() | |
| )["project"]["version"] | |
| archives = list(Path("fabric-dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| archive = archives[0] | |
| assert archive.name == f"hgraph_fabric-{version}.tar.gz", archive.name | |
| with tarfile.open(archive) as package: | |
| names = set(package.getnames()) | |
| root = f"hgraph_fabric-{version}" | |
| for required in ( | |
| "CMakeLists.txt", | |
| "include/hgraph/fabric/service.h", | |
| "python/hgraph_fabric/__init__.py", | |
| ): | |
| assert f"{root}/{required}" in names, required | |
| - name: Audit Fabric source distribution contents | |
| run: >- | |
| python extensions/fabric/tools/audit_distribution.py | |
| "fabric-dist/*.tar.gz" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: fabric-distribution-sdist | |
| path: fabric-dist/*.tar.gz | |
| if-no-files-found: error | |
| - name: Build web source distribution | |
| run: >- | |
| python -m build --sdist --no-isolation --skip-dependency-check | |
| --outdir web-dist extensions/web | |
| - name: Verify web source distribution | |
| shell: python | |
| run: | | |
| from pathlib import Path | |
| import tarfile | |
| import tomllib | |
| version = tomllib.loads( | |
| Path("extensions/web/pyproject.toml").read_text() | |
| )["project"]["version"] | |
| archives = list(Path("web-dist").glob("*.tar.gz")) | |
| assert len(archives) == 1, archives | |
| archive = archives[0] | |
| assert archive.name == f"hgraph_web-{version}.tar.gz", archive.name | |
| with tarfile.open(archive) as package: | |
| names = set(package.getnames()) | |
| root = f"hgraph_web-{version}" | |
| for required in ( | |
| "CMakeLists.txt", | |
| "include/hgraph/web/service.h", | |
| "python/hgraph_web/__init__.py", | |
| ): | |
| assert f"{root}/{required}" in names, required | |
| - name: Audit web source distribution contents | |
| run: >- | |
| python extensions/web/tools/audit_distribution.py | |
| "web-dist/*.tar.gz" | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: web-distribution-sdist | |
| path: web-dist/*.tar.gz | |
| if-no-files-found: error | |
| test-windows-wheel: | |
| name: Test Windows wheel artifacts | |
| needs: | |
| - reuse-build | |
| - build-windows-wheel | |
| if: needs.reuse-build.outputs.run-id == '' | |
| uses: ./.github/workflows/test-platform-wheel.yml | |
| with: | |
| os: windows-latest | |
| test-macos-wheel: | |
| name: Test macOS wheel artifacts | |
| needs: | |
| - reuse-build | |
| - build-macos-wheel | |
| if: needs.reuse-build.outputs.run-id == '' | |
| uses: ./.github/workflows/test-platform-wheel.yml | |
| with: | |
| os: macos-26 | |
| test-linux-wheel: | |
| name: Test Linux wheel artifacts | |
| needs: | |
| - reuse-build | |
| - build-linux-wheel | |
| if: needs.reuse-build.outputs.run-id == '' | |
| uses: ./.github/workflows/test-platform-wheel.yml | |
| with: | |
| os: ubuntu-latest | |
| parity-smoke: | |
| name: Differential parity smoke / Python 3.14 | |
| needs: | |
| - reuse-build | |
| - build-linux-wheel | |
| if: needs.reuse-build.outputs.run-id == '' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install parity controller | |
| run: >- | |
| python -m pip install --upgrade --only-binary=:all: | |
| "uv==0.12.3" "hypothesis==6.165.2" | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| name: distribution-wheel-ubuntu-latest | |
| path: dist | |
| # The reference hgraph 0.5 serves the frame-recording scenarios | |
| # natively; the candidate needs core + hgraph-persistence (RFC 0025). | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| name: persistence-distribution-wheel-ubuntu-latest | |
| path: persistence-dist | |
| - name: Restore released-hgraph traces | |
| uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 | |
| with: | |
| path: | | |
| .parity/envs/reference-* | |
| .parity/cache/reference-traces | |
| key: parity-reference-${{ runner.os }}-py314-${{ hashFiles('tools/parity/**/*.py') }} | |
| restore-keys: | | |
| parity-reference-${{ runner.os }}-py314- | |
| - name: Run fixed corpus and deterministic generated matrix | |
| run: >- | |
| python -m tools.parity campaign | |
| --profile pr | |
| --seed 20260726 | |
| --candidate-wheel dist/*.whl | |
| --candidate-extra-wheel persistence-dist/*.whl | |
| --output-dir parity-results | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| if: always() | |
| with: | |
| name: parity-smoke | |
| path: parity-results | |
| if-no-files-found: error | |
| publish: | |
| name: Publish hgraph to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist | |
| publish-kafka: | |
| name: Publish hgraph-kafka to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph-kafka | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: kafka-distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp Kafka distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish Kafka package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist | |
| publish-analytics: | |
| name: Publish hgraph-analytics to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph-analytics | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: analytics-distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp analytics distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish analytics package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist | |
| publish-web: | |
| name: Publish hgraph-web to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph-web | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: web-distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp web distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish web package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist | |
| publish-persistence: | |
| name: Publish hgraph-persistence to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph-persistence | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: persistence-distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp persistence distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish persistence package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist | |
| publish-fabric: | |
| name: Publish hgraph-fabric to PyPI | |
| if: >- | |
| always() && | |
| github.ref_type == 'tag' && | |
| needs.validate-release.result == 'success' && | |
| needs.reuse-build.result == 'success' && | |
| ( | |
| needs.reuse-build.outputs.run-id != '' || | |
| ( | |
| needs.build-sdist.result == 'success' && | |
| needs.test-windows-wheel.result == 'success' && | |
| needs.test-macos-wheel.result == 'success' && | |
| needs.test-linux-wheel.result == 'success' | |
| ) | |
| ) | |
| needs: | |
| - validate-release | |
| - reuse-build | |
| - build-sdist | |
| - test-windows-wheel | |
| - test-macos-wheel | |
| - test-linux-wheel | |
| - build-linux-wheel | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/hgraph-fabric | |
| permissions: | |
| actions: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 | |
| with: | |
| pattern: fabric-distribution-* | |
| path: dist | |
| merge-multiple: true | |
| github-token: ${{ github.token }} | |
| run-id: ${{ needs.reuse-build.outputs.run-id || github.run_id }} | |
| - name: Restamp Fabric distributions to the tag version | |
| env: | |
| RELEASE_TAG: ${{ github.ref_name }} | |
| run: python tools/restamp_distribution.py dist "$RELEASE_TAG" | |
| - name: Publish Fabric package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 | |
| with: | |
| packages-dir: dist |