mirror of
https://github.com/openai/codex.git
synced 2026-09-13 11:47:17 +00:00
npm: ship platform packages in Codex package layout
## Summary
The npm platform packages should stop carrying a bespoke native layout now that the release workflow builds canonical Codex package archives. Keeping npm on the same `bin/`, `codex-resources/`, and `codex-path/` structure lets the Rust package-layout detection behave consistently across standalone, npm, and future DotSlash installs.
This changes platform npm packages to stage the `codex-package` artifact for each target under `vendor/<target>`. The Node launcher now resolves `bin/codex` and prepends `codex-path`, while retaining legacy `vendor/<target>/codex` and `vendor/<target>/path` fallback support for local development and migration. The npm staging helper downloads `codex-package` archives instead of rebuilding the CLI payload from individual `codex`, `rg`, `bwrap`, and sandbox helper artifacts.
CI still needs to stage npm packages from historical rust-release workflow artifacts that predate package archives, so the staging scripts now expose an explicit `--allow-legacy-codex-package` fallback. That fallback synthesizes the canonical package layout from legacy per-binary artifacts and is wired only into the CI smoke path; release staging remains strict and continues to require real package archives.
## Test plan
- `python3 -m py_compile codex-cli/scripts/build_npm_package.py codex-cli/scripts/install_native_deps.py scripts/stage_npm_packages.py scripts/codex_package/cli.py`
- `node --check codex-cli/bin/codex.js`
- `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/rust-release.yml"); YAML.load_file(".github/workflows/ci.yml"); puts "ok"'`
- Staged a synthetic `codex-linux-x64` platform package from a canonical vendor tree and verified it copied only `bin/`, `codex-path/`, `codex-resources/`, and `codex-package.json`.
- Imported `install_native_deps.py` and extracted a synthetic `codex-package-x86_64-unknown-linux-musl.tar.gz` into `vendor/<target>`.
- Ran legacy-layout conversion smokes for Linux, Windows, and unsigned macOS artifact naming.
- `NPM_CONFIG_CACHE="$tmp_dir/npm-cache" python3 ./scripts/stage_npm_packages.py --release-version 0.125.0 --workflow-url https://github.com/openai/codex/actions/runs/26131514935 --package codex --allow-legacy-codex-package --output-dir "$tmp_dir"`
- `node codex-cli/bin/codex.js --version`
This commit is contained in:
@@ -77,33 +77,43 @@ if (!platformPackage) {
|
||||
|
||||
const codexBinaryName = process.platform === "win32" ? "codex.exe" : "codex";
|
||||
const localVendorRoot = path.join(__dirname, "..", "vendor");
|
||||
const localBinaryPath = path.join(
|
||||
localVendorRoot,
|
||||
targetTriple,
|
||||
"codex",
|
||||
codexBinaryName,
|
||||
);
|
||||
const packageBinaryPath = (vendorRoot) =>
|
||||
path.join(vendorRoot, targetTriple, "bin", codexBinaryName);
|
||||
const legacyBinaryPath = (vendorRoot) =>
|
||||
path.join(vendorRoot, targetTriple, "codex", codexBinaryName);
|
||||
|
||||
let vendorRoot;
|
||||
try {
|
||||
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
||||
vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
|
||||
} catch {
|
||||
if (existsSync(localBinaryPath)) {
|
||||
vendorRoot = localVendorRoot;
|
||||
} else {
|
||||
const packageManager = detectPackageManager();
|
||||
const updateCommand =
|
||||
packageManager === "bun"
|
||||
? "bun install -g @openai/codex@latest"
|
||||
: "npm install -g @openai/codex@latest";
|
||||
throw new Error(
|
||||
`Missing optional dependency ${platformPackage}. Reinstall Codex: ${updateCommand}`,
|
||||
);
|
||||
function resolveNativePackage(vendorRoot) {
|
||||
const packageRoot = path.join(vendorRoot, targetTriple);
|
||||
const binaryPath = packageBinaryPath(vendorRoot);
|
||||
if (existsSync(binaryPath)) {
|
||||
return {
|
||||
binaryPath,
|
||||
pathDir: path.join(packageRoot, "codex-path"),
|
||||
};
|
||||
}
|
||||
|
||||
const legacyPath = legacyBinaryPath(vendorRoot);
|
||||
if (existsSync(legacyPath)) {
|
||||
return {
|
||||
binaryPath: legacyPath,
|
||||
pathDir: path.join(packageRoot, "path"),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!vendorRoot) {
|
||||
let nativePackage;
|
||||
try {
|
||||
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
||||
nativePackage = resolveNativePackage(
|
||||
path.join(path.dirname(packageJsonPath), "vendor"),
|
||||
);
|
||||
} catch {
|
||||
nativePackage = resolveNativePackage(localVendorRoot);
|
||||
}
|
||||
|
||||
if (!nativePackage) {
|
||||
const packageManager = detectPackageManager();
|
||||
const updateCommand =
|
||||
packageManager === "bun"
|
||||
@@ -114,8 +124,7 @@ if (!vendorRoot) {
|
||||
);
|
||||
}
|
||||
|
||||
const archRoot = path.join(vendorRoot, targetTriple);
|
||||
const binaryPath = path.join(archRoot, "codex", codexBinaryName);
|
||||
const { binaryPath, pathDir } = nativePackage;
|
||||
|
||||
// Use an asynchronous spawn instead of spawnSync so that Node is able to
|
||||
// respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
|
||||
@@ -159,7 +168,6 @@ function detectPackageManager() {
|
||||
}
|
||||
|
||||
const additionalDirs = [];
|
||||
const pathDir = path.join(archRoot, "path");
|
||||
if (existsSync(pathDir)) {
|
||||
additionalDirs.push(pathDir);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user