From fb1f99aecb6a7a80fc18a88b74ea4f37ec5a76c2 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 19 May 2026 23:52:55 -0700 Subject: [PATCH] dotslash: publish Codex entrypoints from package archives ## Summary DotSlash should resolve the same canonical package layout used by standalone installers and npm platform packages, but it should not take the size regression of downloading gzip-compressed package archives. Installers continue to use `.tar.gz` because that format is broadly available, while DotSlash can use zstd-compressed tar archives. This updates the package archive release helper to emit both `*.tar.gz` and `*.tar.zst` package archives from the same package directory. The Codex CLI and `codex-app-server` DotSlash release config entries now match `codex-package-.tar.zst` and `codex-app-server-package-.tar.zst`, with paths that select `bin/codex` or `bin/codex-app-server` inside the extracted package. The Windows release compression loop also skips prebuilt `.tar.zst` archives so it does not try to recompress them as ordinary files. The other helper outputs stay on their existing per-binary artifacts for now. ## Test plan - `python3 -m json.tool .github/dotslash-config.json > /dev/null` - `bash -n .github/scripts/build-codex-package-archive.sh` - `python3 -m py_compile scripts/codex_package/cli.py` - `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/rust-release-windows.yml"); puts "ok"'` - Ran a Python regex smoke test that checked every updated `codex` and `codex-app-server` platform entry against the `.tar.zst` archive names emitted by `.github/scripts/build-codex-package-archive.sh`. - Ran `scripts/build_codex_package.py` with synthetic macOS entrypoint and `rg` binaries and repeated `--archive-output` values for `.tar.gz` and `.tar.zst`, verifying both archives were written. --- .github/dotslash-config.json | 48 +++++++++---------- .../scripts/build-codex-package-archive.sh | 10 +++- .github/workflows/rust-release-windows.yml | 2 +- scripts/codex_package/cli.py | 9 ++-- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/.github/dotslash-config.json b/.github/dotslash-config.json index a0297c269a..78ea6b37e6 100644 --- a/.github/dotslash-config.json +++ b/.github/dotslash-config.json @@ -3,56 +3,56 @@ "codex": { "platforms": { "macos-aarch64": { - "regex": "^codex-aarch64-apple-darwin\\.zst$", - "path": "codex" + "regex": "^codex-package-aarch64-apple-darwin\\.tar\\.zst$", + "path": "bin/codex" }, "macos-x86_64": { - "regex": "^codex-x86_64-apple-darwin\\.zst$", - "path": "codex" + "regex": "^codex-package-x86_64-apple-darwin\\.tar\\.zst$", + "path": "bin/codex" }, "linux-x86_64": { - "regex": "^codex-x86_64-unknown-linux-musl-bundle\\.tar\\.zst$", - "path": "codex" + "regex": "^codex-package-x86_64-unknown-linux-musl\\.tar\\.zst$", + "path": "bin/codex" }, "linux-aarch64": { - "regex": "^codex-aarch64-unknown-linux-musl-bundle\\.tar\\.zst$", - "path": "codex" + "regex": "^codex-package-aarch64-unknown-linux-musl\\.tar\\.zst$", + "path": "bin/codex" }, "windows-x86_64": { - "regex": "^codex-x86_64-pc-windows-msvc\\.exe\\.zst$", - "path": "codex.exe" + "regex": "^codex-package-x86_64-pc-windows-msvc\\.tar\\.zst$", + "path": "bin/codex.exe" }, "windows-aarch64": { - "regex": "^codex-aarch64-pc-windows-msvc\\.exe\\.zst$", - "path": "codex.exe" + "regex": "^codex-package-aarch64-pc-windows-msvc\\.tar\\.zst$", + "path": "bin/codex.exe" } } }, "codex-app-server": { "platforms": { "macos-aarch64": { - "regex": "^codex-app-server-aarch64-apple-darwin\\.zst$", - "path": "codex-app-server" + "regex": "^codex-app-server-package-aarch64-apple-darwin\\.tar\\.zst$", + "path": "bin/codex-app-server" }, "macos-x86_64": { - "regex": "^codex-app-server-x86_64-apple-darwin\\.zst$", - "path": "codex-app-server" + "regex": "^codex-app-server-package-x86_64-apple-darwin\\.tar\\.zst$", + "path": "bin/codex-app-server" }, "linux-x86_64": { - "regex": "^codex-app-server-x86_64-unknown-linux-musl\\.zst$", - "path": "codex-app-server" + "regex": "^codex-app-server-package-x86_64-unknown-linux-musl\\.tar\\.zst$", + "path": "bin/codex-app-server" }, "linux-aarch64": { - "regex": "^codex-app-server-aarch64-unknown-linux-musl\\.zst$", - "path": "codex-app-server" + "regex": "^codex-app-server-package-aarch64-unknown-linux-musl\\.tar\\.zst$", + "path": "bin/codex-app-server" }, "windows-x86_64": { - "regex": "^codex-app-server-x86_64-pc-windows-msvc\\.exe\\.zst$", - "path": "codex-app-server.exe" + "regex": "^codex-app-server-package-x86_64-pc-windows-msvc\\.tar\\.zst$", + "path": "bin/codex-app-server.exe" }, "windows-aarch64": { - "regex": "^codex-app-server-aarch64-pc-windows-msvc\\.exe\\.zst$", - "path": "codex-app-server.exe" + "regex": "^codex-app-server-package-aarch64-pc-windows-msvc\\.tar\\.zst$", + "path": "bin/codex-app-server.exe" } } }, diff --git a/.github/scripts/build-codex-package-archive.sh b/.github/scripts/build-codex-package-archive.sh index 90eae12ef0..c475ffe952 100644 --- a/.github/scripts/build-codex-package-archive.sh +++ b/.github/scripts/build-codex-package-archive.sh @@ -97,9 +97,14 @@ else python_bin="python" fi +if ! command -v zstd >/dev/null 2>&1 && [[ -x "${repo_root}/.github/workflows/zstd" ]]; then + export PATH="${repo_root}/.github/workflows:${PATH}" +fi + mkdir -p "$archive_dir" package_dir="${RUNNER_TEMP:-/tmp}/${archive_stem}-${target}" -archive_path="${archive_dir}/${archive_stem}-${target}.tar.gz" +gzip_archive_path="${archive_dir}/${archive_stem}-${target}.tar.gz" +zstd_archive_path="${archive_dir}/${archive_stem}-${target}.tar.zst" rm -rf "$package_dir" "$python_bin" "${repo_root}/scripts/build_codex_package.py" \ @@ -108,5 +113,6 @@ rm -rf "$package_dir" --entrypoint-bin "${entrypoint_dir%/}/${entrypoint_name}${exe_suffix}" \ --cargo-profile release \ --package-dir "$package_dir" \ - --archive-output "$archive_path" \ + --archive-output "$gzip_archive_path" \ + --archive-output "$zstd_archive_path" \ --force diff --git a/.github/workflows/rust-release-windows.yml b/.github/workflows/rust-release-windows.yml index ac28b7855a..81b5a1e51b 100644 --- a/.github/workflows/rust-release-windows.yml +++ b/.github/workflows/rust-release-windows.yml @@ -295,7 +295,7 @@ jobs: base="$(basename "$f")" # Skip files that are already archives (shouldn't happen, but be # safe). - if [[ "$base" == *.tar.gz || "$base" == *.zip || "$base" == *.dmg ]]; then + if [[ "$base" == *.tar.gz || "$base" == *.tar.zst || "$base" == *.zip || "$base" == *.dmg ]]; then continue fi diff --git a/scripts/codex_package/cli.py b/scripts/codex_package/cli.py index 16324cf44d..0ca9f5d35e 100644 --- a/scripts/codex_package/cli.py +++ b/scripts/codex_package/cli.py @@ -50,9 +50,11 @@ def parse_args() -> argparse.Namespace: parser.add_argument( "--archive-output", type=Path, + action="append", + default=[], help=( - "Optional archive output path. Supported suffixes: .tar.gz, .tgz, " - ".tar.zst, .zip." + "Optional archive output path. May be repeated. Supported suffixes: " + ".tar.gz, .tgz, .tar.zst, .zip." ), ) parser.add_argument( @@ -130,8 +132,7 @@ def main() -> int: build_package_dir(package_dir, version, variant, spec, inputs) validate_package_dir(package_dir, variant, spec) - archive_output = args.archive_output - if archive_output is not None: + for archive_output in args.archive_output: archive_path = archive_output.resolve() write_archive(package_dir, archive_path, force=args.force) print(f"Built Codex package archive at {archive_path}")