blob: 54db5fa15f05d51c4995ee780227a9bd49a17630 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { execFile } from 'node:child_process';
import { copyFile, mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { basename, join, resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import { promisify } from 'node:util';
import { npmSpawnOptions } from '../npm-spawn.mjs';
import { desktopShell } from './build-cli.mjs';
import { readPreviewRelease } from './publish-cli.mjs';
const run = promisify(execFile);
/** Exercise the actual packaged launcher and this machine's native component. */
export async function verifyRelease(directory) {
const packages = await readPreviewRelease(directory);
const target = `${process.platform}-${process.arch}${process.platform === 'linux' ? '-gnu' : ''}`;
const native = packages.find((pkg) => pkg.name === '@maka-agent/cli-' + target);
if (!native) throw new Error('No native release for this verifier: ' + target);
const launcher = packages.find((pkg) => pkg.name === '@maka-agent/cli');
const stage = await mkdtemp(join(tmpdir(), 'maka release verification '));
try {
await writeFile(
join(stage, 'package.json'),
JSON.stringify({ name: 'maka-release-verification', private: true }),
);
for (const pkg of [native, launcher])
await copyFile(pkg.archive, join(stage, basename(pkg.archive)));
await run(
'npm',
[
'install',
'--offline',
'--ignore-scripts',
'--no-audit',
'--no-fund',
'./' + basename(native.archive),
'./' + basename(launcher.archive),
],
npmSpawnOptions({ cwd: stage, timeout: 180_000, maxBuffer: 1024 * 1024 }),
);
const command = join(stage, 'node_modules/@maka-agent/cli/bin/maka.mjs');
const options = { cwd: stage, timeout: 30_000, maxBuffer: 1024 * 1024, encoding: 'utf8' };
const { stdout } = await run(process.execPath, [command, '--version'], options);
if (stdout.trim() !== 'maka ' + native.source.version)
throw new Error('Installed launcher reports another source version');
const desktop = await run(
join(stage, 'node_modules', native.name, 'bin', desktopShell(process.platform)),
['--version'],
options,
);
if (desktop.stdout.trim() !== 'maka-desktop-shell ' + native.source.version)
throw new Error('Installed desktop shell reports another source version');
const terminal = await run(process.execPath, [command, 'terminal-shell', '--version'], options);
if (!terminal.stdout.trim().endsWith(' ' + native.source.version))
throw new Error('Installed terminal shell reports another source version');
const result = await new Promise((resolveResult, reject) => {
const child = execFile(
process.execPath,
[command, 'code', '--log', join(stage, 'code.sqlite')],
options,
(error, stdout) => (error ? reject(error) : resolveResult(stdout)),
);
child.stdin.end(
'if (Math.abs(Math.sin(1) - 0.8414709848078965) > 1e-15 || Math.cos(0) !== 1 || !new Intl.DateTimeFormat("en").format(new Date(0)) || Temporal.PlainDate.from("2026-09-28").year !== 2026) throw new Error("V8 smoke failed");',
);
child.stdin.on('error', reject);
});
if (JSON.parse(result).output?.ok !== true)
throw new Error('Installed launcher failed its V8 smoke');
return { target, version: native.version };
} finally {
await rm(stage, { recursive: true, force: true });
}
}
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
if (process.argv.length !== 3) throw new Error('Usage: verify-release.mjs <artifact-directory>');
console.log(JSON.stringify(await verifyRelease(process.argv[2])));
}