























@@ -0,0 +1,98 @@
1+import { spawnSync } from "node:child_process";
2+import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3+import { tmpdir } from "node:os";
4+import path from "node:path";
5+import { afterEach, describe, expect, it } from "vitest";
6+7+const tempDirs: string[] = [];
8+const scriptPath = "scripts/package-mac-dist.sh";
9+10+function makePlist(): string {
11+const dir = mkdtempSync(path.join(tmpdir(), "openclaw-dist-plist-"));
12+tempDirs.push(dir);
13+const plist = path.join(dir, "Info.plist");
14+writeFileSync(
15+plist,
16+[
17+'<?xml version="1.0" encoding="UTF-8"?>',
18+'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
19+'<plist version="1.0">',
20+"<dict>",
21+"<key>CFBundleShortVersionString</key>",
22+"<string>1.2.3</string>",
23+"</dict>",
24+"</plist>",
25+"",
26+].join("\n"),
27+"utf8",
28+);
29+return plist;
30+}
31+32+function runHelper(script: string) {
33+return spawnSync("bash", ["-lc", script], {
34+cwd: process.cwd(),
35+encoding: "utf8",
36+});
37+}
38+39+afterEach(() => {
40+for (const dir of tempDirs.splice(0)) {
41+rmSync(dir, { recursive: true, force: true });
42+}
43+});
44+45+describe("package-mac-dist plist validation", () => {
46+it("fails closed for required Info.plist reads", () => {
47+const script = readFileSync(scriptPath, "utf8");
48+const readBlock = script.slice(
49+script.indexOf("VERSION="),
50+script.indexOf('ZIP="$ROOT_DIR/dist/OpenClaw-$VERSION.zip"'),
51+);
52+53+expect(script).toContain('source "$ROOT_DIR/scripts/lib/plistbuddy.sh"');
54+expect(readBlock).toContain(
55+'VERSION="$(plist_print_required "$APP/Contents/Info.plist" CFBundleShortVersionString)"',
56+);
57+expect(readBlock).toContain(
58+'BUNDLE_VERSION="$(plist_print_required "$APP/Contents/Info.plist" CFBundleVersion)"',
59+);
60+expect(readBlock).toContain(
61+'ACTUAL_BUNDLE_ID="$(plist_print_required "$APP/Contents/Info.plist" CFBundleIdentifier)"',
62+);
63+expect(readBlock).toContain(
64+'ACTUAL_FEED_URL="$(plist_print_required "$APP/Contents/Info.plist" SUFeedURL)"',
65+);
66+expect(readBlock).not.toContain("PlistBuddy");
67+expect(readBlock).not.toContain("|| echo");
68+});
69+70+it("requires the release bundle id to match the configured bundle id", () => {
71+const script = readFileSync(scriptPath, "utf8");
72+const releaseBlock = script.slice(
73+script.indexOf('if [[ "$BUILD_CONFIG" == "release" ]]'),
74+script.indexOf('if [[ "$NOTARIZE" == "1" ]]'),
75+);
76+77+expect(releaseBlock).toContain('if [[ "$ACTUAL_BUNDLE_ID" != "$BUNDLE_ID" ]]');
78+expect(releaseBlock).toContain("expected '$BUNDLE_ID'");
79+expect(releaseBlock).not.toContain("*.debug");
80+});
81+82+it.runIf(process.platform === "darwin")(
83+"prints required plist keys and fails when a key is missing",
84+() => {
85+const plist = makePlist();
86+const result = runHelper(`
87+ set -euo pipefail
88+ source scripts/lib/plistbuddy.sh
89+ plist_print_required ${JSON.stringify(plist)} CFBundleShortVersionString
90+ plist_print_required ${JSON.stringify(plist)} CFBundleVersion
91+ `);
92+93+expect(result.status).toBe(1);
94+expect(result.stdout).toContain("1.2.3");
95+expect(result.stderr).toContain("Does Not Exist");
96+},
97+);
98+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。