blob: e97ca5a7161d182fba2c1842a61816239ab7fb50 [file]
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';
const repoRoot = new URL('../', import.meta.url);
const desktopRoot = new URL('../apps/desktop/', import.meta.url);
const desktopManifest = JSON.parse(await readFile(new URL('package.json', desktopRoot), 'utf8'));
const bundledTools = JSON.parse(await readFile(new URL('bundled-tools.json', desktopRoot), 'utf8'));
const officeCliVersion = bundledTools.officecli.version.replace(/^v/, '');
const signingEnvironment = {
CSC_LINK: 'base64-certificate',
CSC_KEY_PASSWORD: 'password',
APPLE_API_KEY: '/tmp/AuthKey_TEST.p8',
APPLE_API_KEY_ID: 'TESTKEY',
APPLE_API_ISSUER: '00000000-0000-0000-0000-000000000000',
};
test('desktop packager has signed macOS arm64 install and update targets', async () => {
const { default: config } = await import(new URL('electron-builder.config.mjs', desktopRoot));
assert.equal(config.appId, 'com.maka.desktop');
assert.equal(config.productName, 'Maka');
assert.equal(config.asar, true);
assert.equal(config.artifactName, 'Maka-${version}-mac-${arch}.${ext}');
assert.deepEqual(config.mac.target, [
{ target: 'dmg', arch: ['arm64'] },
{ target: 'zip', arch: ['arm64'] },
]);
assert.equal(config.mac.forceCodeSigning, true);
assert.equal(config.mac.hardenedRuntime, true);
assert.equal(config.mac.notarize, true);
assert.equal(config.mac.entitlements, 'build/entitlements.mac.plist');
assert.equal(config.mac.entitlementsInherit, 'build/entitlements.mac.inherit.plist');
assert.deepEqual(config.mac.binaries, ['Contents/Resources/tools/officecli']);
assert.deepEqual(config.dmg, { writeUpdateInfo: true });
assert.deepEqual(config.publish, [
{
provider: 'github',
owner: 'Maka-Agent',
repo: 'maka-agent',
},
]);
assert.ok(config.files.includes('!**/__tests__/**'));
});
test('Electron is a build tool rather than a packaged application dependency', async () => {
assert.equal(desktopManifest.dependencies.electron, undefined);
assert.match(desktopManifest.devDependencies.electron, /^\d+\.\d+\.\d+$/);
});
test('renderer build inputs are not duplicated in the packaged Node runtime', async () => {
const manifest = JSON.parse(await readFile(new URL('package.json', desktopRoot), 'utf8'));
for (const dependency of [
'@ant-design/icons-svg',
'@fontsource-variable/geist',
'@fontsource-variable/geist-mono',
'@vitejs/plugin-react',
'simple-icons',
'vite',
]) {
assert.equal(manifest.dependencies[dependency], undefined);
assert.equal(typeof manifest.devDependencies[dependency], 'string');
}
});
test('OfficeCLI arm64 release is anchored to a repository-pinned digest', () => {
assert.equal(
bundledTools.officecli.sha256['darwin-arm64'],
'3ede6c3457f050f2d06d95895d7a3391183911ad729c61df990d4e27c1067510',
);
});
test('OfficeCLI preparation rejects a mutually consistent upstream replacement', async () => {
const { assertOfficeCliChecksums } = await import(
new URL('prepare-officecli.mjs', import.meta.url)
);
const pinned = bundledTools.officecli.sha256['darwin-arm64'];
const replaced = 'a'.repeat(64);
assert.throws(
() =>
assertOfficeCliChecksums({
asset: bundledTools.officecli.assets['darwin-arm64'],
actual: replaced,
upstream: replaced,
pinned,
}),
/does not match repository-pinned checksum/,
);
});
test('desktop packager ships only the release runtime resources', async () => {
const { default: config } = await import(new URL('electron-builder.config.mjs', desktopRoot));
assert.deepEqual(config.extraResources, [
{
from: 'bundled-tools.json',
to: 'bundled-tools.json',
},
{
from: 'resources/workers/filesystem-worker.js',
to: 'workers/filesystem-worker.js',
},
{
from: 'resources/tools/officecli',
to: 'tools/officecli',
},
{
from: '../../LICENSE',
to: 'licenses/officecli/LICENSE',
},
{
from: 'resources/licenses/officecli/ATTRIBUTION.md',
to: 'licenses/officecli/ATTRIBUTION.md',
},
{
from: '../../LICENSE',
to: 'licenses/maka/LICENSE',
},
{
from: '../../NOTICE',
to: 'licenses/maka/NOTICE',
},
{
from: 'src/renderer/public/THIRD_PARTY_LICENSES.txt',
to: 'licenses/renderer/THIRD_PARTY_LICENSES.txt',
},
{
from: '../../node_modules/@fontsource-variable/geist/LICENSE',
to: 'licenses/renderer/GEIST_LICENSE.txt',
},
{
from: '../../node_modules/@fontsource-variable/geist-mono/LICENSE',
to: 'licenses/renderer/GEIST_MONO_LICENSE.txt',
},
{
from: 'resources/licenses/renderer/ANT_DESIGN_ICONS_LICENSE.txt',
to: 'licenses/renderer/ANT_DESIGN_ICONS_LICENSE.txt',
},
{
from: 'node_modules/simple-icons/LICENSE.md',
to: 'licenses/renderer/SIMPLE_ICONS_LICENSE.md',
},
]);
assert.equal(
config.extraResources.some(({ from }) => from.includes('cua-driver')),
false,
);
});
test('release package script runs the single arm64 pipeline in order', async () => {
const { packageMacosArm64 } = await import(new URL('package-macos-arm64.mjs', import.meta.url));
const calls = [];
const removed = [];
const asserted = [];
const result = await packageMacosArm64({
platform: 'darwin',
arch: 'arm64',
env: signingEnvironment,
run: async (command, args) => {
calls.push([command, args]);
},
remove: async (path, options) => {
removed.push([path, options]);
},
assertFile: async (path) => {
asserted.push(path);
},
});
assert.deepEqual(calls, [
['npm', ['run', 'clean']],
['npm', ['run', 'prepare:officecli', '--', '--platform', 'darwin', '--arch', 'arm64']],
['npm', ['run', 'build']],
['npm', ['run', 'check:release']],
['npm', ['--workspace', '@maka/desktop', 'run', 'package:macos-arm64']],
]);
assert.equal(removed.length, 2);
assert.ok(removed[0][0].endsWith('/apps/desktop/release'));
assert.equal(removed[0][1].recursive, true);
assert.equal(removed[0][1].force, true);
assert.ok(removed[1][0].endsWith('/apps/desktop/release/mac-arm64'));
assert.equal(removed[1][1].recursive, true);
assert.equal(removed[1][1].force, true);
assert.deepEqual(
asserted.map((path) => path.replaceAll('\\', '/')),
[
`${desktopRoot.pathname.replace(/\/$/, '')}/release/Maka-${desktopManifest.version}-mac-arm64.dmg`,
`${desktopRoot.pathname.replace(/\/$/, '')}/release/Maka-${desktopManifest.version}-mac-arm64.zip`,
`${desktopRoot.pathname.replace(/\/$/, '')}/release/latest-mac.yml`,
],
);
assert.ok(result.endsWith(`/apps/desktop/release/Maka-${desktopManifest.version}-mac-arm64.dmg`));
});
test('release package script refuses an unsupported host or incomplete signing identity', async () => {
const { packageMacosArm64 } = await import(new URL('package-macos-arm64.mjs', import.meta.url));
await assert.rejects(
packageMacosArm64({
platform: 'darwin',
arch: 'x64',
env: signingEnvironment,
}),
/Apple Silicon macOS host/,
);
await assert.rejects(
packageMacosArm64({
platform: 'darwin',
arch: 'arm64',
env: {},
}),
/CSC_LINK/,
);
});
test('packaged app verification proves identity, notarization, resources, PTY, and renderer launch', async () => {
const { verifyPackagedMacApp } = await import(
new URL('verify-macos-arm64-dmg.mjs', import.meta.url)
);
const commands = [];
const requiredPaths = [];
const forbiddenPaths = [];
const rendererLaunches = [];
const workerLaunches = [];
await verifyPackagedMacApp('/tmp/Maka.app', {
run: async (command, args, options) => {
commands.push([command, args, options]);
if (command === 'plutil') {
return args[1] === 'CFBundleIdentifier'
? { stdout: 'com.maka.desktop\n', stderr: '' }
: args[1] === 'CFBundleShortVersionString'
? { stdout: `${desktopManifest.version}\n`, stderr: '' }
: { stdout: 'Maka\n', stderr: '' };
}
if (command === 'lipo') {
return { stdout: 'arm64\n', stderr: '' };
}
if (args[0] === '--version') {
return { stdout: `officecli ${officeCliVersion}\n`, stderr: '' };
}
return { stdout: '', stderr: '' };
},
requirePath: async (path) => {
requiredPaths.push(path);
},
forbidPath: async (path) => {
forbiddenPaths.push(path);
},
smokeRenderer: async (executable, options) => {
rendererLaunches.push([executable, options]);
},
smokeFilesystemWorker: async (executable, worker, options) => {
workerLaunches.push([executable, worker, options]);
},
});
assert.equal(
commands.some(
([command, args]) =>
command === 'codesign' && args.includes('--deep') && args.includes('/tmp/Maka.app'),
),
true,
);
assert.equal(
commands.some(
([command, args]) =>
command === 'spctl' && args.includes('--assess') && args.includes('/tmp/Maka.app'),
),
true,
);
assert.equal(
commands.some(
([command, args]) =>
command === 'xcrun' && args[0] === 'stapler' && args.includes('/tmp/Maka.app'),
),
true,
);
assert.equal(
commands.some(
([command, args], index) =>
command === '/tmp/Maka.app/Contents/MacOS/Maka' &&
args[0] === '-e' &&
args[1].includes("requireFromApp('node-pty')") &&
commands[index][2]?.env?.ELECTRON_RUN_AS_NODE === '1',
),
true,
);
assert.equal(
requiredPaths.some((path) => path.endsWith('/Resources/app.asar')),
true,
);
assert.equal(
requiredPaths.some((path) => path.endsWith('/Resources/workers/filesystem-worker.js')),
true,
);
for (const licensePath of [
'/Resources/licenses/officecli/ATTRIBUTION.md',
'/Resources/licenses/maka/LICENSE',
'/Resources/licenses/maka/NOTICE',
'/Resources/licenses/renderer/THIRD_PARTY_LICENSES.txt',
'/Resources/licenses/renderer/GEIST_LICENSE.txt',
'/Resources/licenses/renderer/GEIST_MONO_LICENSE.txt',
'/Resources/licenses/renderer/ANT_DESIGN_ICONS_LICENSE.txt',
'/Resources/licenses/renderer/SIMPLE_ICONS_LICENSE.md',
]) {
assert.equal(
requiredPaths.some((path) => path.endsWith(licensePath)),
true,
`missing final artifact check for ${licensePath}`,
);
}
assert.equal(
forbiddenPaths.some((path) => path.endsWith('/Resources/bin/cua-driver')),
true,
);
assert.equal(rendererLaunches.length, 1);
assert.deepEqual(workerLaunches, [
[
'/tmp/Maka.app/Contents/MacOS/Maka',
'/tmp/Maka.app/Contents/Resources/workers/filesystem-worker.js',
{ workingDirectory: '/tmp' },
],
]);
});
test('packaged app verification rejects a non-arm64 executable', async () => {
const { verifyPackagedMacApp } = await import(
new URL('verify-macos-arm64-dmg.mjs', import.meta.url)
);
await assert.rejects(
verifyPackagedMacApp('/tmp/Maka.app', {
run: async (command, args) => {
if (command === 'plutil') {
return args[1] === 'CFBundleIdentifier'
? { stdout: 'com.maka.desktop\n', stderr: '' }
: args[1] === 'CFBundleShortVersionString'
? { stdout: `${desktopManifest.version}\n`, stderr: '' }
: { stdout: 'Maka\n', stderr: '' };
}
if (command === 'lipo') {
return { stdout: 'x86_64\n', stderr: '' };
}
return { stdout: `officecli ${officeCliVersion}\n`, stderr: '' };
},
requirePath: async () => {},
forbidPath: async () => {},
smokeRenderer: async () => {},
}),
/arm64/,
);
});
test('renderer readiness rejects the static preload skeleton', async () => {
const { isPackagedRendererUsable } = await import(
new URL('verify-macos-arm64-dmg.mjs', import.meta.url)
);
assert.equal(
isPackagedRendererUsable({
readyState: 'complete',
hasBridge: true,
hasRoot: true,
hasPreloadSkeleton: true,
hasAppShell: false,
}),
false,
);
assert.equal(
isPackagedRendererUsable({
readyState: 'complete',
hasBridge: true,
hasRoot: true,
hasPreloadSkeleton: false,
hasAppShell: true,
}),
true,
);
});
test('one manual workflow packages, verifies, then creates one draft release from main', async () => {
const workflow = await readFile(
new URL('.github/workflows/release-macos-arm64.yml', repoRoot),
'utf8',
);
assert.match(workflow, /^on:\n workflow_dispatch:\s*$/m);
assert.match(workflow, /permissions:\n contents: write/);
assert.match(workflow, /jobs:\n release:/);
assert.match(workflow, /if: github\.ref == 'refs\/heads\/main'/);
assert.match(workflow, /runs-on: macos-15/);
assert.match(workflow, /environment: release/);
assert.match(workflow, /node-version: ['"]?24['"]?/);
assert.match(workflow, /ref: \$\{\{ github\.sha \}\}/);
assert.match(workflow, /persist-credentials: false/);
assert.doesNotMatch(workflow, /\bmatrix:/);
assert.doesNotMatch(workflow, /^\s+push:/m);
assert.doesNotMatch(workflow, /^\s+workflow_call:/m);
const jobHeader = workflow.slice(workflow.indexOf('jobs:'), workflow.indexOf('\n steps:'));
assert.doesNotMatch(jobHeader, /secrets\.|GH_TOKEN/);
const packageStep = workflow.indexOf('npm run package:macos-arm64');
const removeKeyStep = workflow.indexOf('Remove the temporary notarization key');
const auditStep = workflow.indexOf('npm audit --omit=dev --audit-level=high');
const verifyStep = workflow.indexOf('npm run verify:macos-arm64');
const releaseStep = workflow.indexOf('gh release create');
assert.ok(auditStep > 0);
assert.ok(packageStep > auditStep);
assert.ok(packageStep > 0);
assert.ok(removeKeyStep > packageStep);
assert.ok(verifyStep > removeKeyStep);
assert.ok(verifyStep > packageStep);
assert.ok(releaseStep > verifyStep);
assert.match(workflow, /gh release create[\s\S]*--draft/);
assert.match(workflow, /--target "\$GITHUB_SHA"/);
assert.match(workflow, /\$\{DMG_PATH\}\.sha256/);
assert.match(workflow, /\$\{\{ steps\.release\.outputs\.zip \}\}/);
assert.match(workflow, /\$\{\{ steps\.release\.outputs\.update_yml \}\}/);
});
test('the distributable includes OfficeCLI Apache-2.0 attribution', async () => {
const license = await readFile(new URL('LICENSE', repoRoot), 'utf8');
const attribution = await readFile(
new URL('resources/licenses/officecli/ATTRIBUTION.md', desktopRoot),
'utf8',
);
assert.match(license, /Apache License\s+Version 2\.0, January 2004/);
assert.match(license, /END OF TERMS AND CONDITIONS/);
assert.match(attribution, new RegExp(`OfficeCLI ${bundledTools.officecli.version}`));
assert.match(attribution, /github\.com\/iOfficeAI\/OfficeCLI/);
assert.match(attribution, /Copyright 2026 OfficeCli/);
});
test('the distributable includes the governed Ant Design Icons license', async () => {
const antDesign = await readFile(
new URL('resources/licenses/renderer/ANT_DESIGN_ICONS_LICENSE.txt', desktopRoot),
'utf8',
);
assert.match(antDesign, /Copyright \(c\) 2018-present Ant UED/);
assert.match(antDesign, /MIT LICENSE/);
});
test('generated release artifacts never enter source control', async () => {
const gitignore = await readFile(new URL('.gitignore', repoRoot), 'utf8');
assert.match(gitignore, /^apps\/desktop\/release\/$/m);
assert.match(gitignore, /^apps\/desktop\/resources\/tools\/$/m);
});