Repository navigation
docs: Update projects #24
Workflow file for this run
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 | |
| --- | |
| # Based on upstream's own Python build/publish tooling at this tag: | |
| # https://github.com/Unleash/yggdrasil-bindings/blob/python-engine-v1.3.1/python-engine/{build.sh,tox.ini,scripts/repair_wheel.py} | |
| # The PyPI package `yggdrasil-engine` is Unleash's ctypes binding to their | |
| # Rust `yggdrasilffi` cdylib, not Google's Yggdrasil Decision Forests. | |
| name: Build yggdrasil-engine wheels (riscv64) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version glob to (re)build; empty builds every version of docs/packages/yggdrasil-engine.yaml not released yet' | |
| required: false | |
| default: '' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-yggdrasil-engine.yml' | |
| - 'docs/packages/yggdrasil-engine.yaml' | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-yggdrasil-engine.yml' | |
| - 'docs/packages/yggdrasil-engine.yaml' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 | |
| jobs: | |
| setup: | |
| uses: $/.github/workflows/_setup.yml | |
| with: | |
| package: yggdrasil-engine | |
| 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 yggdrasil-engine ${{ matrix.version }} cp312-abi3-manylinux_riscv64 | |
| runs-on: ubuntu-24.04-riscv | |
| timeout-minutes: 60 | |
| env: | |
| YGGDRASIL_ENGINE_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Checkout yggdrasil-bindings python-engine-v${{ env.YGGDRASIL_ENGINE_VERSION }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: Unleash/yggdrasil-bindings | |
| ref: python-engine-v${{ env.YGGDRASIL_ENGINE_VERSION }} | |
| persist-credentials: false | |
| # build-python.yml's own "Get client spec" step. | |
| - name: Get client spec | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: Unleash/client-specification | |
| ref: v6.1.0 | |
| path: client-specification | |
| persist-credentials: false | |
| - name: Checkout python-wheels | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: python-wheels | |
| persist-credentials: false | |
| # compat_glibc.rs defines SYS_GETTID/SYS_STATX for x86_64 and aarch64 | |
| # only but compiles unconditionally, so the crate fails to build on | |
| # riscv64. See patches/yggdrasil-engine/1.3.1 for the full rationale. | |
| - name: Patch yggdrasilffi source | |
| run: git apply python-wheels/patches/yggdrasil-engine/${{ env.YGGDRASIL_ENGINE_VERSION }}/00*.patch | |
| # LICENSE.md lives at the repo root; poetry-core only auto-bundles a | |
| # licence file that sits beside pyproject.toml, and upstream's own | |
| # published wheel carries none either (same gap build-valkey-glide.yml | |
| # hit). | |
| - name: Stage the project licence beside pyproject.toml | |
| run: cp LICENSE.md python-engine/LICENSE.md | |
| # Mirrors build-python.yml (build the ffi, `poetry run pytest`) and | |
| # python-engine/build.sh + tox.ini (vendor the binary, `poetry build`, | |
| # repair_wheel.py retags the resulting py3-none-any wheel): upstream | |
| # downloads a prebuilt binary here instead of building it, but ships | |
| # none for riscv64, so this builds it natively in-container. musllinux | |
| # is skipped: rustup ships no riscv64gc-unknown-linux-musl host | |
| # toolchain (gotcha 10). | |
| - name: Write in-container build script | |
| run: | | |
| cat > "$RUNNER_TEMP/build.sh" <<'SCRIPT' | |
| set -euxo pipefail | |
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y | |
| source "$HOME/.cargo/env" | |
| cargo build --release -p yggdrasilffi | |
| pybin=/opt/python/cp312-cp312/bin | |
| "$pybin/pip" install -q poetry-core setuptools build pytest | |
| mkdir -p python-engine/yggdrasil_engine/lib python-engine/staging | |
| cp target/release/libyggdrasilffi.so python-engine/yggdrasil_engine/lib/ | |
| cd python-engine | |
| "$pybin/python3" -m pytest | |
| "$pybin/python3" -m build --wheel --no-isolation | |
| PLATFORM_TAG=manylinux_2_39_riscv64 "$pybin/python3" scripts/repair_wheel.py | |
| SCRIPT | |
| - name: Build wheel | |
| run: | | |
| docker run --rm \ | |
| -v "$(pwd)":/workspace \ | |
| -v "$RUNNER_TEMP/build.sh":/build.sh \ | |
| -w /workspace \ | |
| "${MANYLINUX_RISCV64_IMAGE}" \ | |
| bash /build.sh | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: yggdrasil-engine-${{ env.YGGDRASIL_ENGINE_VERSION }}-cp312-abi3-manylinux_riscv64 | |
| path: python-engine/staging/*.whl | |
| if-no-files-found: error | |
| test_wheel: | |
| name: Test yggdrasil-engine ${{ 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) }} | |
| # abi3 wheels are not compatible with free-threaded interpreters | |
| # (packaging.tags._abi3_applies), matching upstream, which ships no | |
| # cp3XXt wheel either; 3.12/3.13/3.14 exercise the same cp312-abi3 | |
| # wheel via abi3 forward compatibility. | |
| python-version: ['3.12', '3.13', '3.14'] | |
| env: | |
| YGGDRASIL_ENGINE_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Download wheel | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: yggdrasil-engine-${{ env.YGGDRASIL_ENGINE_VERSION }}-cp312-abi3-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 wheel | |
| run: uv pip install --reinstall --no-index --find-links . yggdrasil-engine==${{ env.YGGDRASIL_ENGINE_VERSION }} | |
| # 2.0.0 changed is_enabled from returning Optional[bool] (None for an | |
| # unknown toggle) to returning a FeatureToggle, whose unknown-toggle | |
| # answer is is_enabled=False, is_found=False and whose __bool__ raises | |
| # TypeError (upstream python-engine/tests/test_engine.py, | |
| # test_is_enabled_reports_not_found_when_toggle_missing_without_fallback). | |
| - name: Test wheel | |
| run: | | |
| python -c " | |
| from importlib.metadata import version | |
| from yggdrasil_engine.engine import UnleashEngine | |
| engine = UnleashEngine() | |
| engine.take_state('{\"version\": 2, \"features\": [{\"name\": \"my-toggle\", \"enabled\": true, \"strategies\": [{\"name\": \"default\"}]}]}') | |
| hit = engine.is_enabled('my-toggle', {}) | |
| miss = engine.is_enabled('missing-toggle', {}) | |
| if int(version('yggdrasil-engine').split('.')[0]) >= 2: | |
| assert (hit.name, hit.is_enabled, hit.is_found) == ('my-toggle', True, True), hit | |
| assert (miss.name, miss.is_enabled, miss.is_found) == ('missing-toggle', False, False), miss | |
| else: | |
| assert hit is True, hit | |
| assert miss is None, miss | |
| print('Smoke test passed') | |
| " | |
| publish: | |
| name: Publish yggdrasil-engine ${{ 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: yggdrasil-engine-${{ matrix.version }}-cp312-abi3-manylinux_riscv64 |