release: consume standalone zsh artifacts (#30116)

## Why

Once #30114 publishes zsh independently, regular Rust releases should
reuse that protected, versioned artifact set instead of rebuilding
identical zsh binaries for every Codex version. Keeping the zsh release
tag explicit in the workflow also makes future artifact upgrades
deliberate and easy to review.

This PR assumes the first standalone artifact release will be published
as `codex-zsh-v0.1.0` before this change lands.

## What changed

- Added `CODEX_ZSH_RELEASE_TAG` near the top of
`.github/workflows/rust-release.yml`, initially pinned to
`codex-zsh-v0.1.0`.
- Download the standalone release’s generated `codex-zsh` DotSlash
manifest before assembling Linux and macOS Codex packages.
- Added a `--zsh-manifest` package-builder override so release packaging
fetches the matching target archive and verifies the size and SHA-256
digest recorded in that manifest.
- Removed the reusable zsh build job from regular Rust releases.
- Stopped copying zsh archives into each Rust release and stopped
regenerating a zsh DotSlash manifest there.

Windows packaging remains unchanged because the patched zsh resource is
only shipped for supported Unix targets.

## Testing

- Added package-helper coverage that supplies a standalone manifest
override and verifies the extracted zsh bytes.
- Ran the `scripts/codex_package` unit test suite.
- Validated `.github/scripts/build-codex-package-archive.sh` with `bash
-n`.
This commit is contained in:
Michael Bolin
2026-06-25 14:05:49 -07:00
committed by GitHub
Unverified
parent 891f1f4c85
commit e23e7cbe46
6 changed files with 111 additions and 22 deletions
@@ -9,6 +9,7 @@ Usage: build-codex-package-archive.sh \
--entrypoint-dir <dir> \
--archive-dir <dir> \
[--bwrap-bin <path>] \
[--zsh-manifest <path>] \
[--codex-command-runner-bin <path>] \
[--codex-windows-sandbox-setup-bin <path>] \
[--target-suffixed-entrypoint]
@@ -48,6 +49,10 @@ while [[ $# -gt 0 ]]; do
bwrap_bin_provided="true"
shift 2
;;
--zsh-manifest)
resource_args+=(--zsh-manifest "${2:?--zsh-manifest requires a value}")
shift 2
;;
--codex-command-runner-bin)
resource_args+=(
--codex-command-runner-bin
+26 -18
View File
@@ -14,6 +14,9 @@ on:
tags:
- "rust-v*.*.*"
env:
CODEX_ZSH_RELEASE_TAG: codex-zsh-v0.1.0
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
@@ -354,6 +357,15 @@ jobs:
cp target/${{ matrix.target }}/release/codex-${{ matrix.target }}.dmg "$dest/codex-${{ matrix.target }}.dmg"
fi
- name: Download packaged zsh manifest
if: ${{ runner.os != 'macOS' }}
shell: bash
run: |
set -euo pipefail
curl -fsSL \
"https://github.com/${GITHUB_REPOSITORY}/releases/download/${CODEX_ZSH_RELEASE_TAG}/codex-zsh" \
-o "${RUNNER_TEMP}/codex-zsh"
- name: Build Codex package archive
if: ${{ runner.os != 'macOS' }}
shell: bash
@@ -366,7 +378,8 @@ jobs:
--target "$TARGET" \
--bundle "$BUNDLE" \
--entrypoint-dir "target/${TARGET}/release" \
--archive-dir "dist/${TARGET}"
--archive-dir "dist/${TARGET}" \
--zsh-manifest "${RUNNER_TEMP}/codex-zsh"
- name: Build Python runtime wheel
if: ${{ matrix.bundle == 'primary' && runner.os != 'macOS' }}
@@ -697,6 +710,14 @@ jobs:
cp "target/${{ matrix.target }}/release/${binary}" "$dest/${binary}-${{ matrix.target }}"
done
- name: Download packaged zsh manifest
shell: bash
run: |
set -euo pipefail
curl -fsSL \
"https://github.com/${GITHUB_REPOSITORY}/releases/download/${CODEX_ZSH_RELEASE_TAG}/codex-zsh" \
-o "${RUNNER_TEMP}/codex-zsh"
- name: Build Codex package archive
shell: bash
env:
@@ -708,7 +729,8 @@ jobs:
--target "$TARGET" \
--bundle "$BUNDLE" \
--entrypoint-dir "target/${TARGET}/release" \
--archive-dir "dist/${TARGET}"
--archive-dir "dist/${TARGET}" \
--zsh-manifest "${RUNNER_TEMP}/codex-zsh"
- name: Build Python runtime wheel
if: ${{ matrix.bundle == 'primary' }}
@@ -1043,11 +1065,6 @@ jobs:
with:
publish: true
zsh-release-assets:
name: zsh release assets
needs: tag-check
uses: ./.github/workflows/rust-release-zsh.yml
release:
needs:
- tag-check
@@ -1055,7 +1072,6 @@ jobs:
- finalize-macos
- build-windows
- argument-comment-lint-release-assets
- zsh-release-assets
if: >-
${{
always() &&
@@ -1063,8 +1079,7 @@ jobs:
needs.build.result == 'success' &&
needs.finalize-macos.result == 'success' &&
needs.build-windows.result == 'success' &&
needs.argument-comment-lint-release-assets.result == 'success' &&
needs.zsh-release-assets.result == 'success'
needs.argument-comment-lint-release-assets.result == 'success'
}}
name: release
runs-on: ubuntu-latest
@@ -1113,7 +1128,7 @@ jobs:
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
pattern: "{*-symbols,argument-comment-lint-*,codex-zsh-*,python-runtime-wheel-*}"
pattern: "{*-symbols,argument-comment-lint-*,python-runtime-wheel-*}"
- name: List
run: ls -R dist/
@@ -1236,13 +1251,6 @@ jobs:
tag: ${{ github.ref_name }}
config: .github/dotslash-config.json
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ github.ref_name }}
config: .github/dotslash-zsh-config.json
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -1
View File
@@ -73,4 +73,6 @@ The patched zsh fork used by `shell_zsh_fork` is fetched from the DotSlash
manifest at `scripts/codex_package/codex-zsh` when the selected target has a
matching prebuilt artifact. Downloaded archives are cached under
`$TMPDIR/codex-package/<target>-zsh` and installed at
`codex-resources/zsh/bin/zsh`.
`codex-resources/zsh/bin/zsh`. Pass `--zsh-manifest` to use a different
DotSlash manifest, such as the manifest published with a standalone zsh
artifact release.
+9 -1
View File
@@ -90,6 +90,14 @@ def parse_args() -> argparse.Namespace:
"targets, bwrap is built with Cargo."
),
)
parser.add_argument(
"--zsh-manifest",
type=Path,
help=(
"Optional DotSlash manifest for the patched zsh fork instead of "
"scripts/codex_package/codex-zsh."
),
)
parser.add_argument(
"--codex-command-runner-bin",
type=Path,
@@ -160,7 +168,7 @@ def main() -> int:
inputs = PackageInputs(
entrypoint_bin=source_outputs.entrypoint_bin,
rg_bin=resolve_rg_bin(spec, args.rg_bin),
zsh_bin=resolve_zsh_bin(spec),
zsh_bin=resolve_zsh_bin(spec, args.zsh_manifest),
bwrap_bin=source_outputs.bwrap_bin,
codex_command_runner_bin=source_outputs.codex_command_runner_bin,
codex_windows_sandbox_setup_bin=source_outputs.codex_windows_sandbox_setup_bin,
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
import hashlib
import json
from pathlib import Path
import sys
import tarfile
import tempfile
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from codex_package.targets import TARGET_SPECS
from codex_package.zsh import resolve_zsh_bin
class ResolveZshBinTest(unittest.TestCase):
def test_uses_manifest_override(self) -> None:
with tempfile.TemporaryDirectory() as temp_dir:
root = Path(temp_dir)
archive = root / "codex-zsh.tar.gz"
source = root / "zsh"
source.write_bytes(b"standalone zsh")
with tarfile.open(archive, "w:gz") as tar:
tar.add(source, arcname="codex-zsh/bin/zsh")
manifest = root / "codex-zsh"
manifest.write_text(
json.dumps(
{
"platforms": {
"linux-x86_64": {
"size": archive.stat().st_size,
"hash": "sha256",
"digest": hashlib.sha256(
archive.read_bytes()
).hexdigest(),
"format": "tar.gz",
"path": "codex-zsh/bin/zsh",
"providers": [{"url": archive.as_uri()}],
}
}
}
),
encoding="utf-8",
)
with patch(
"codex_package.dotslash.default_cache_root",
return_value=root / "cache",
):
zsh_bin = resolve_zsh_bin(
TARGET_SPECS["x86_64-unknown-linux-musl"], manifest
)
self.assertIsNotNone(zsh_bin)
assert zsh_bin is not None
self.assertEqual(zsh_bin.read_bytes(), b"standalone zsh")
if __name__ == "__main__":
unittest.main()
+5 -2
View File
@@ -11,10 +11,13 @@ ZSH_MANIFEST = REPO_ROOT / "scripts" / "codex_package" / "codex-zsh"
ZSH_RESOURCE_PATH = Path("zsh") / "bin" / "zsh"
def resolve_zsh_bin(spec: TargetSpec) -> Path | None:
def resolve_zsh_bin(
spec: TargetSpec,
manifest_path: Path | None = None,
) -> Path | None:
return fetch_dotslash_executable(
spec,
manifest_path=ZSH_MANIFEST,
manifest_path=manifest_path or ZSH_MANIFEST,
artifact_label="codex-zsh",
cache_key=f"{spec.target}-zsh",
dest_name="zsh",