diff --git a/CHANGELOG.md b/CHANGELOG.md index eef46588432..76dec664922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Release validation: install the cross-OS TypeScript harness through Windows-safe Node/npm shims so native Windows package checks reach the OpenClaw smoke suites instead of exiting before artifact capture. Thanks @vincentkoc. - Agents/bootstrap: keep pending `BOOTSTRAP.md` and bootstrap truncation notices in system-prompt Project Context instead of copying setup text or raw warning diagnostics into WebChat user/runtime context. Fixes #76946. - Channels/WhatsApp: allow `@whiskeysockets/libsignal-node` in `onlyBuiltDependencies` so pnpm v9+ `blockExoticSubdeps` no longer rejects the baileys git-tarball subdep and silences all inbound agent replies. Fixes #76539. Thanks @ottodeng and @vincentkoc. - Gateway/install: keep `.env`-managed values in the macOS LaunchAgent env file while still tracking `OPENCLAW_SERVICE_MANAGED_ENV_KEYS`, so regenerated services do not boot without managed auth/provider keys. Fixes #75374. diff --git a/scripts/github/run-openclaw-cross-os-release-checks.sh b/scripts/github/run-openclaw-cross-os-release-checks.sh index 2025b39091f..c377fc492ff 100755 --- a/scripts/github/run-openclaw-cross-os-release-checks.sh +++ b/scripts/github/run-openclaw-cross-os-release-checks.sh @@ -15,6 +15,19 @@ if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then fi fi +node_cmd="node" +npm_cmd="npm" +if command -v cygpath >/dev/null 2>&1; then + if command -v node.exe >/dev/null 2>&1; then + node_cmd="node.exe" + fi + if command -v npm.cmd >/dev/null 2>&1; then + npm_cmd="npm.cmd" + elif command -v npm.exe >/dev/null 2>&1; then + npm_cmd="npm.exe" + fi +fi + 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}")" @@ -22,27 +35,34 @@ 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" +npm_tool_dir="${tool_dir}" +if command -v cygpath >/dev/null 2>&1; then + npm_tool_dir="$(cygpath -w "${tool_dir}")" +fi -command -v node >/dev/null 2>&1 || { +command -v "${node_cmd}" >/dev/null 2>&1 || { echo "node is required to run cross-OS release checks." >&2 exit 127 } -command -v npm >/dev/null 2>&1 || { +command -v "${npm_cmd}" >/dev/null 2>&1 || { echo "npm is required to install the cross-OS release-check loader." >&2 exit 127 } if [[ ! -f "${loader_path}" ]]; then mkdir -p "${tool_dir}" - npm install --prefix "${tool_dir}" --no-save --no-package-lock "tsx@${tsx_version}" >/dev/null + if ! "${npm_cmd}" install --prefix "${npm_tool_dir}" --no-save --no-package-lock "tsx@${tsx_version}" >/dev/null; then + echo "failed to install cross-OS release-check loader with ${npm_cmd}." >&2 + exit 127 + fi fi loader_url="$( - node -e ' + "${node_cmd}" -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}" "$@" +exec "${node_cmd}" --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 index 649790ebf65..fb5c42ee286 100644 --- a/test/scripts/openclaw-cross-os-release-workflow.test.ts +++ b/test/scripts/openclaw-cross-os-release-workflow.test.ts @@ -2,6 +2,7 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; const WORKFLOW_PATH = ".github/workflows/openclaw-cross-os-release-checks-reusable.yml"; +const WRAPPER_PATH = "scripts/github/run-openclaw-cross-os-release-checks.sh"; const HARNESS = "bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh"; describe("cross-OS release checks workflow", () => { @@ -11,4 +12,13 @@ describe("cross-OS release checks workflow", () => { expect(workflow).toContain(HARNESS); expect(workflow).not.toContain('pnpm dlx "tsx@${TSX_VERSION}"'); }); + + it("uses Windows-safe npm resolution for the TypeScript loader bootstrap", () => { + const wrapper = readFileSync(WRAPPER_PATH, "utf8"); + + expect(wrapper).toContain("command -v npm.cmd"); + expect(wrapper).toContain('npm_tool_dir="$(cygpath -w "${tool_dir}")"'); + expect(wrapper).toContain('"${npm_cmd}" install --prefix "${npm_tool_dir}"'); + expect(wrapper).toContain('exec "${node_cmd}" --import "${loader_url}"'); + }); });