From ae68ca936677fc1f8a312347e257f4a3a13046e3 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 19 Aug 2026 16:31:46 -0500 Subject: [PATCH 1/3] ci: update Linux runner labels Signed-off-by: Will Killian --- .github/workflows/ci.yaml | 12 ++++++------ .github/workflows/ci_changes.yml | 2 +- .github/workflows/ci_check.yml | 6 +++--- .github/workflows/ci_go.yml | 4 ++-- .github/workflows/ci_license_diff.yml | 2 +- .github/workflows/ci_node.yml | 10 +++++----- .github/workflows/ci_python.yml | 10 +++++----- .github/workflows/ci_rust.yml | 12 ++++++------ .github/workflows/fern-docs.yml | 10 +++++----- .github/workflows/nightly-alpha-tag.yaml | 4 ++-- .github/workflows/pr-labels.yaml | 2 +- .github/workflows/stale.yaml | 2 +- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ae107c9c1..2c8e23f1a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,7 @@ jobs: # Executes the get-pr-info action to determine if the PR has the skip-ci label, if the action fails we assume the # PR does not have the label name: Prepare - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 permissions: pull-requests: read steps: @@ -202,7 +202,7 @@ jobs: - ci_node - ci_python if: ${{ always() && !cancelled() && needs.prepare.result == 'success' && ! fromJSON(needs.prepare.outputs.has_skip_ci_label) }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 permissions: contents: read steps: @@ -260,7 +260,7 @@ jobs: name: Release Distribution Artifacts needs: [prepare, ci_required] if: ${{ needs.prepare.outputs.publish_packages == 'true' && needs.ci_required.result == 'success' }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 15 permissions: contents: write @@ -353,7 +353,7 @@ jobs: name: Publish (crates.io) needs: [prepare, ci_required] if: ${{ needs.prepare.outputs.publish_packages == 'true' && needs.ci_required.result == 'success' }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 30 permissions: contents: read @@ -429,7 +429,7 @@ jobs: name: Publish (PyPI) needs: [prepare, ci_required] if: ${{ needs.prepare.outputs.publish_packages == 'true' && needs.ci_required.result == 'success' }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 30 permissions: contents: read @@ -491,7 +491,7 @@ jobs: name: Publish (npm) needs: [prepare, ci_required] if: ${{ needs.prepare.outputs.publish_packages == 'true' && needs.ci_required.result == 'success' }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 30 permissions: contents: read diff --git a/.github/workflows/ci_changes.yml b/.github/workflows/ci_changes.yml index 0d7ea81c7..d61188db7 100644 --- a/.github/workflows/ci_changes.yml +++ b/.github/workflows/ci_changes.yml @@ -67,7 +67,7 @@ on: jobs: changes: name: Detect - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 10 permissions: contents: read diff --git a/.github/workflows/ci_check.yml b/.github/workflows/ci_check.yml index 7f33e9ca0..54ea8b00b 100644 --- a/.github/workflows/ci_check.yml +++ b/.github/workflows/ci_check.yml @@ -49,11 +49,11 @@ jobs: matrix: include: - platform: linux-x86_64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 shell: sh run_mock_tests: true - platform: linux-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 shell: sh run_mock_tests: false - platform: macos-arm64 @@ -120,7 +120,7 @@ jobs: check: name: Run - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 30 permissions: contents: read diff --git a/.github/workflows/ci_go.yml b/.github/workflows/ci_go.yml index d185def7c..bb1e3303b 100644 --- a/.github/workflows/ci_go.yml +++ b/.github/workflows/ci_go.yml @@ -33,9 +33,9 @@ jobs: matrix: include: - platform: linux-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 - platform: linux-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 - platform: macos-arm64 runner: macos-15 - platform: windows-amd64 diff --git a/.github/workflows/ci_license_diff.yml b/.github/workflows/ci_license_diff.yml index fa8332f6a..26db11047 100644 --- a/.github/workflows/ci_license_diff.yml +++ b/.github/workflows/ci_license_diff.yml @@ -27,7 +27,7 @@ env: jobs: license-diff: name: Run - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 20 permissions: contents: read diff --git a/.github/workflows/ci_node.yml b/.github/workflows/ci_node.yml index c2c5581ef..558c38d5d 100644 --- a/.github/workflows/ci_node.yml +++ b/.github/workflows/ci_node.yml @@ -55,12 +55,12 @@ jobs: platform: linux-amd64 node_build_strategy: zig node_target: x86_64-unknown-linux-gnu - runner: ubuntu-latest + runner: linux-amd64-cpu4 - &linux-arm64 platform: linux-arm64 node_build_strategy: zig node_target: aarch64-unknown-linux-gnu - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 - &macos-arm64 platform: macos-arm64 node_build_strategy: native @@ -154,7 +154,7 @@ jobs: node_build_strategy: zig node_target: x86_64-unknown-linux-musl platform: linux-musl-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 container_image: node:24-alpine3.22@sha256:191c9f0080fcbbc6547a85dc0ff7988072214a355aabdc1d2ec55a7dae5eea8a package_name: nemo-relay-node-linux-x64-musl - &package-linux-musl-arm64 @@ -162,7 +162,7 @@ jobs: node_build_strategy: zig node_target: aarch64-unknown-linux-musl platform: linux-musl-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 container_image: node:24-alpine3.22@sha256:191c9f0080fcbbc6547a85dc0ff7988072214a355aabdc1d2ec55a7dae5eea8a package_name: nemo-relay-node-linux-arm64-musl @@ -258,7 +258,7 @@ jobs: PackageOpenClaw: name: Package OpenClaw plugin if: ${{ inputs.run_openclaw }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 30 permissions: contents: read diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 2595f1798..62053ae81 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -53,10 +53,10 @@ jobs: include: - &linux-amd64 platform: linux-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 - &linux-arm64 platform: linux-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 - &macos-arm64 platform: macos-arm64 runner: macos-15 @@ -160,13 +160,13 @@ jobs: platform: linux-musl-amd64 architecture: x86_64 rust_target: x86_64-unknown-linux-musl - runner: ubuntu-latest + runner: linux-amd64-cpu4 container_image: quay.io/pypa/musllinux_1_2_x86_64@sha256:7b54360b191356838f6e41d4b9820c69be4f3d8dc8e7bca26f2684d48e5c8633 - &package-linux-musl-arm64 platform: linux-musl-arm64 architecture: aarch64 rust_target: aarch64-unknown-linux-musl - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 container_image: quay.io/pypa/musllinux_1_2_aarch64@sha256:274a947b4d5d745b56b868b0d052641e0798a652e3e65755987edf60547d1268 steps: @@ -386,7 +386,7 @@ jobs: - *package-linux-musl-amd64 - *package-linux-musl-arm64 - platform: source-and-plugin - runner: ubuntu-latest + runner: linux-amd64-cpu4 steps: - name: Remove untrusted Homebrew tap diff --git a/.github/workflows/ci_rust.yml b/.github/workflows/ci_rust.yml index a50f2aa23..fb67237e1 100644 --- a/.github/workflows/ci_rust.yml +++ b/.github/workflows/ci_rust.yml @@ -60,13 +60,13 @@ jobs: matrix: include: - platform: linux-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 run_redis_tests: true redis_service_image: redis:7.4.7-alpine@sha256:02f2cc4882f8bf87c79a220ac958f58c700bdec0dfb9b9ea61b62fb0e8f1bfcf run_s3_tests: true s3_service_image: adobe/s3mock:5.0.0@sha256:c461c8f4234bd63540d2f3a3cabce69d814c78dc890a5af08727525a028e23da - platform: linux-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 run_redis_tests: false redis_service_image: '' s3_service_image: '' @@ -180,25 +180,25 @@ jobs: include: - &package-linux-amd64 platform: linux-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 target: x86_64-unknown-linux-gnu build_image: quay.io/pypa/manylinux2014_x86_64@sha256:35baef377f64c2ae2e7ed647917ecd090c50f6e8b06fd605012661c2e954cc92 runtime_image: quay.io/pypa/manylinux2014_x86_64@sha256:35baef377f64c2ae2e7ed647917ecd090c50f6e8b06fd605012661c2e954cc92 - &package-linux-arm64 platform: linux-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 target: aarch64-unknown-linux-gnu build_image: quay.io/pypa/manylinux2014_aarch64@sha256:63f73ecd2be3ad7cf66a402c72c1594b3f9140e263ab6838896e93a8fbf53794 runtime_image: quay.io/pypa/manylinux2014_aarch64@sha256:63f73ecd2be3ad7cf66a402c72c1594b3f9140e263ab6838896e93a8fbf53794 - &package-linux-musl-amd64 platform: linux-musl-amd64 - runner: ubuntu-latest + runner: linux-amd64-cpu4 target: x86_64-unknown-linux-musl build_image: '' runtime_image: quay.io/pypa/musllinux_1_2_x86_64@sha256:7b54360b191356838f6e41d4b9820c69be4f3d8dc8e7bca26f2684d48e5c8633 - &package-linux-musl-arm64 platform: linux-musl-arm64 - runner: ubuntu-24.04-arm + runner: linux-arm64-cpu4 target: aarch64-unknown-linux-musl build_image: '' runtime_image: quay.io/pypa/musllinux_1_2_aarch64@sha256:274a947b4d5d745b56b868b0d052641e0798a652e3e65755987edf60547d1268 diff --git a/.github/workflows/fern-docs.yml b/.github/workflows/fern-docs.yml index 558f04914..06782bc3f 100644 --- a/.github/workflows/fern-docs.yml +++ b/.github/workflows/fern-docs.yml @@ -28,7 +28,7 @@ jobs: changed-files: name: Detect docs changes if: ${{ github.ref_type != 'tag' && github.event_name != 'pull_request' }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 timeout-minutes: 10 permissions: contents: read @@ -55,7 +55,7 @@ jobs: needs.changed-files.outputs.docs == 'true' && startsWith(github.ref_name, 'pull-request/') }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 environment: fern timeout-minutes: 60 permissions: @@ -185,7 +185,7 @@ jobs: && github.event.action == 'closed' && github.event.pull_request.merged == true }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 environment: fern timeout-minutes: 10 permissions: @@ -241,7 +241,7 @@ jobs: || (github.event_name == 'workflow_dispatch' && (inputs.tag == '' || inputs.tag == null)) ) }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 environment: fern timeout-minutes: 60 permissions: @@ -370,7 +370,7 @@ jobs: github.ref_type == 'tag' || (github.event_name == 'workflow_dispatch' && inputs.tag != '' && inputs.tag != null) }} - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 environment: fern timeout-minutes: 60 permissions: diff --git a/.github/workflows/nightly-alpha-tag.yaml b/.github/workflows/nightly-alpha-tag.yaml index 99873d071..59cd8a975 100644 --- a/.github/workflows/nightly-alpha-tag.yaml +++ b/.github/workflows/nightly-alpha-tag.yaml @@ -16,7 +16,7 @@ concurrency: jobs: nightly-alpha-config: name: Load nightly alpha branches - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 permissions: contents: read outputs: @@ -37,7 +37,7 @@ jobs: tag-nightly-alpha: name: Tag nightly alpha needs: nightly-alpha-config - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 strategy: fail-fast: false matrix: diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml index 12c785f7c..19b6c728c 100644 --- a/.github/workflows/pr-labels.yaml +++ b/.github/workflows/pr-labels.yaml @@ -23,7 +23,7 @@ defaults: jobs: label: name: Apply PR labels - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 permissions: issues: write pull-requests: write diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 852b171fd..c12d1a368 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -9,7 +9,7 @@ on: jobs: stale: - runs-on: ubuntu-latest + runs-on: linux-amd64-cpu4 permissions: issues: write pull-requests: write From 1c5caa533a3b47e428d5a6357f0eb780a8022b69 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 19 Aug 2026 16:50:26 -0500 Subject: [PATCH 2/3] ci: support managed Linux Python toolchains Signed-off-by: Will Killian --- .github/workflows/ci_python.yml | 21 +++++++++++++++++++++ .github/workflows/ci_rust.yml | 23 ++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 62053ae81..16fb3513f 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -109,6 +109,27 @@ jobs: uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ steps.ci-config.outputs.default_python_version }} + + - name: Configure Python linker library + if: ${{ runner.os == 'Linux' }} + run: | + set -euo pipefail + python - <<'PY' + import os + import sysconfig + from pathlib import Path + + library_dir = Path(sysconfig.get_config_var("LIBDIR")) + library = library_dir / sysconfig.get_config_var("INSTSONAME") + linker_name = sysconfig.get_config_var("LDLIBRARY") + if not library.is_file(): + raise SystemExit(f"Python shared library not found: {library}") + linker_dir = Path(os.environ["RUNNER_TEMP"]) / "python-linker-library" + linker_dir.mkdir(exist_ok=True) + (linker_dir / linker_name).symlink_to(library) + with Path(os.environ["GITHUB_ENV"]).open("a") as env_file: + env_file.write(f"LIBRARY_PATH={linker_dir}\n") + PY - name: Run Python tests with coverage working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }} run: just --set ci true --set output_dir "${{ github.workspace }}" test-python diff --git a/.github/workflows/ci_rust.yml b/.github/workflows/ci_rust.yml index fb67237e1..0d743e7e6 100644 --- a/.github/workflows/ci_rust.yml +++ b/.github/workflows/ci_rust.yml @@ -129,6 +129,27 @@ jobs: with: python-version: ${{ steps.ci-config.outputs.default_python_version }} + - name: Configure Python linker library + if: ${{ runner.os == 'Linux' }} + run: | + set -euo pipefail + python - <<'PY' + import os + import sysconfig + from pathlib import Path + + library_dir = Path(sysconfig.get_config_var("LIBDIR")) + library = library_dir / sysconfig.get_config_var("INSTSONAME") + linker_name = sysconfig.get_config_var("LDLIBRARY") + if not library.is_file(): + raise SystemExit(f"Python shared library not found: {library}") + linker_dir = Path(os.environ["RUNNER_TEMP"]) / "python-linker-library" + linker_dir.mkdir(exist_ok=True) + (linker_dir / linker_name).symlink_to(library) + with Path(os.environ["GITHUB_ENV"]).open("a") as env_file: + env_file.write(f"LIBRARY_PATH={linker_dir}\n") + PY + - uses: taiki-e/install-action@c070f87102a1c75b3183910f391c1cb887fe13c8 # v2.77.6 with: tool: cargo-llvm-cov@${{ steps.ci-config.outputs.cargo_llvm_cov_version }},cargo-nextest@${{ steps.ci-config.outputs.cargo_nextest_version }},just@${{ steps.ci-config.outputs.just_version }} @@ -347,7 +368,7 @@ jobs: version="$NEMO_RELAY_CLI_PACKAGE_VERSION" rm -rf "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-packages" mkdir -p "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-packages" - python scripts/package-cli-bin.py \ + python3 scripts/package-cli-bin.py \ --binary "$source" \ --target "$target" \ --version "$version" \ From 0edc55a4ec6721d33980e6778083fa8be9e1763d Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 19 Aug 2026 16:56:14 -0500 Subject: [PATCH 3/3] ci: resolve managed Python library paths Signed-off-by: Will Killian --- .github/workflows/ci_python.yml | 2 +- .github/workflows/ci_rust.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 16fb3513f..2bb1f0f90 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -119,7 +119,7 @@ jobs: import sysconfig from pathlib import Path - library_dir = Path(sysconfig.get_config_var("LIBDIR")) + library_dir = Path(os.environ["Python_ROOT_DIR"]) / "lib" library = library_dir / sysconfig.get_config_var("INSTSONAME") linker_name = sysconfig.get_config_var("LDLIBRARY") if not library.is_file(): diff --git a/.github/workflows/ci_rust.yml b/.github/workflows/ci_rust.yml index 0d743e7e6..a6220a0ce 100644 --- a/.github/workflows/ci_rust.yml +++ b/.github/workflows/ci_rust.yml @@ -138,7 +138,7 @@ jobs: import sysconfig from pathlib import Path - library_dir = Path(sysconfig.get_config_var("LIBDIR")) + library_dir = Path(os.environ["Python_ROOT_DIR"]) / "lib" library = library_dir / sysconfig.get_config_var("INSTSONAME") linker_name = sysconfig.get_config_var("LDLIBRARY") if not library.is_file():