pnpm-upgrade

Keep pnpm current: preflight the published package and pnpm/action-setup self-installer, update pnpm locally, align packageManager in package.json, and refresh CI pins. Use this when refreshing the pnpm toolchain manually or in automation.

Install
npx skills add 'https://github.com/openai/openai-agents-js/tree/main/.agents/skills/pnpm-upgrade'
Download bundle ↓
main · 506f736Scanned 2026-09-17

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

scripts/preflight.mjs

scripts/preflight.mjsBrowse 3 files
View on GitHub
← Back to SKILL.md
#!/usr/bin/env node import { spawn } from 'node:child_process';import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';import { tmpdir } from 'node:os';import path from 'node:path'; const { console, fetch, process } = globalThis; function readArg(name) {  const index = process.argv.indexOf(name);  if (index === -1 || !process.argv[index + 1]) {    throw new Error(`Missing required argument: ${name}`);  }  return process.argv[index + 1];} async function fetchJson(url) {  const response = await fetch(url, {    headers: { 'user-agent': 'openai-agents-js-pnpm-upgrade-preflight' },  });  if (!response.ok) {    throw new Error(`Request failed (${response.status}): ${url}`);  }  return response.json();} function run(command, args, options) {  return new Promise((resolve, reject) => {    const child = spawn(command, args, {      ...options,      stdio: 'inherit',    });    child.on('error', reject);    child.on('close', (code, signal) => {      if (code === 0) {        resolve();        return;      }      reject(        new Error(          `${command} exited with ${signal ? `signal ${signal}` : `code ${code}`}`,        ),      );    });  });} async function loadBootstrap(actionRef, options) {  const lock = await fetchJson(    `https://raw.githubusercontent.com/pnpm/action-setup/${actionRef}/src/install-pnpm/bootstrap/${options.lockFile}`,  );  const version = lock.packages?.[options.packageKey]?.version;  if (!version) {    throw new Error(      `Could not resolve the ${options.label} bootstrap version from pnpm/action-setup@${actionRef}.`,    );  }  return { ...options, lock, version };} async function runBootstrapProbe(bootstrap, targetVersion) {  const workDir = await mkdtemp(    path.join(tmpdir(), `pnpm-upgrade-preflight-${bootstrap.label}-`),  );  try {    await writeFile(      path.join(workDir, 'package.json'),      `${JSON.stringify({ private: true, dependencies: { [bootstrap.packageName]: bootstrap.version } }, null, 2)}\n`,    );    await writeFile(      path.join(workDir, 'package-lock.json'),      `${JSON.stringify(bootstrap.lock, null, 2)}\n`,    );    await run('npm', ['ci'], {      cwd: workDir,      env: process.env,      shell: process.platform === 'win32',    });     const pnpmHome =      bootstrap.label === 'standalone' && process.platform === 'win32'        ? path.join(workDir, 'node_modules', '@pnpm', 'exe')        : path.join(workDir, 'node_modules', '.bin');    const xdgDataHome = path.join(workDir, 'xdg-data');    await mkdir(xdgDataHome, { recursive: true });    const bootstrapPnpm =      bootstrap.label === 'standalone'        ? path.join(            workDir,            'node_modules',            '@pnpm',            'exe',            process.platform === 'win32' ? 'pnpm.exe' : 'pnpm',          )        : path.join(workDir, 'node_modules', 'pnpm', 'bin', 'pnpm.mjs');    const command =      bootstrap.label === 'standalone' ? bootstrapPnpm : process.execPath;    const args =      bootstrap.label === 'standalone'        ? ['self-update', targetVersion]        : [bootstrapPnpm, 'self-update', targetVersion];    await run(command, args, {      cwd: workDir,      env: {        ...process.env,        PNPM_HOME: pnpmHome,        XDG_DATA_HOME: xdgDataHome,      },    });  } finally {    await rm(workDir, { recursive: true, force: true });  }   console.log(    `Preflight passed for the ${bootstrap.label} pnpm/action-setup bootstrap ${bootstrap.version}.`,  );} function assertDependencyFreeManifest(manifest, version) {  const dependencies = Object.keys(manifest.dependencies ?? {});  const devDependencies = Object.keys(manifest.devDependencies ?? {});  if (dependencies.length === 0 && devDependencies.length === 0) return;   const summarize = (names) =>    names.length === 0      ? 'none'      : `${names.length}: ${names.slice(0, 10).join(', ')}${names.length > 10 ? ', ...' : ''}`;  throw new Error(    [      `pnpm@${version} has an unexpected published manifest.`,      `dependencies (${summarize(dependencies)})`,      `devDependencies (${summarize(devDependencies)})`,      'pnpm bundles its runtime dependencies; aborting before the pnpm/action-setup self-installer runs.',    ].join('\n'),  );} async function main() {  const version = readArg('--version');  const actionRef = readArg('--action-ref');  if (!/^[0-9a-f]{40}$/.test(actionRef)) {    throw new Error('--action-ref must be a 40-character commit SHA.');  }   const manifest = await fetchJson(    `https://registry.npmjs.org/pnpm/${encodeURIComponent(version)}`,  );  if (manifest.version !== version) {    throw new Error(      `Registry returned pnpm@${manifest.version ?? 'unknown'} instead of pnpm@${version}.`,    );  }  assertDependencyFreeManifest(manifest, version);   const bootstraps = await Promise.all([    loadBootstrap(actionRef, {      label: 'regular',      lockFile: 'pnpm-lock.json',      packageKey: 'node_modules/pnpm',      packageName: 'pnpm',    }),    loadBootstrap(actionRef, {      label: 'standalone',      lockFile: 'exe-lock.json',      packageKey: 'node_modules/@pnpm/exe',      packageName: '@pnpm/exe',    }),  ]);   for (const bootstrap of bootstraps) {    await runBootstrapProbe(bootstrap, version);  }   console.log(    `Preflight passed: all pnpm/action-setup bootstrap paths can self-update to pnpm ${version}.`,  );} main().catch((error) => {  console.error(error instanceof Error ? error.message : error);  process.exitCode = 1;});