Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
425 lines
15 KiB
TypeScript
425 lines
15 KiB
TypeScript
// Package Mac Dist tests cover package mac dist script behavior.
|
|
import { spawnSync } from "node:child_process";
|
|
import { chmodSync, mkdirSync, mkdtempSync, readFileSync, 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/package-mac-dist.sh";
|
|
|
|
function makePlist(): string {
|
|
const dir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-plist-"));
|
|
tempDirs.push(dir);
|
|
const plist = path.join(dir, "Info.plist");
|
|
writeFileSync(
|
|
plist,
|
|
[
|
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
'<plist version="1.0">',
|
|
"<dict>",
|
|
"<key>CFBundleShortVersionString</key>",
|
|
"<string>1.2.3</string>",
|
|
"</dict>",
|
|
"</plist>",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
return plist;
|
|
}
|
|
|
|
function runHelper(script: string) {
|
|
return spawnSync("bash", ["-lc", script], {
|
|
cwd: process.cwd(),
|
|
encoding: "utf8",
|
|
});
|
|
}
|
|
|
|
function getPackageManagerHelperBlock(): string {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const start = script.indexOf("DIST_PNPM_CMD=()");
|
|
const end = script.indexOf("ensure_sparkle_build_deps()");
|
|
|
|
expect(start).toBeGreaterThanOrEqual(0);
|
|
expect(end).toBeGreaterThan(start);
|
|
|
|
return script.slice(start, end);
|
|
}
|
|
|
|
afterEach(() => {
|
|
for (const dir of tempDirs.splice(0)) {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
describe("package-mac-dist plist validation", () => {
|
|
it("fails closed for required Info.plist reads", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const readBlock = script.slice(
|
|
script.indexOf("VERSION="),
|
|
script.indexOf('ZIP="$ROOT_DIR/dist/OpenClaw-$VERSION.zip"'),
|
|
);
|
|
|
|
expect(script).toContain('source "$ROOT_DIR/scripts/lib/plistbuddy.sh"');
|
|
expect(readBlock).toContain(
|
|
'VERSION="$(plist_print_required "$APP/Contents/Info.plist" CFBundleShortVersionString)"',
|
|
);
|
|
expect(readBlock).toContain(
|
|
'BUNDLE_VERSION="$(plist_print_required "$APP/Contents/Info.plist" CFBundleVersion)"',
|
|
);
|
|
expect(readBlock).toContain(
|
|
'ACTUAL_BUNDLE_ID="$(plist_print_required "$APP/Contents/Info.plist" CFBundleIdentifier)"',
|
|
);
|
|
expect(readBlock).toContain(
|
|
'ACTUAL_FEED_URL="$(plist_print_required "$APP/Contents/Info.plist" SUFeedURL)"',
|
|
);
|
|
expect(readBlock).not.toContain("PlistBuddy");
|
|
expect(readBlock).not.toContain("|| echo");
|
|
});
|
|
|
|
it("requires the release bundle id to match the configured bundle id", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const releaseBlock = script.slice(
|
|
script.indexOf('if [[ "$BUILD_CONFIG" == "release" ]]'),
|
|
script.indexOf('if [[ "$NOTARIZE" == "1" ]]'),
|
|
);
|
|
|
|
expect(releaseBlock).toContain('if [[ "$ACTUAL_BUNDLE_ID" != "$BUNDLE_ID" ]]');
|
|
expect(releaseBlock).toContain("expected '$BUNDLE_ID'");
|
|
expect(releaseBlock).not.toContain("*.debug");
|
|
});
|
|
|
|
it("does not mask canonical Sparkle build failures for release packaging", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
|
|
expect(script).toContain("ensure_sparkle_build_deps()");
|
|
expect(script).toContain(
|
|
"run_dist_pnpm install --frozen-lockfile --config.node-linker=hoisted >&2",
|
|
);
|
|
expect(script).toContain(
|
|
'(cd "$ROOT_DIR" && node --import tsx "$ROOT_DIR/scripts/sparkle-build.ts" canonical-build "$1")',
|
|
);
|
|
expect(script).toContain('if [[ "$SPARKLE_BUILD_DEPS_RETRIED" == "1" ]]');
|
|
expect(script).toContain("require_canonical_sparkle_build()");
|
|
expect(script).toContain(
|
|
'CANONICAL_APP_BUILD="$(require_canonical_sparkle_build "$APP_VERSION_INPUT")"',
|
|
);
|
|
expect(script).toContain('CANONICAL_APP_BUILD="$(require_canonical_sparkle_build "$VERSION")"');
|
|
expect(script).not.toContain(
|
|
'canonical_sparkle_build "$APP_VERSION_INPUT" 2>/dev/null || true',
|
|
);
|
|
expect(script).not.toContain('canonical_sparkle_build "$VERSION" 2>/dev/null || true');
|
|
});
|
|
|
|
it("checks Swift before Sparkle metadata or dependency bootstrap work", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const swiftIndex = script.indexOf("\nrequire_swift_toolchain\n");
|
|
const versionIndex = script.indexOf('if [[ -z "$APP_VERSION_INPUT" ]]');
|
|
const appBuildIndex = script.indexOf(
|
|
'if [[ -z "${APP_BUILD:-}" && "$BUILD_CONFIG" == "release" ]]',
|
|
);
|
|
const packageAppIndex = script.indexOf('"$ROOT_DIR/scripts/package-mac-app.sh"');
|
|
const preSwiftBlock = script.slice(0, swiftIndex);
|
|
|
|
expect(script).toContain('source "$ROOT_DIR/scripts/lib/swift-toolchain.sh"');
|
|
expect(swiftIndex).toBeGreaterThanOrEqual(0);
|
|
expect(versionIndex).toBeGreaterThan(swiftIndex);
|
|
expect(appBuildIndex).toBeGreaterThan(versionIndex);
|
|
expect(packageAppIndex).toBeGreaterThan(appBuildIndex);
|
|
expect(preSwiftBlock).not.toContain("node -p");
|
|
});
|
|
|
|
it("fails on old Swift before reading package metadata", () => {
|
|
const toolsDir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-swift-tools-"));
|
|
tempDirs.push(toolsDir);
|
|
|
|
writeFileSync(
|
|
path.join(toolsDir, "swift"),
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"echo 'swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)'",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(path.join(toolsDir, "swift"), 0o755);
|
|
writeFileSync(
|
|
path.join(toolsDir, "node"),
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"echo 'node should not run before Swift preflight' >&2",
|
|
"exit 42",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(path.join(toolsDir, "node"), 0o755);
|
|
|
|
const result = runHelper(`
|
|
set -euo pipefail
|
|
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
|
BUILD_CONFIG=release bash ${scriptPath}
|
|
`);
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("OpenClaw macOS app packaging requires Swift tools 6.2+");
|
|
expect(result.stderr).toContain("Current Swift is 6.0");
|
|
expect(result.stderr).not.toContain("node should not run before Swift preflight");
|
|
});
|
|
|
|
it("prefers repo Corepack pnpm over a global pnpm shim", () => {
|
|
const helperBlock = getPackageManagerHelperBlock();
|
|
const tempRoot = mkdtempSync(path.join(tmpdir(), "openclaw-dist-pnpm-root-"));
|
|
const outerRoot = mkdtempSync(path.join(tmpdir(), "openclaw-dist-pnpm-outer-"));
|
|
const toolsDir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-pnpm-tools-"));
|
|
const logPath = path.join(tempRoot, "pnpm.log");
|
|
tempDirs.push(tempRoot, outerRoot, toolsDir);
|
|
|
|
writeFileSync(
|
|
path.join(tempRoot, "package.json"),
|
|
'{\n "packageManager": "pnpm@11.2.2+sha512.test"\n}\n',
|
|
);
|
|
writeFileSync(
|
|
path.join(outerRoot, "package.json"),
|
|
'{\n "packageManager": "pnpm@11.8.0+sha512.test"\n}\n',
|
|
);
|
|
writeFileSync(
|
|
path.join(toolsDir, "pnpm"),
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
'printf "global|%s|%s\\n" "$PWD" "$*" >> "$OPENCLAW_TEST_LOG"',
|
|
'if [[ "${1:-}" == "--version" ]]; then echo "11.8.0"; fi',
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
writeFileSync(
|
|
path.join(toolsDir, "corepack"),
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
'printf "corepack|%s|%s\\n" "$PWD" "$*" >> "$OPENCLAW_TEST_LOG"',
|
|
'if [[ "${1:-}" == "pnpm" && "${2:-}" == "--version" ]]; then',
|
|
' if grep -q "pnpm@11.2.2" package.json 2>/dev/null; then echo "11.2.2"; else echo "11.8.0"; fi',
|
|
"fi",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(path.join(toolsDir, "pnpm"), 0o755);
|
|
chmodSync(path.join(toolsDir, "corepack"), 0o755);
|
|
|
|
const result = runHelper(`
|
|
set -euo pipefail
|
|
ROOT_DIR=${JSON.stringify(tempRoot)}
|
|
OPENCLAW_TEST_LOG=${JSON.stringify(logPath)}
|
|
export OPENCLAW_TEST_LOG
|
|
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
|
cd ${JSON.stringify(outerRoot)}
|
|
${helperBlock}
|
|
run_dist_pnpm --version
|
|
`);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toBe("11.2.2\n");
|
|
expect(readFileSync(logPath, "utf8").trim().split("\n")).toEqual([
|
|
`corepack|${tempRoot}|pnpm --version`,
|
|
`corepack|${tempRoot}|pnpm --version`,
|
|
]);
|
|
});
|
|
|
|
it("keeps dependency bootstrap output out of captured Sparkle build values", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const helpers = script.slice(
|
|
script.indexOf("DIST_PNPM_CMD=()"),
|
|
script.indexOf("correction_build_from_exact_tag()"),
|
|
);
|
|
const dir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-sparkle-"));
|
|
tempDirs.push(dir);
|
|
const tools = path.join(dir, "tools");
|
|
const marker = path.join(dir, "installed");
|
|
const fakeNode = path.join(tools, "node");
|
|
const fakePnpm = path.join(tools, "pnpm");
|
|
|
|
mkdirSync(tools, { recursive: true });
|
|
writeFileSync(
|
|
fakeNode,
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
'if [[ "$PWD" != "$OPENCLAW_ROOT" ]]; then',
|
|
' echo "node ran outside repo root: $PWD" >&2',
|
|
" exit 1",
|
|
"fi",
|
|
'if [[ ! -f "$OPENCLAW_MARKER" ]]; then',
|
|
' echo "Cannot find package tsx" >&2',
|
|
" exit 1",
|
|
"fi",
|
|
'echo "ExperimentalWarning: tsx loader changed" >&2',
|
|
"echo 2026060200",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(fakeNode, 0o755);
|
|
writeFileSync(
|
|
fakePnpm,
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
"echo 'Already up to date'",
|
|
'touch "$OPENCLAW_MARKER"',
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(fakePnpm, 0o755);
|
|
|
|
const result = runHelper(`
|
|
set -euo pipefail
|
|
ROOT_DIR=${JSON.stringify(process.cwd())}
|
|
OPENCLAW_ROOT=${JSON.stringify(process.cwd())}
|
|
OPENCLAW_MARKER=${JSON.stringify(marker)}
|
|
PATH=${JSON.stringify(tools)}:/usr/bin:/bin
|
|
export OPENCLAW_MARKER OPENCLAW_ROOT PATH
|
|
${helpers}
|
|
require_canonical_sparkle_build 2026.6.2
|
|
`);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toBe("2026060200\n");
|
|
expect(result.stderr).toContain("Ensuring deps for Sparkle build metadata");
|
|
expect(result.stderr).toContain("Already up to date");
|
|
expect(result.stderr).toContain("ExperimentalWarning: tsx loader changed");
|
|
});
|
|
|
|
it("stops when dependency bootstrap fails during Sparkle build retry", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const helpers = script.slice(
|
|
script.indexOf("DIST_PNPM_CMD=()"),
|
|
script.indexOf("correction_build_from_exact_tag()"),
|
|
);
|
|
const dir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-sparkle-"));
|
|
tempDirs.push(dir);
|
|
const tools = path.join(dir, "tools");
|
|
const marker = path.join(dir, "installed");
|
|
const fakeNode = path.join(tools, "node");
|
|
const fakePnpm = path.join(tools, "pnpm");
|
|
|
|
mkdirSync(tools, { recursive: true });
|
|
writeFileSync(
|
|
fakeNode,
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
'if [[ "$PWD" != "$OPENCLAW_ROOT" ]]; then',
|
|
' echo "node ran outside repo root: $PWD" >&2',
|
|
" exit 1",
|
|
"fi",
|
|
'if [[ ! -f "$OPENCLAW_MARKER" ]]; then',
|
|
' echo "Cannot find package tsx" >&2',
|
|
" exit 1",
|
|
"fi",
|
|
'echo "node reran after failed install" >&2',
|
|
"echo 2026060200",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(fakeNode, 0o755);
|
|
writeFileSync(
|
|
fakePnpm,
|
|
[
|
|
"#!/usr/bin/env bash",
|
|
"set -euo pipefail",
|
|
'touch "$OPENCLAW_MARKER"',
|
|
'echo "pnpm failed" >&2',
|
|
"exit 42",
|
|
"",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
chmodSync(fakePnpm, 0o755);
|
|
|
|
const result = runHelper(`
|
|
set -euo pipefail
|
|
ROOT_DIR=${JSON.stringify(process.cwd())}
|
|
OPENCLAW_ROOT=${JSON.stringify(process.cwd())}
|
|
OPENCLAW_MARKER=${JSON.stringify(marker)}
|
|
PATH=${JSON.stringify(tools)}:/usr/bin:/bin
|
|
export OPENCLAW_MARKER OPENCLAW_ROOT PATH
|
|
${helpers}
|
|
require_canonical_sparkle_build 2026.6.2
|
|
`);
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stdout).toBe("");
|
|
expect(result.stderr).toContain("pnpm failed");
|
|
expect(result.stderr).not.toContain("node reran after failed install");
|
|
});
|
|
|
|
it("cleans the temporary notary zip when notarization exits early", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const notaryBlock = script.slice(
|
|
script.indexOf('if [[ "$NOTARIZE" == "1" ]]'),
|
|
script.indexOf('if [[ "$SKIP_DMG" != "1" ]]'),
|
|
);
|
|
|
|
expect(script).toContain("cleanup_notary_zip()");
|
|
expect(notaryBlock).toContain("NOTARY_ZIP_PENDING_CLEANUP=1");
|
|
expect(notaryBlock).toContain("trap cleanup_notary_zip EXIT");
|
|
expect(notaryBlock).toContain(
|
|
'STAPLE_APP_PATH="$APP" "$ROOT_DIR/scripts/notarize-mac-artifact.sh" "$NOTARY_ZIP"',
|
|
);
|
|
expect(notaryBlock).toContain('rm -f "$NOTARY_ZIP"');
|
|
expect(notaryBlock).toContain("NOTARY_ZIP_PENDING_CLEANUP=0");
|
|
expect(notaryBlock).toContain("trap - EXIT");
|
|
});
|
|
|
|
it("fails closed when required dSYM outputs are missing", () => {
|
|
const script = readFileSync(scriptPath, "utf8");
|
|
const dsymBlock = script.slice(script.indexOf('if [[ "$SKIP_DSYM" != "1" ]]'));
|
|
|
|
expect(dsymBlock).toContain('for arch in "${DSYM_ARCHS[@]}"');
|
|
expect(dsymBlock).toContain('if [[ ! -d "$BUILD_ROOT/$arch" ]]; then');
|
|
expect(dsymBlock).toContain('MISSING_DSYM_ARCHS+=("$arch")');
|
|
expect(dsymBlock).toContain("Error: dSYM not found for architecture(s):");
|
|
expect(dsymBlock).not.toContain('find "$BUILD_ROOT/arm64"');
|
|
expect(dsymBlock).not.toContain('find "$BUILD_ROOT/x86_64"');
|
|
expect(dsymBlock).toContain("Error: missing DWARF binaries for dSYM merge");
|
|
expect(dsymBlock).toContain("Error: dSYM not found");
|
|
expect(dsymBlock).toContain("exit 1");
|
|
expect(script).toContain('if ! cp -R "$1" "$TMP_DSYM"; then');
|
|
expect(dsymBlock).toContain("cleanup_tmp_dsym");
|
|
expect(dsymBlock).toContain('copy_dsym_to_tmp "${DSYM_PATHS[0]}"');
|
|
expect(dsymBlock).not.toContain('cp -R "${DSYM_PATHS[0]}" "$TMP_DSYM"');
|
|
expect(dsymBlock).toContain(
|
|
'if ! /usr/bin/lipo -create "${DWARF_INPUTS[@]}" -output "$DWARF_OUT"; then',
|
|
);
|
|
expect(dsymBlock).toContain('if ! ditto -c -k --keepParent "$TMP_DSYM" "$DSYM_ZIP"; then');
|
|
expect(dsymBlock).toContain('rm -rf "$TMP_DSYM"');
|
|
expect(dsymBlock).not.toContain("WARN:");
|
|
expect(dsymBlock).not.toContain("continuing");
|
|
});
|
|
|
|
it.runIf(process.platform === "darwin")(
|
|
"prints required plist keys and fails when a key is missing",
|
|
() => {
|
|
const plist = makePlist();
|
|
const result = runHelper(`
|
|
set -euo pipefail
|
|
source scripts/lib/plistbuddy.sh
|
|
plist_print_required ${JSON.stringify(plist)} CFBundleShortVersionString
|
|
plist_print_required ${JSON.stringify(plist)} CFBundleVersion
|
|
`);
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stdout).toContain("1.2.3");
|
|
expect(result.stderr).toContain("Does Not Exist");
|
|
},
|
|
);
|
|
});
|