diff --git a/scripts/notarize-mac-artifact.sh b/scripts/notarize-mac-artifact.sh index 2ceb5a773f39..abaae84e6279 100755 --- a/scripts/notarize-mac-artifact.sh +++ b/scripts/notarize-mac-artifact.sh @@ -23,6 +23,10 @@ if [[ ! -e "$ARTIFACT" ]]; then echo "Error: artifact not found: $ARTIFACT" >&2 exit 1 fi +if [[ -n "$STAPLE_APP_PATH" && ! -d "$STAPLE_APP_PATH" ]]; then + echo "Error: STAPLE_APP_PATH not found: $STAPLE_APP_PATH" >&2 + exit 1 +fi if ! command -v xcrun >/dev/null 2>&1; then echo "Error: xcrun not found; install Xcode command line tools." >&2 @@ -53,13 +57,9 @@ case "$ARTIFACT" in esac if [[ -n "$STAPLE_APP_PATH" ]]; then - if [[ -d "$STAPLE_APP_PATH" ]]; then - echo "📌 Stapling app: $STAPLE_APP_PATH" - xcrun stapler staple "$STAPLE_APP_PATH" - xcrun stapler validate "$STAPLE_APP_PATH" - else - echo "Warn: STAPLE_APP_PATH not found: $STAPLE_APP_PATH" >&2 - fi + echo "📌 Stapling app: $STAPLE_APP_PATH" + xcrun stapler staple "$STAPLE_APP_PATH" + xcrun stapler validate "$STAPLE_APP_PATH" fi echo "✅ Notarization complete" diff --git a/test/scripts/notarize-mac-artifact.test.ts b/test/scripts/notarize-mac-artifact.test.ts new file mode 100644 index 000000000000..0b94b8ef5465 --- /dev/null +++ b/test/scripts/notarize-mac-artifact.test.ts @@ -0,0 +1,44 @@ +import { spawnSync } from "node:child_process"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { afterEach, describe, expect, it } from "vitest"; + +const tempDirs: string[] = []; +const scriptPath = "scripts/notarize-mac-artifact.sh"; + +function makeTempDir(prefix: string): string { + const dir = mkdtempSync(path.join(tmpdir(), prefix)); + tempDirs.push(dir); + return dir; +} + +afterEach(() => { + for (const dir of tempDirs.splice(0)) { + rmSync(dir, { recursive: true, force: true }); + } +}); + +describe("notarize-mac-artifact input validation", () => { + it("fails before notarization when an explicit staple app path is missing", () => { + const tempRoot = makeTempDir("openclaw-notary-staple-"); + const artifact = path.join(tempRoot, "OpenClaw.zip"); + const missingApp = path.join(tempRoot, "Missing.app"); + writeFileSync(artifact, "placeholder", "utf8"); + + const result = spawnSync("bash", [scriptPath, artifact], { + cwd: process.cwd(), + encoding: "utf8", + env: { + ...process.env, + STAPLE_APP_PATH: missingApp, + }, + }); + + expect(result.status).toBe(1); + expect(result.stderr).toContain("Error: STAPLE_APP_PATH not found"); + expect(result.stderr).not.toContain("xcrun not found"); + expect(result.stderr).not.toContain("Notary auth missing"); + expect(result.stdout).not.toContain("Notarizing:"); + }); +});