Skip to content

fix(ci): remove cached v8 gn output before rebuild (#63) #8

fix(ci): remove cached v8 gn output before rebuild (#63)

fix(ci): remove cached v8 gn output before rebuild (#63) #8

name: Codex++ release
on:
push:
branches:
- main
tags:
- "codex-plus-plus-v*"
paths:
- ".github/workflows/codex-plus-plus-release.yml"
- "codex-rs/**/Cargo.toml"
- "codex-rs/Cargo.lock"
- "codex-rs/rust-toolchain.toml"
- "scripts/build_codex_package.py"
- "scripts/build_codex_plus_plus.py"
- "scripts/codex_package/**"
permissions: {}
concurrency:
group: codex-plus-plus-release-${{ github.ref }}
cancel-in-progress: ${{ github.ref == 'refs/heads/main' }}
jobs:
prepare:
if: startsWith(github.ref, 'refs/tags/codex-plus-plus-v')
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Validate release tag
id: version
shell: bash
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#codex-plus-plus-v}"
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+-fork\.[0-9]+$ ]] || {
echo "Invalid Codex++ release tag: ${GITHUB_REF_NAME}"
exit 1
}
base_version="${version%%-fork.*}"
workspace_version="$(sed -n '/^\[workspace.package\]/,/^\[/s/^version = "\([^"]*\)"/\1/p' codex-rs/Cargo.toml | head -1)"
[[ "$base_version" == "$workspace_version" ]] || {
echo "Tag base ${base_version} does not match workspace ${workspace_version}"
exit 1
}
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Validate release helpers
run: |
python scripts/codex_package/test_build_codex_plus_plus.py
python scripts/codex_package/tests/test_codex_plus_plus_release.py
python -m py_compile \
scripts/build_codex_plus_plus.py \
scripts/codex_package/codex_plus_plus/release.py
warm-cache:
if: github.ref == 'refs/heads/main'
strategy:
fail-fast: false
matrix:
include:
- runner: windows-latest
target: x86_64-pc-windows-msvc
- runner: macos-15
target: aarch64-apple-darwin
- runner: ubuntu-24.04
target: x86_64-unknown-linux-musl
runs-on: ${{ matrix.runner }}
permissions:
contents: read
env:
AWS_LC_SYS_NO_JITTER_ENTROPY: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}
AWS_LC_SYS_NO_JITTER_ENTROPY_x86_64_unknown_linux_musl: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
LIBSQLITE3_FLAGS: ${{ matrix.target == 'x86_64-pc-windows-msvc' && 'SQLITE_DISABLE_INTRINSIC' || '' }}
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0
with:
targets: ${{ matrix.target }}
- name: Restore and save Codex++ dependency cache
continue-on-error: true
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: codex-rs -> target
shared-key: codex-plus-plus-${{ env.TARGET }}-release
env-vars: AWS_LC_SYS_NO_JITTER_ENTROPY LIBSQLITE3_FLAGS TARGET
cache-bin: false
cache-workspace-crates: false
- name: Regenerate v8 after cache restore
working-directory: codex-rs
shell: bash
run: |
cargo clean -p v8 --target "$TARGET" --profile release
rm -rf "target/${TARGET}/release/gn_out"
- name: Install Zig
if: runner.os == 'Linux'
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: 0.14.0
use-cache: false
- name: Install musl build tools
if: runner.os == 'Linux'
shell: bash
run: bash .github/scripts/install-musl-build-tools.sh
- name: Build bundled bwrap
if: runner.os == 'Linux'
working-directory: codex-rs
shell: bash
run: |
set -euo pipefail
cargo build --target "$TARGET" --profile release --bin bwrap
bwrap="target/${TARGET}/release/bwrap"
digest="$(sha256sum "$bwrap" | awk '{print $1}')"
echo "BWRAP=${GITHUB_WORKSPACE}/codex-rs/${bwrap}" >> "$GITHUB_ENV"
echo "CODEX_BWRAP_SHA256=${digest}" >> "$GITHUB_ENV"
- name: Warm full-release dependencies
shell: bash
run: |
package_args=(
--cargo-profile release
--target "$TARGET"
--package-dir "dist/cache-package-${TARGET}"
--force
)
if [[ -n "${BWRAP:-}" ]]; then
package_args+=(--bwrap-bin "$BWRAP")
fi
python scripts/build_codex_plus_plus.py --suffix cache -- "${package_args[@]}"
build:
needs: prepare
strategy:
fail-fast: false
matrix:
include:
- runner: windows-latest
target: x86_64-pc-windows-msvc
archive_suffix: zip
executable: bin/codex.exe
- runner: macos-15
target: aarch64-apple-darwin
archive_suffix: tar.gz
executable: bin/codex
- runner: ubuntu-24.04
target: x86_64-unknown-linux-musl
archive_suffix: tar.gz
executable: bin/codex
runs-on: ${{ matrix.runner }}
permissions:
contents: read
env:
AWS_LC_SYS_NO_JITTER_ENTROPY: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}
AWS_LC_SYS_NO_JITTER_ENTROPY_x86_64_unknown_linux_musl: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
TARGET: ${{ matrix.target }}
VERSION: ${{ needs.prepare.outputs.version }}
ARCHIVE_SUFFIX: ${{ matrix.archive_suffix }}
LIBSQLITE3_FLAGS: ${{ matrix.target == 'x86_64-pc-windows-msvc' && 'SQLITE_DISABLE_INTRINSIC' || '' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0
with:
targets: ${{ matrix.target }}
- name: Restore Codex++ dependency cache
continue-on-error: true
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: codex-rs -> target
shared-key: codex-plus-plus-${{ env.TARGET }}-release
env-vars: AWS_LC_SYS_NO_JITTER_ENTROPY LIBSQLITE3_FLAGS TARGET
cache-bin: false
cache-workspace-crates: false
save-if: false
- name: Regenerate v8 after cache restore
working-directory: codex-rs
shell: bash
run: |
cargo clean -p v8 --target "$TARGET" --profile release
rm -rf "target/${TARGET}/release/gn_out"
- name: Install Zig
if: runner.os == 'Linux'
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: 0.14.0
use-cache: false
- name: Install musl build tools
if: runner.os == 'Linux'
shell: bash
run: bash .github/scripts/install-musl-build-tools.sh
- name: Build bundled bwrap
if: runner.os == 'Linux'
working-directory: codex-rs
shell: bash
run: |
set -euo pipefail
cargo build --target "$TARGET" --profile release --bin bwrap
bwrap="target/${TARGET}/release/bwrap"
digest="$(sha256sum "$bwrap" | awk '{print $1}')"
echo "BWRAP=${GITHUB_WORKSPACE}/codex-rs/${bwrap}" >> "$GITHUB_ENV"
echo "CODEX_BWRAP_SHA256=${digest}" >> "$GITHUB_ENV"
- name: Build package archive
shell: bash
run: |
set -euo pipefail
archive="dist/codex-plus-plus-${VERSION}-${TARGET}.${ARCHIVE_SUFFIX}"
package_args=(
--target "$TARGET"
--package-dir "dist/package-${TARGET}"
--archive-output "$archive"
--force
)
if [[ -n "${BWRAP:-}" ]]; then
package_args+=(--bwrap-bin "$BWRAP")
fi
python scripts/build_codex_plus_plus.py \
--fork-version "$VERSION" \
-- \
--cargo-profile release \
"${package_args[@]}"
- name: Smoke package
shell: bash
env:
EXECUTABLE: ${{ matrix.executable }}
run: |
set -euo pipefail
executable="dist/package-${TARGET}/${EXECUTABLE}"
[[ "$("$executable" --version)" == "codex-cli ${VERSION}" ]]
- name: Stage release assets
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: codex-plus-plus-native-${{ matrix.target }}
path: dist/codex-plus-plus-${{ env.VERSION }}-${{ matrix.target }}.${{ matrix.archive_suffix }}
if-no-files-found: error
compression-level: 0
retention-days: 1
stage-npm:
needs:
- prepare
- build
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
package-manager-cache: false
- name: Pin npm
run: npm install --global npm@12.0.0
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: codex-plus-plus-native-*
path: dist/archives
merge-multiple: true
- name: Stage exact npm payloads
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |
python scripts/codex_package/codex_plus_plus/release.py hydrate \
--version "$VERSION" --archives-dir dist/archives --vendor-dir dist/vendor
python scripts/stage_npm_packages.py --release-version "$VERSION" \
--package codex-plus-plus --vendor-src dist/vendor --output-dir dist/npm
python scripts/codex_package/codex_plus_plus/release.py verify \
--version "$VERSION" --archives-dir dist/archives --npm-dir dist/npm
cd dist/npm
for tarball in *.tgz; do sha256sum "$tarball" > "$tarball.sha256"; done
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: codex-plus-plus-npm-${{ needs.prepare.outputs.version }}
path: dist/npm/*
if-no-files-found: error
compression-level: 0
retention-days: 1
publish-npm:
needs:
- prepare
- stage-npm
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
registry-url: https://registry.npmjs.org
package-manager-cache: false
- name: Pin npm
run: npm install --global npm@12.0.0
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: codex-plus-plus-npm-${{ needs.prepare.outputs.version }}
path: dist/npm
- name: Publish npm packages serially
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |
(cd dist/npm && sha256sum --check *.sha256)
python scripts/codex_package/codex_plus_plus/release.py publish \
--version "$VERSION" --npm-dir dist/npm --dry-run
python scripts/codex_package/codex_plus_plus/release.py publish \
--version "$VERSION" --npm-dir dist/npm
publish-github:
needs:
- prepare
- build
- stage-npm
- publish-npm
runs-on: ubuntu-24.04
permissions:
actions: write
contents: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: codex-plus-plus-native-*
path: dist/archives
merge-multiple: true
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: codex-plus-plus-npm-${{ needs.prepare.outputs.version }}
path: dist/npm
- name: Publish GitHub release
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.prepare.outputs.version }}
run: |
set -euo pipefail
mkdir dist/release
cp dist/archives/* dist/npm/* scripts/install/install-codex-plus-plus*.sh \
scripts/install/install-codex-plus-plus*.ps1 dist/release/
cd dist/release
for asset in codex-plus-plus-*.tar.gz codex-plus-plus-*.zip install-*.sh install-*.ps1; do
sha256sum "$asset" > "$asset.sha256"
done
cd ../..
notes="${RUNNER_TEMP}/release-notes.md"
cat > "$notes" <<EOF
Codex++ ${VERSION}, based on upstream Codex ${VERSION%%-fork.*}.
npm package: @jjliebig/codex-plus-plus
Standalone unsigned builds: Windows x64, macOS ARM64, and Linux x64.
EOF
assets=(dist/release/*)
if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
[[ "$(gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --json isDraft --jq .isDraft)" == "true" ]] || {
echo "Release ${GITHUB_REF_NAME} is already published"
exit 1
}
gh release upload "$GITHUB_REF_NAME" "${assets[@]}" \
--repo "$GITHUB_REPOSITORY" --clobber
else
gh release create "$GITHUB_REF_NAME" "${assets[@]}" \
--repo "$GITHUB_REPOSITORY" \
--verify-tag \
--draft \
--title "Codex++ ${VERSION}" \
--notes-file "$notes"
fi
gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --draft=false --latest
- name: Delete intermediate artifacts
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api --paginate \
"repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/artifacts?per_page=100" \
--jq '.artifacts[] | select(.name | startswith("codex-plus-plus-native-") or startswith("codex-plus-plus-npm-")) | .id' |
while read -r artifact_id; do
gh api --method DELETE \
"repos/${GITHUB_REPOSITORY}/actions/artifacts/${artifact_id}"
done