| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #!/usr/bin/env node
- import assert from "node:assert/strict";
- import { execFile } from "node:child_process";
- import { constants } from "node:fs";
- import { access, lstat, mkdtemp, readFile, realpath, rm } from "node:fs/promises";
- import { tmpdir } from "node:os";
- import { isAbsolute, join, relative } from "node:path";
- import { promisify } from "node:util";
- const execFileAsync = promisify(execFile);
- const PACKAGE_NAME = "@bodicsek/codex-app-server-bridge";
- const BIN_NAME = "codex-app-server-bridge";
- const DEFAULT_CACHE = "/private/tmp/codex-app-server-bridge-npm-cache";
- const USAGE = "usage: npm run verify:git-package -- <git+https|git+ssh|git+file URL>#<vX.Y.Z|40-character-commit>";
- function selectedGitPackage(argv) {
- if (argv.length !== 1) throw new Error(USAGE);
- const packageSpec = argv[0];
- const fragmentAt = packageSpec.lastIndexOf("#");
- const repository = packageSpec.slice(0, fragmentAt);
- const revision = packageSpec.slice(fragmentAt + 1);
- const supportedRepository = /^(?:git\+https|git\+ssh|git\+file):\/\/.+\.git$/.test(repository);
- const immutableRevision = /^(?:[0-9a-fA-F]{40}|v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/.test(revision);
- if (fragmentAt <= 0 || !supportedRepository || !immutableRevision) {
- throw new Error("Git package must use a supported URL pinned to a full commit or release tag");
- }
- return { packageSpec, revision };
- }
- function isWithin(parent, child) {
- const pathFromParent = relative(parent, child);
- return pathFromParent === "" || (!pathFromParent.startsWith("..") && !isAbsolute(pathFromParent));
- }
- function commandExit(error) {
- return typeof error === "object" && error !== null && "code" in error
- ? String(error.code)
- : "unknown";
- }
- async function installPackage(prefix, cache, packageSpec) {
- try {
- await execFileAsync("npm", [
- "install",
- "--global",
- "--prefix",
- prefix,
- "--ignore-scripts",
- "--cache",
- cache,
- packageSpec,
- ], { maxBuffer: 10 * 1024 * 1024 });
- } catch (error) {
- throw new Error(`isolated npm installation failed with exit code ${commandExit(error)}`);
- }
- }
- async function installedPackage(prefix, cache) {
- const packageRoot = join(prefix, "lib", "node_modules", PACKAGE_NAME);
- const executable = join(prefix, "bin", BIN_NAME);
- await Promise.all([
- access(executable, constants.X_OK),
- access(join(packageRoot, "dist", "cli.js"), constants.R_OK),
- access(join(packageRoot, "dist", "config.js"), constants.R_OK),
- ]);
- const packageMetadata = await lstat(packageRoot);
- if (packageMetadata.isSymbolicLink()) {
- throw new Error("installed package must not be a temporary link");
- }
- const [realPrefix, realCache, realPackage, realExecutable] = await Promise.all([
- realpath(prefix),
- realpath(cache),
- realpath(packageRoot),
- realpath(executable),
- ]);
- if (!isWithin(realPrefix, realPackage) || isWithin(realCache, realPackage)) {
- throw new Error("installed package resolved outside the isolated prefix");
- }
- if (!isWithin(realPackage, realExecutable) || isWithin(realCache, realExecutable)) {
- throw new Error("installed executable resolved outside the installed package");
- }
- const manifest = JSON.parse(await readFile(join(realPackage, "package.json"), "utf8"));
- assert.equal(manifest.name, PACKAGE_NAME);
- assert.deepEqual(manifest.bin, { [BIN_NAME]: `bin/${BIN_NAME}.js` });
- return { executable, version: String(manifest.version) };
- }
- async function verifyExecutable(executable) {
- try {
- await execFileAsync(executable, ["--unsupported"], {
- env: process.env,
- maxBuffer: 1024 * 1024,
- });
- throw new Error("installed executable unexpectedly accepted an unsupported invocation");
- } catch (error) {
- if (typeof error !== "object" || error === null || !("code" in error) || error.code !== 1) {
- throw error;
- }
- const stdout = "stdout" in error ? String(error.stdout) : "";
- const stderr = "stderr" in error ? String(error.stderr) : "";
- assert.equal(stdout, "");
- assert.match(stderr, /Usage: codex-app-server-bridge app-server/);
- }
- }
- async function verify() {
- const { packageSpec, revision } = selectedGitPackage(process.argv.slice(2));
- const prefix = await mkdtemp(join(tmpdir(), "codex-app-server-bridge-git-package-"));
- const cache = process.env.CODEX_APP_SERVER_BRIDGE_NPM_CACHE ?? DEFAULT_CACHE;
- try {
- await installPackage(prefix, cache, packageSpec);
- const installed = await installedPackage(prefix, cache);
- await verifyExecutable(installed.executable);
- process.stdout.write(`${JSON.stringify({
- ok: true,
- package: `${PACKAGE_NAME}@${installed.version}`,
- revision,
- executable: `bin/${BIN_NAME}`,
- storage: "isolated-prefix",
- invocation: "verified",
- })}\n`);
- } finally {
- await rm(prefix, { recursive: true, force: true });
- }
- }
- verify().catch((error) => {
- const message = error instanceof Error ? error.message : String(error);
- process.stderr.write(`Git-package verification failed: ${message}\n`);
- process.exitCode = 1;
- });
|