diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 885d87fcb..a2abe26ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,10 @@ jobs: - name: Checkout submodules (retry) run: | set -euo pipefail + if [ ! -f .gitmodules ]; then + echo "No .gitmodules found; skipping submodule update." + exit 0 + fi git submodule sync --recursive for attempt in 1 2 3 4 5; do if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then @@ -101,6 +105,10 @@ jobs: - name: Checkout submodules (retry) run: | set -euo pipefail + if [ ! -f .gitmodules ]; then + echo "No .gitmodules found; skipping submodule update." + exit 0 + fi git submodule sync --recursive for attempt in 1 2 3 4 5; do if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then @@ -217,6 +225,10 @@ jobs: - name: Checkout submodules (retry) run: | set -euo pipefail + if [ ! -f .gitmodules ]; then + echo "No .gitmodules found; skipping submodule update." + exit 0 + fi git submodule sync --recursive for attempt in 1 2 3 4 5; do if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then @@ -293,6 +305,10 @@ jobs: - name: Checkout submodules (retry) run: | set -euo pipefail + if [ ! -f .gitmodules ]; then + echo "No .gitmodules found; skipping submodule update." + exit 0 + fi git submodule sync --recursive for attempt in 1 2 3 4 5; do if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then @@ -389,6 +405,10 @@ jobs: - name: Checkout submodules (retry) run: | set -euo pipefail + if [ ! -f .gitmodules ]; then + echo "No .gitmodules found; skipping submodule update." + exit 0 + fi git submodule sync --recursive for attempt in 1 2 3 4 5; do if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then diff --git a/src/infra/binaries.test.ts b/src/infra/binaries.test.ts index 50b48d372..6c2faf96d 100644 --- a/src/infra/binaries.test.ts +++ b/src/infra/binaries.test.ts @@ -4,6 +4,8 @@ import type { runExec } from "../process/exec.js"; import type { RuntimeEnv } from "../runtime.js"; import { ensureBinary } from "./binaries.js"; +const expectedCmd = process.platform === "win32" ? "where" : "which"; + describe("ensureBinary", () => { it("passes through when binary exists", async () => { const exec: typeof runExec = vi.fn().mockResolvedValue({ @@ -16,7 +18,7 @@ describe("ensureBinary", () => { exit: vi.fn(), }; await ensureBinary("node", exec, runtime); - expect(exec).toHaveBeenCalledWith("which", ["node"]); + expect(exec).toHaveBeenCalledWith(expectedCmd, ["node"]); }); it("logs and exits when missing", async () => { diff --git a/src/infra/binaries.ts b/src/infra/binaries.ts index 492cf5a9c..3e82ee940 100644 --- a/src/infra/binaries.ts +++ b/src/infra/binaries.ts @@ -7,7 +7,9 @@ export async function ensureBinary( runtime: RuntimeEnv = defaultRuntime, ): Promise { // Abort early if a required CLI tool is missing. - await exec("which", [name]).catch(() => { + // Use `where` on Windows, `which` elsewhere. + const cmd = process.platform === "win32" ? "where" : "which"; + await exec(cmd, [name]).catch(() => { runtime.error(`Missing required binary: ${name}. Please install it.`); runtime.exit(1); });