#!/usr/bin/env node import { spawnSync } from 'node:child_process'; import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; const PREFLIGHT_SCRIPT = 'scripts/check-pingora-direct-preflight.mjs'; const failures = []; const tmpRoot = mkdtempSync( path.join(tmpdir(), 'genarrative-pingora-direct-preflight-guard-'), ); try { main(); } finally { rmSync(tmpRoot, { recursive: true, force: true }); } if (failures.length > 0) { console.error('[check:pingora-direct-preflight-guard] FAILED'); for (const failure of failures) { console.error(`- ${failure}`); } process.exit(1); } console.log('[check:pingora-direct-preflight-guard] OK'); function main() { assertRejectsEnvFileWithControlCharacters(); assertRejectsSystemdServiceWithControlCharactersBeforeSystemctl(); } function assertRejectsEnvFileWithControlCharacters() { const fixture = prepareFixture('env-file-control-character'); const result = runPreflight(fixture, [ '--env-file', `${path.join(fixture.root, 'pingora-gateway.env')}\n--fake-flag`, '--require-live-env', ]); assertNonZero(result, 'direct preflight 必须拒绝带换行的 --env-file。'); assertIncludes( `${result.stdout}\n${result.stderr}`, '--env-file 不能包含换行或 NUL 字符', '带换行的 --env-file 必须给出明确错误。', ); } function assertRejectsSystemdServiceWithControlCharactersBeforeSystemctl() { const fixture = prepareFixture('systemd-service-control-character'); const result = runPreflight(fixture, [ '--systemd-cat', '--systemd-service', 'genarrative-pingora-gateway.service\n--fake-flag', ]); assertNonZero( result, 'direct preflight 必须拒绝带换行的 systemd service 参数。', ); assertIncludes( `${result.stdout}\n${result.stderr}`, '子命令参数 不能包含换行或 NUL 字符', '带换行的 systemd service 参数必须在执行 systemctl 前失败。', ); const commandsLog = readFileSync(fixture.commandsLog, 'utf8'); if (commandsLog.includes('systemctl')) { failures.push('systemd service 含控制字符时必须在执行 systemctl 前失败。'); } } function prepareFixture(name) { const root = path.join(tmpRoot, name); const fakeBin = path.join(root, 'bin'); const commandsLog = path.join(root, 'commands.log'); mkdirSync(fakeBin, { recursive: true }); writeFileSync(commandsLog, '', 'utf8'); writeFileSync( path.join(fakeBin, 'systemctl'), [ '#!/usr/bin/env bash', `printf 'systemctl %s\\n' "$*" >> ${shellQuote(commandsLog)}`, 'cat <