[apply-patch] Add binary to path

This commit is contained in:
Dylan Hurd
2025-08-23 12:26:13 -07:00
parent eca97d8559
commit 19af6d2fec
5 changed files with 88 additions and 2 deletions

View File

@@ -95,7 +95,7 @@ jobs:
sudo apt install -y musl-tools pkg-config
- name: Cargo build
run: cargo build --target ${{ matrix.target }} --release --bin codex
run: cargo build --target ${{ matrix.target }} --release --bin codex --bin apply-patch
- name: Stage artifacts
shell: bash
@@ -105,8 +105,10 @@ jobs:
if [[ "${{ matrix.runner }}" == windows* ]]; then
cp target/${{ matrix.target }}/release/codex.exe "$dest/codex-${{ matrix.target }}.exe"
cp target/${{ matrix.target }}/release/apply-patch.exe "$dest/apply-patch-${{ matrix.target }}.exe"
else
cp target/${{ matrix.target }}/release/codex "$dest/codex-${{ matrix.target }}"
cp target/${{ matrix.target }}/release/apply-patch "$dest/apply-patch-${{ matrix.target }}"
fi
- name: Compress artifacts

View File

@@ -2,6 +2,9 @@
// Unified entry point for the Codex CLI.
import path from "path";
import os from "os";
import fs from "fs";
import { createRequire } from "module";
import { fileURLToPath } from "url";
// __dirname equivalent in ESM
@@ -56,7 +59,9 @@ if (!targetTriple) {
throw new Error(`Unsupported platform: ${platform} (${arch})`);
}
const binaryPath = path.join(__dirname, "..", "bin", `codex-${targetTriple}`);
const pkgRoot = path.join(__dirname, "..");
const pkgBinDir = path.join(pkgRoot, "bin");
const binaryPath = path.join(pkgBinDir, `codex-${targetTriple}`);
// 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
@@ -93,10 +98,35 @@ function getUpdatedPath(newDirs) {
}
const additionalDirs = [];
// 1) Make packaged bin directory available on PATH for any helper binaries.
additionalDirs.push(pkgBinDir);
const rgDir = await resolveRgDir();
if (rgDir) {
additionalDirs.push(rgDir);
}
// 2) Ensure an `apply_patch` helper exists in $CODEX_HOME/<version>/ and add that directory to PATH.
try {
const require = createRequire(import.meta.url);
// Load package.json to read the version string.
const { version } = require("../package.json");
const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
const versionDir = path.join(codexHome, version);
fs.mkdirSync(versionDir, { recursive: true });
const isWindows = platform === "win32";
const destName = isWindows ? "apply_patch.exe" : "apply_patch";
const destPath = path.join(versionDir, destName);
const srcPath = path.join(pkgBinDir, `apply-patch-${targetTriple}`);
// Only copy if missing; keep it simple and fast.
if (!fs.existsSync(destPath)) {
fs.copyFileSync(srcPath, destPath);
if (!isWindows) {
fs.chmodSync(destPath, 0o755);
}
}
additionalDirs.push(versionDir);
} catch {
// Best-effort: if anything fails, continue without the helper.
}
const updatedPath = getUpdatedPath(additionalDirs);
const child = spawn(binaryPath, process.argv.slice(2), {

View File

@@ -75,17 +75,27 @@ gh run download --dir "$ARTIFACTS_DIR" --repo openai/codex "$WORKFLOW_ID"
# x64 Linux
zstd -d "$ARTIFACTS_DIR/x86_64-unknown-linux-musl/codex-x86_64-unknown-linux-musl.zst" \
-o "$BIN_DIR/codex-x86_64-unknown-linux-musl"
zstd -d "$ARTIFACTS_DIR/x86_64-unknown-linux-musl/apply-patch-x86_64-unknown-linux-musl.zst" \
-o "$BIN_DIR/apply-patch-x86_64-unknown-linux-musl"
# ARM64 Linux
zstd -d "$ARTIFACTS_DIR/aarch64-unknown-linux-musl/codex-aarch64-unknown-linux-musl.zst" \
-o "$BIN_DIR/codex-aarch64-unknown-linux-musl"
zstd -d "$ARTIFACTS_DIR/aarch64-unknown-linux-musl/apply-patch-aarch64-unknown-linux-musl.zst" \
-o "$BIN_DIR/apply-patch-aarch64-unknown-linux-musl"
# x64 macOS
zstd -d "$ARTIFACTS_DIR/x86_64-apple-darwin/codex-x86_64-apple-darwin.zst" \
-o "$BIN_DIR/codex-x86_64-apple-darwin"
zstd -d "$ARTIFACTS_DIR/x86_64-apple-darwin/apply-patch-x86_64-apple-darwin.zst" \
-o "$BIN_DIR/apply-patch-x86_64-apple-darwin"
# ARM64 macOS
zstd -d "$ARTIFACTS_DIR/aarch64-apple-darwin/codex-aarch64-apple-darwin.zst" \
-o "$BIN_DIR/codex-aarch64-apple-darwin"
zstd -d "$ARTIFACTS_DIR/aarch64-apple-darwin/apply-patch-aarch64-apple-darwin.zst" \
-o "$BIN_DIR/apply-patch-aarch64-apple-darwin"
# x64 Windows
zstd -d "$ARTIFACTS_DIR/x86_64-pc-windows-msvc/codex-x86_64-pc-windows-msvc.exe.zst" \
-o "$BIN_DIR/codex-x86_64-pc-windows-msvc.exe"
zstd -d "$ARTIFACTS_DIR/x86_64-pc-windows-msvc/apply-patch-x86_64-pc-windows-msvc.exe.zst" \
-o "$BIN_DIR/apply-patch-x86_64-pc-windows-msvc.exe"
echo "Installed native dependencies into $BIN_DIR"

View File

@@ -6,6 +6,10 @@ version = { workspace = true }
[lib]
name = "codex_apply_patch"
path = "src/lib.rs"
[[bin]]
name = "apply-patch"
path = "src/main.rs"
[lints]
workspace = true

View File

@@ -0,0 +1,40 @@
use std::io::Write;
use std::process::ExitCode;
fn main() -> ExitCode {
// Expect exactly one argument: the full apply_patch payload.
let mut args = std::env::args_os();
// argv[0]
let _argv0 = args.next();
let patch_arg = match args.next() {
Some(arg) => match arg.into_string() {
Ok(s) => s,
Err(_) => {
eprintln!("Error: apply-patch requires a UTF-8 PATCH argument.");
return ExitCode::from(1);
}
},
None => {
eprintln!("Usage: apply-patch '<apply_patch_payload>'");
return ExitCode::from(2);
}
};
// Refuse extra args to avoid ambiguity.
if args.next().is_some() {
eprintln!("Error: apply-patch accepts exactly one argument.");
return ExitCode::from(2);
}
let mut stdout = std::io::stdout();
let mut stderr = std::io::stderr();
match codex_apply_patch::apply_patch(&patch_arg, &mut stdout, &mut stderr) {
Ok(()) => {
// Flush to ensure output ordering when used in pipelines.
let _ = stdout.flush();
ExitCode::from(0)
}
Err(_) => ExitCode::from(1),
}
}