Files
Michał Pierzchała b15121ffc8 test(ios): establish snapshot convergence baselines and permanent evidence (#2204)
* test(ios): add snapshot convergence evidence harness

* fix(ios): satisfy benchmark CI guards

* fix(ios): constrain benchmark proxy routes

* fix(ios-benchmark): enforce cell admission evidence

* fix(ios-benchmark): protect benchmark state ownership

* fix(ios-benchmark): use proxy port flag

* fix(ios-benchmark): let proxy choose an ephemeral port

* test(ios-benchmark): keep CLI process seam local

* fix(ios-benchmark): parse proxy startup envelope

* fix(ios-benchmark): bind proxy lease to simulator

* fix(ios-benchmark): keep fresh proxy CLI sessions isolated

* fix(ios-benchmark): preserve async timeout evidence

* docs(ios-benchmark): retain exact-head evidence

* test(ios): reveal offscreen alert fixture controls

* test(ios): reset alert between relaunch samples

* test(ios): admit native alert snapshots

* docs(ios): publish snapshot convergence corpus

* chore(ios): format benchmark evidence

* fix(ios-benchmark): admit proxy fixture anchors

* docs(ios): republish exact-head benchmark corpus

* fix(size): make publish asset evidence hermetic

* style(size): format package evidence test

* test(size): update publish preparation contracts

* fix: retire stale utils layering zone

* test: pin shared publish asset owner

* test: verify preserved size reporter closure

* fix: move mutation ownership to snapshot module

* test(ios): add snapshot convergence evidence harness

* fix(ios): satisfy benchmark CI guards

* fix(ios): constrain benchmark proxy routes

* fix(ios-benchmark): enforce cell admission evidence

* fix(ios-benchmark): protect benchmark state ownership

* fix(ios-benchmark): use proxy port flag

* fix(ios-benchmark): let proxy choose an ephemeral port

* test(ios-benchmark): keep CLI process seam local

* fix(ios-benchmark): parse proxy startup envelope

* fix(ios-benchmark): bind proxy lease to simulator

* fix(ios-benchmark): keep fresh proxy CLI sessions isolated

* fix(ios-benchmark): preserve async timeout evidence

* docs(ios-benchmark): retain exact-head evidence

* test(ios): reveal offscreen alert fixture controls

* test(ios): reset alert between relaunch samples

* test(ios): admit native alert snapshots

* docs(ios): publish snapshot convergence corpus

* chore(ios): format benchmark evidence

* fix(ios-benchmark): admit proxy fixture anchors

* docs(ios): republish exact-head benchmark corpus

* fix(size): make publish asset evidence hermetic

* test(size): update publish preparation contracts

* fix: keep git-state gates out of mutation sandboxes
2026-09-01 21:39:05 +02:00

90 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const HELPERS = [
{
name: 'snapshot',
directory: path.join('android', 'snapshot-helper', 'dist'),
releaseTag: true,
},
{
name: 'ime',
directory: path.join('android', 'ime-helper', 'dist'),
releaseTag: false,
},
];
export function preparePublishAssets(options = {}) {
const root = path.resolve(options.root ?? process.cwd());
const version = readPackageVersion(root);
const packageAppleRunnerScript = path.join(root, 'scripts', 'package-apple-runner-source.mjs');
const packageAndroidHelperScript = path.join(root, 'scripts', 'package-android-helper.sh');
run(process.execPath, [packageAppleRunnerScript, '--quiet'], root);
for (const helper of HELPERS) {
const outputDirectory = path.join(root, helper.directory);
fs.rmSync(outputDirectory, { recursive: true, force: true });
const helperArguments = [version];
if (helper.releaseTag) helperArguments.push(`v${version}`);
helperArguments.push(outputDirectory);
run('sh', [packageAndroidHelperScript, ...helperArguments], root, {
AGENT_DEVICE_ANDROID_HELPER: helper.name,
});
}
assertPreparedAssets(root, version);
return { root, version };
}
function readPackageVersion(root) {
const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
if (typeof packageJson.version !== 'string' || packageJson.version.length === 0) {
throw new Error('package.json must declare a non-empty version');
}
return packageJson.version;
}
function run(command, arguments_, root, environment = {}) {
execFileSync(command, arguments_, {
cwd: root,
env: { ...process.env, ...environment },
stdio: ['ignore', 'ignore', 'inherit'],
});
}
function assertPreparedAssets(root, version) {
for (const helper of HELPERS) {
const directory = path.join(root, helper.directory);
for (const suffix of ['.apk', '.manifest.json', '.apk.sha256']) {
const filePath = path.join(
directory,
`agent-device-android-${helper.name}-helper-${version}${suffix}`,
);
if (!isNonEmptyFile(filePath)) {
throw new Error(`Publish asset was not prepared: ${filePath}`);
}
}
}
}
function isNonEmptyFile(filePath) {
try {
const stat = fs.statSync(filePath);
return stat.isFile() && stat.size > 0;
} catch {
return false;
}
}
function isMainModule() {
return process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
}
if (isMainModule()) {
const result = preparePublishAssets();
process.stdout.write(`Prepared publish assets for ${result.version}.\n`);
}