From 57092a17944aa28eef03c9a07fb088596dd3697d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 10:03:32 +0100 Subject: [PATCH] ci: harden cross-os release harness on Windows --- ...nclaw-cross-os-release-checks-reusable.yml | 6 ++-- .../run-openclaw-cross-os-release-checks.sh | 28 +++++++++++++++++++ ...openclaw-cross-os-release-workflow.test.ts | 14 ++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100755 scripts/github/run-openclaw-cross-os-release-checks.sh create mode 100644 test/scripts/openclaw-cross-os-release-workflow.test.ts diff --git a/.github/workflows/openclaw-cross-os-release-checks-reusable.yml b/.github/workflows/openclaw-cross-os-release-checks-reusable.yml index 474139e7b75..96aa4c432d9 100644 --- a/.github/workflows/openclaw-cross-os-release-checks-reusable.yml +++ b/.github/workflows/openclaw-cross-os-release-checks-reusable.yml @@ -286,7 +286,7 @@ jobs: env: OUTPUT_DIR: ${{ runner.temp }}/openclaw-cross-os-release-checks/prepare run: | - pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \ + bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \ --prepare-only \ --source-dir source \ --output-dir "${OUTPUT_DIR}" @@ -370,7 +370,7 @@ jobs: VAR_WINDOWS_RUNNER: ${{ vars.OPENCLAW_RELEASE_CHECKS_WINDOWS_RUNNER }} VAR_MACOS_RUNNER: ${{ vars.OPENCLAW_RELEASE_CHECKS_MACOS_RUNNER }} run: | - MATRIX_JSON="$(pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \ + MATRIX_JSON="$(bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \ --resolve-matrix \ --ref "${INPUT_REF}" \ --mode "${INPUT_MODE}" \ @@ -448,7 +448,7 @@ jobs: if [[ -n "${OPENCLAW_DISCORD_SMOKE_BOT_TOKEN}" ]] && [[ -n "${OPENCLAW_DISCORD_SMOKE_GUILD_ID}" ]] && [[ -n "${OPENCLAW_DISCORD_SMOKE_CHANNEL_ID}" ]]; then DISCORD_ARGS+=(--run-discord-roundtrip true) fi - pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \ + bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \ --candidate-tgz "${CANDIDATE_TGZ}" \ --candidate-version "${CANDIDATE_VERSION}" \ --source-sha "${SOURCE_SHA}" \ diff --git a/scripts/github/run-openclaw-cross-os-release-checks.sh b/scripts/github/run-openclaw-cross-os-release-checks.sh new file mode 100755 index 00000000000..cd63b4c27b6 --- /dev/null +++ b/scripts/github/run-openclaw-cross-os-release-checks.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +tsx_version="${OPENCLAW_RELEASE_TSX_VERSION:-${TSX_VERSION:-4.21.0}}" +script_path="${OPENCLAW_RELEASE_CHECKS_SCRIPT:-workflow/scripts/openclaw-cross-os-release-checks.ts}" + +temp_root="${OPENCLAW_RELEASE_TSX_TOOL_ROOT:-${RUNNER_TEMP:-${TMPDIR:-/tmp}}}" +if command -v cygpath >/dev/null 2>&1; then + temp_root="$(cygpath -u "${temp_root}")" +fi + +tool_dir="${OPENCLAW_RELEASE_TSX_TOOL_DIR:-${temp_root}/openclaw-release-tsx-${tsx_version}}" +loader_path="${tool_dir}/node_modules/tsx/dist/loader.mjs" + +if [[ ! -f "${loader_path}" ]]; then + mkdir -p "${tool_dir}" + npm install --prefix "${tool_dir}" --no-save --no-package-lock "tsx@${tsx_version}" >/dev/null +fi + +loader_url="$( + node -e ' + const { resolve } = require("node:path"); + const { pathToFileURL } = require("node:url"); + process.stdout.write(pathToFileURL(resolve(process.argv[1])).href); + ' "${loader_path}" +)" + +exec node --import "${loader_url}" "${script_path}" "$@" diff --git a/test/scripts/openclaw-cross-os-release-workflow.test.ts b/test/scripts/openclaw-cross-os-release-workflow.test.ts new file mode 100644 index 00000000000..649790ebf65 --- /dev/null +++ b/test/scripts/openclaw-cross-os-release-workflow.test.ts @@ -0,0 +1,14 @@ +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; + +const WORKFLOW_PATH = ".github/workflows/openclaw-cross-os-release-checks-reusable.yml"; +const HARNESS = "bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh"; + +describe("cross-OS release checks workflow", () => { + it("runs the TypeScript release harness through the Windows-safe wrapper", () => { + const workflow = readFileSync(WORKFLOW_PATH, "utf8"); + + expect(workflow).toContain(HARNESS); + expect(workflow).not.toContain('pnpm dlx "tsx@${TSX_VERSION}"'); + }); +});