fix(release): enforce binary version integrity pre/post publish

This commit is contained in:
leeguooooo
2026-03-04 15:01:52 +09:00
parent 59589043db
commit 17d44baa2f
5 changed files with 275 additions and 20 deletions
+52 -16
View File
@@ -2,19 +2,29 @@
/**
* Postinstall script for agent-browser
*
*
* Downloads the platform-specific native binary if not present.
* On global installs, patches npm's bin entry to use the native binary directly:
* - Windows: Overwrites .cmd/.ps1 shims
* - Mac/Linux: Replaces symlink to point to native binary
*/
import { existsSync, mkdirSync, chmodSync, createWriteStream, unlinkSync, writeFileSync, symlinkSync, lstatSync, readFileSync } from 'fs';
import {
existsSync,
mkdirSync,
chmodSync,
createWriteStream,
unlinkSync,
writeFileSync,
symlinkSync,
lstatSync,
readFileSync,
} from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { platform, arch } from 'os';
import { get } from 'https';
import { execSync } from 'child_process';
import { execFileSync, execSync } from 'child_process';
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = join(__dirname, '..');
@@ -65,7 +75,7 @@ function getBinCommands(pkg) {
async function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
const file = createWriteStream(dest);
const request = (url) => {
get(url, (response) => {
// Handle redirects
@@ -73,12 +83,12 @@ async function downloadFile(url, dest) {
request(response.headers.location);
return;
}
if (response.statusCode !== 200) {
reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
return;
}
response.pipe(file);
file.on('finish', () => {
file.close();
@@ -89,7 +99,7 @@ async function downloadFile(url, dest) {
reject(err);
});
};
request(url);
});
}
@@ -101,13 +111,21 @@ async function main() {
if (platform() !== 'win32') {
chmodSync(binaryPath, 0o755);
}
console.log(`✓ Native binary ready: ${binaryName}`);
// On global installs, fix npm's bin entry to use native binary directly
await fixGlobalInstallBin();
showPlaywrightReminder();
return;
const installedVersion = readBinaryVersion(binaryPath);
if (installedVersion.includes(version)) {
console.log(`✓ Native binary ready: ${binaryName}`);
// On global installs, fix npm's bin entry to use native binary directly
await fixGlobalInstallBin();
showPlaywrightReminder();
return;
}
console.log(
`⚠ Binary version mismatch detected: expected ${version}, got "${installedVersion || 'unknown'}"`
);
console.log(` Re-downloading ${binaryName} from release assets...`);
}
// Ensure bin directory exists
@@ -120,12 +138,19 @@ async function main() {
try {
await downloadFile(DOWNLOAD_URL, binaryPath);
// Make executable on Unix
if (platform() !== 'win32') {
chmodSync(binaryPath, 0o755);
}
const downloadedVersion = readBinaryVersion(binaryPath);
if (!downloadedVersion.includes(version)) {
throw new Error(
`downloaded binary version mismatch: expected ${version}, got "${downloadedVersion || 'unknown'}"`
);
}
console.log(`✓ Downloaded native binary: ${binaryName}`);
} catch (err) {
console.log(`⚠ Could not download native binary: ${err.message}`);
@@ -143,6 +168,17 @@ async function main() {
showPlaywrightReminder();
}
function readBinaryVersion(path) {
try {
return execFileSync(path, ['--version'], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
} catch {
return '';
}
}
function showPlaywrightReminder() {
console.log('');
console.log('╔═══════════════════════════════════════════════════════════════════════════╗');