110f088d41
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 1m12s
Project CI / AI game creator shell Rust smoke (push) Failing after 1m12s
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 1m12s
Project CI / AI game creator shell Rust crates (push) Successful in 1m37s
Project CI / Frontend tests (push) Successful in 3m37s
Project CI / Repository checks (push) Successful in 4m4s
Project CI / AI game creator shell web tests (push) Successful in 2m11s
Project CI / Backend tests (push) Successful in 6m31s
Project CI / Native shell tests (push) Successful in 7m13s
- 转义 Stdb Publish GString 内的 shell 命令替换,避免 Jenkinsfile 加载时 Groovy 编译失败 - 为 Stdb Publish 暂存清理命令补充生产运维回归门禁 - 抽离 macOS 包内容策略并放行随包 Claude Agent SDK 的受控 node_modules - 违规资源现在会输出具体相对路径,并补充包内容白名单单测与排障记录
163 lines
5.4 KiB
JavaScript
163 lines
5.4 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import { listForbiddenBundledResourceFiles } from './macos-bundle-policy.mjs';
|
|
import {
|
|
assertMacosAppMatchesChannelIdentity,
|
|
assertManifestArtifactMatchesExpected,
|
|
listStaleMacosArtifacts,
|
|
readMacosAppInfoIdentity,
|
|
} from './macos-release-identity.mjs';
|
|
|
|
test('allows only the production node_modules subtrees in the macOS bundle', () => {
|
|
assert.deepEqual(
|
|
listForbiddenBundledResourceFiles([
|
|
'game-runtime/node/node_modules',
|
|
'game-runtime/node/node_modules/npm/bin/npm-cli.js',
|
|
'claude-agent/node_modules',
|
|
'claude-agent/node_modules/@anthropic-ai',
|
|
'claude-agent/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs',
|
|
'claude-agent/node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64/claude',
|
|
]),
|
|
[],
|
|
);
|
|
assert.deepEqual(
|
|
listForbiddenBundledResourceFiles([
|
|
'claude-agent/node_modules/unexpected/index.mjs',
|
|
'claude-agent/node_modules/@anthropic-ai/unexpected/index.mjs',
|
|
'plugins/agc-cocos-editor/node_modules/leftover/index.mjs',
|
|
'game-runtime/node/.env.local',
|
|
'claude-agent/auth.json',
|
|
'claude-agent/target/debug/claude',
|
|
'claude-agent/tool.exe',
|
|
'claude-agent/tool.dll',
|
|
]),
|
|
[
|
|
'claude-agent/node_modules/unexpected/index.mjs',
|
|
'claude-agent/node_modules/@anthropic-ai/unexpected/index.mjs',
|
|
'plugins/agc-cocos-editor/node_modules/leftover/index.mjs',
|
|
'game-runtime/node/.env.local',
|
|
'claude-agent/auth.json',
|
|
'claude-agent/target/debug/claude',
|
|
'claude-agent/tool.exe',
|
|
'claude-agent/tool.dll',
|
|
],
|
|
);
|
|
});
|
|
|
|
const DEV_IDENTITY = {
|
|
productName: '陶泥儿开发版',
|
|
identifier: 'world.genarrative.ai-game-creator',
|
|
};
|
|
|
|
function plist({ version, identifier, name }) {
|
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
<plist version="1.0"><dict>
|
|
<key>CFBundleShortVersionString</key><string>${version}</string>
|
|
<key>CFBundleIdentifier</key><string>${identifier}</string>
|
|
<key>CFBundleName</key><string>${name}</string>
|
|
<key>CFBundleDisplayName</key><string>${name}</string>
|
|
</dict></plist>`;
|
|
}
|
|
|
|
test('reads version, identifier and product name from Info.plist text', () => {
|
|
const identity = readMacosAppInfoIdentity(
|
|
plist({
|
|
version: '0.1.154',
|
|
...DEV_IDENTITY,
|
|
name: DEV_IDENTITY.productName,
|
|
}),
|
|
);
|
|
assert.deepEqual(identity, {
|
|
version: '0.1.154',
|
|
identifier: DEV_IDENTITY.identifier,
|
|
name: DEV_IDENTITY.productName,
|
|
displayName: DEV_IDENTITY.productName,
|
|
});
|
|
});
|
|
|
|
test('accepts the app bundle that matches this channel and version', () => {
|
|
assert.doesNotThrow(() =>
|
|
assertMacosAppMatchesChannelIdentity({
|
|
identity: readMacosAppInfoIdentity(
|
|
plist({
|
|
version: '0.1.154',
|
|
identifier: DEV_IDENTITY.identifier,
|
|
name: DEV_IDENTITY.productName,
|
|
}),
|
|
),
|
|
expectedVersion: '0.1.154',
|
|
expectedProductName: DEV_IDENTITY.productName,
|
|
expectedIdentifier: DEV_IDENTITY.identifier,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// 回归:线上 dev-mac/0.1.142 清单实际指向 0.1.139 的 release 身份包。
|
|
test('rejects the release-identity bundle that shipped in the dev-mac channel', () => {
|
|
const shipped = readMacosAppInfoIdentity(
|
|
plist({
|
|
version: '0.1.139',
|
|
identifier: 'world.genarrative.ai-game-creator.release',
|
|
name: '陶泥儿 Release',
|
|
}),
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
assertMacosAppMatchesChannelIdentity({
|
|
identity: shipped,
|
|
expectedVersion: '0.1.142',
|
|
expectedProductName: DEV_IDENTITY.productName,
|
|
expectedIdentifier: DEV_IDENTITY.identifier,
|
|
}),
|
|
/版本不一致:产物 0\.1\.139,本轮清单 0\.1\.142[\s\S]*bundle identifier 不一致[\s\S]*产品名不一致/u,
|
|
);
|
|
});
|
|
|
|
test('rejects a bundle whose version is right but channel identity is wrong', () => {
|
|
assert.throws(
|
|
() =>
|
|
assertMacosAppMatchesChannelIdentity({
|
|
identity: readMacosAppInfoIdentity(
|
|
plist({
|
|
version: '0.1.154',
|
|
identifier: 'world.genarrative.ai-game-creator.release',
|
|
name: '陶泥儿 Release',
|
|
}),
|
|
),
|
|
expectedVersion: '0.1.154',
|
|
expectedProductName: DEV_IDENTITY.productName,
|
|
expectedIdentifier: DEV_IDENTITY.identifier,
|
|
}),
|
|
/bundle identifier 不一致/u,
|
|
);
|
|
});
|
|
|
|
test('lists every stale mac artifact so the bundle directory cannot leak into the manifest', () => {
|
|
const files = [
|
|
'/bundle/macos/陶泥儿 Release.app.tar.gz',
|
|
'/bundle/macos/陶泥儿 Release.app.tar.gz.sig',
|
|
'/bundle/macos/陶泥儿开发版_0.1.139_aarch64.dmg',
|
|
'/bundle/macos/陶泥儿开发版_0.1.139_aarch64.dmg.sha256',
|
|
'/bundle/macos/陶泥儿开发版.app/Contents/Info.plist',
|
|
];
|
|
assert.deepEqual(listStaleMacosArtifacts(files), files.slice(0, 4));
|
|
});
|
|
|
|
test('rejects a manifest that selected a different artifact than this build wrote', () => {
|
|
assert.throws(
|
|
() =>
|
|
assertManifestArtifactMatchesExpected({
|
|
artifactPath: '/bundle/macos/陶泥儿 Release.app.tar.gz',
|
|
expectedPath: '/bundle/macos/陶泥儿开发版.app.tar.gz',
|
|
}),
|
|
/清单选中的更新包不是本轮产物/u,
|
|
);
|
|
assert.doesNotThrow(() =>
|
|
assertManifestArtifactMatchesExpected({
|
|
artifactPath: '/bundle/macos/陶泥儿开发版.app.tar.gz',
|
|
expectedPath: '/bundle/macos/陶泥儿开发版.app.tar.gz',
|
|
}),
|
|
);
|
|
});
|