rust-release #81
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Release workflow for codex-rs. | |
| # To release, follow a workflow like: | |
| # ``` | |
| # git tag -a rust-v0.1.0 -m "Release 0.1.0" | |
| # git push origin rust-v0.1.0 | |
| # ``` | |
| name: rust-release | |
| on: | |
| push: | |
| tags: | |
| - "rust-v*.*.*" | |
| concurrency: | |
| group: ${{ github.workflow }} | |
| cancel-in-progress: true | |
| jobs: | |
| tag-check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0 | |
| - name: Validate tag matches Cargo.toml version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| echo "::group::Tag validation" | |
| # 1. Must be a tag and match the regex | |
| [[ "${GITHUB_REF_TYPE}" == "tag" ]] \ | |
| || { echo "❌ Not a tag push"; exit 1; } | |
| [[ "${GITHUB_REF_NAME}" =~ ^rust-v[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|cometix)(\.[0-9]+)?)?$ ]] \ | |
| || { echo "❌ Tag '${GITHUB_REF_NAME}' doesn't match expected format"; exit 1; } | |
| # 2. Extract versions | |
| tag_ver="${GITHUB_REF_NAME#rust-v}" | |
| cargo_ver="$(grep -m1 '^version' codex-rs/Cargo.toml \ | |
| | sed -E 's/version *= *"([^"]+)".*/\1/')" | |
| # 3. Compare | |
| [[ "${tag_ver}" == "${cargo_ver}" ]] \ | |
| || { echo "❌ Tag ${tag_ver} ≠ Cargo.toml ${cargo_ver}"; exit 1; } | |
| echo "✅ Tag and Cargo.toml agree (${tag_ver})" | |
| echo "::endgroup::" | |
| build: | |
| needs: tag-check | |
| name: Build - ${{ matrix.runner }} - ${{ matrix.target }} | |
| runs-on: ${{ matrix.runs_on || matrix.runner }} | |
| # Release builds can take a long time, so leave some headroom to avoid | |
| # having to restart the full workflow due to a timeout. | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| defaults: | |
| run: | |
| working-directory: codex-rs | |
| env: | |
| CARGO_PROFILE_RELEASE_LTO: ${{ (contains(github.ref_name, '-alpha') || contains(github.ref_name, '-cometix')) && 'thin' || 'fat' }} | |
| CARGO_PROFILE_RELEASE_OPT_LEVEL: ${{ contains(github.ref_name, '-cometix') && 's' || '3' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: macos-latest | |
| target: aarch64-apple-darwin | |
| - runner: macos-latest | |
| target: x86_64-apple-darwin | |
| - runner: ubuntu-24.04 | |
| target: x86_64-unknown-linux-musl | |
| - runner: ubuntu-24.04 | |
| target: x86_64-unknown-linux-gnu | |
| - runner: ubuntu-24.04-arm | |
| target: aarch64-unknown-linux-musl | |
| - runner: ubuntu-24.04-arm | |
| target: aarch64-unknown-linux-gnu | |
| - runner: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Print runner specs (Linux) | |
| if: ${{ runner.os == 'Linux' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cpu_model="$(lscpu | awk -F: '/Model name/ {gsub(/^[ \t]+/, "", $2); print $2; exit}')" | |
| total_ram="$(awk '/MemTotal/ {printf "%.1f GiB\n", $2 / 1024 / 1024}' /proc/meminfo)" | |
| echo "Runner: ${RUNNER_NAME:-unknown}" | |
| echo "OS: $(uname -a)" | |
| echo "CPU model: ${cpu_model}" | |
| echo "Logical CPUs: $(nproc)" | |
| echo "Total RAM: ${total_ram}" | |
| echo "Disk usage:" | |
| df -h . | |
| - name: Print runner specs (macOS) | |
| if: ${{ runner.os == 'macOS' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| total_ram="$(sysctl -n hw.memsize | awk '{printf "%.1f GiB\n", $1 / 1024 / 1024 / 1024}')" | |
| echo "Runner: ${RUNNER_NAME:-unknown}" | |
| echo "OS: $(sw_vers -productName) $(sw_vers -productVersion)" | |
| echo "Hardware model: $(sysctl -n hw.model)" | |
| echo "CPU architecture: $(uname -m)" | |
| echo "Logical CPUs: $(sysctl -n hw.logicalcpu)" | |
| echo "Physical CPUs: $(sysctl -n hw.physicalcpu)" | |
| echo "Total RAM: ${total_ram}" | |
| echo "Disk usage:" | |
| df -h . | |
| - name: Install Linux bwrap build dependencies | |
| if: ${{ runner.os == 'Linux' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update -y | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev | |
| - name: Install UBSan runtime (musl) | |
| if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if command -v apt-get >/dev/null 2>&1; then | |
| sudo apt-get update -y | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libubsan1 | |
| fi | |
| - uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0 | |
| with: | |
| targets: ${{ matrix.target }} | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}} | |
| name: Use hermetic Cargo home (musl) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo_home="${GITHUB_WORKSPACE}/.cargo-home" | |
| mkdir -p "${cargo_home}/bin" | |
| echo "CARGO_HOME=${cargo_home}" >> "$GITHUB_ENV" | |
| echo "${cargo_home}/bin" >> "$GITHUB_PATH" | |
| : > "${cargo_home}/config.toml" | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}} | |
| name: Install Zig | |
| uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 | |
| with: | |
| version: 0.14.0 | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}} | |
| name: Install musl build tools | |
| env: | |
| TARGET: ${{ matrix.target }} | |
| run: bash "${GITHUB_WORKSPACE}/.github/scripts/install-musl-build-tools.sh" | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}} | |
| name: Configure rustc UBSan wrapper (musl host) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ubsan="" | |
| if command -v ldconfig >/dev/null 2>&1; then | |
| ubsan="$(ldconfig -p | grep -m1 'libubsan\.so\.1' | sed -E 's/.*=> (.*)$/\1/')" | |
| fi | |
| wrapper_root="${RUNNER_TEMP:-/tmp}" | |
| wrapper="${wrapper_root}/rustc-ubsan-wrapper" | |
| cat > "${wrapper}" <<EOF | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| if [[ -n "${ubsan}" ]]; then | |
| export LD_PRELOAD="${ubsan}\${LD_PRELOAD:+:\${LD_PRELOAD}}" | |
| fi | |
| exec "\$1" "\${@:2}" | |
| EOF | |
| chmod +x "${wrapper}" | |
| echo "RUSTC_WRAPPER=${wrapper}" >> "$GITHUB_ENV" | |
| echo "RUSTC_WORKSPACE_WRAPPER=" >> "$GITHUB_ENV" | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}} | |
| name: Clear sanitizer flags (musl) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Avoid problematic aws-lc jitter entropy code path on musl builders. | |
| echo "AWS_LC_SYS_NO_JITTER_ENTROPY=1" >> "$GITHUB_ENV" | |
| target_no_jitter="AWS_LC_SYS_NO_JITTER_ENTROPY_${{ matrix.target }}" | |
| target_no_jitter="${target_no_jitter//-/_}" | |
| echo "${target_no_jitter}=1" >> "$GITHUB_ENV" | |
| # Clear global Rust flags so host/proc-macro builds don't pull in UBSan. | |
| echo "RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "CARGO_ENCODED_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "RUSTDOCFLAGS=" >> "$GITHUB_ENV" | |
| # Override any runner-level Cargo config rustflags as well. | |
| echo "CARGO_BUILD_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV" | |
| sanitize_flags() { | |
| local input="$1" | |
| input="${input//-fsanitize=undefined/}" | |
| input="${input//-fno-sanitize-recover=undefined/}" | |
| input="${input//-fno-sanitize-trap=undefined/}" | |
| echo "$input" | |
| } | |
| cflags="$(sanitize_flags "${CFLAGS-}")" | |
| cxxflags="$(sanitize_flags "${CXXFLAGS-}")" | |
| echo "CFLAGS=${cflags}" >> "$GITHUB_ENV" | |
| echo "CXXFLAGS=${cxxflags}" >> "$GITHUB_ENV" | |
| # Ensure the cross-compile target is present on the *active* toolchain. | |
| # dtolnay/rust-toolchain@1.93 installs with --profile minimal, but | |
| # cargo's first invocation may trigger rustup to sync a different | |
| # patch release (e.g. 1.93.1 vs 1.93.0) using the default profile, | |
| # which only includes the host rust-std and drops the cross target. | |
| - name: Ensure cross-compile target is present | |
| shell: bash | |
| run: rustup target add ${{ matrix.target }} | |
| - if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' }} | |
| name: Configure musl rusty_v8 artifact overrides and verify checksums | |
| uses: ./.github/actions/setup-rusty-v8-musl | |
| with: | |
| target: ${{ matrix.target }} | |
| # @cometix: build bwrap on all Linux targets (upstream gates on matrix.bundle which we don't use) | |
| - if: ${{ contains(matrix.target, 'linux') }} | |
| name: Build bwrap and export digest | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| target="${{ matrix.target }}" | |
| cargo build --target "$target" --release --timings --bin bwrap | |
| bwrap_path="target/${target}/release/bwrap" | |
| if [[ ! -f "$bwrap_path" ]]; then | |
| echo "bwrap binary ${bwrap_path} not found" | |
| exit 1 | |
| fi | |
| digest="$(sha256sum "$bwrap_path" | awk '{print $1}')" | |
| echo "CODEX_BWRAP_SHA256=${digest}" >> "$GITHUB_ENV" | |
| echo "Built bwrap ${bwrap_path} with sha256:${digest}" | |
| - name: Cargo build | |
| shell: bash | |
| run: | | |
| if [[ "${{ contains(matrix.target, 'windows') }}" == 'true' ]]; then | |
| cargo build --target ${{ matrix.target }} --release --timings --bin codex --bin codex-windows-sandbox-setup --bin codex-command-runner | |
| else | |
| cargo build --target ${{ matrix.target }} --release --timings --bin codex | |
| fi | |
| - name: Upload Cargo timings | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: cargo-timings-rust-release-${{ matrix.target }} | |
| path: codex-rs/target/**/cargo-timings/cargo-timing.html | |
| if-no-files-found: warn | |
| - name: Stage artifacts | |
| shell: bash | |
| run: | | |
| dest="dist/${{ matrix.target }}" | |
| mkdir -p "$dest" | |
| if [[ "${{ matrix.runner }}" == windows* ]]; then | |
| cp target/${{ matrix.target }}/release/codex.exe "$dest/codex-${{ matrix.target }}.exe" | |
| cp target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe "$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe" | |
| cp target/${{ matrix.target }}/release/codex-command-runner.exe "$dest/codex-command-runner-${{ matrix.target }}.exe" | |
| else | |
| cp target/${{ matrix.target }}/release/codex "$dest/codex-${{ matrix.target }}" | |
| # @cometix: include bwrap for Linux npm packages | |
| if [[ -f target/${{ matrix.target }}/release/bwrap ]]; then | |
| cp target/${{ matrix.target }}/release/bwrap "$dest/bwrap-${{ matrix.target }}" | |
| fi | |
| fi | |
| - name: Compress artifacts | |
| shell: bash | |
| run: | | |
| # Path that contains the uncompressed binaries for the current | |
| # ${{ matrix.target }} | |
| dest="dist/${{ matrix.target }}" | |
| repo_root=$PWD | |
| # We want to ship the raw Windows executables in the GitHub Release | |
| # in addition to the compressed archives. Keep the originals for | |
| # Windows targets; remove them elsewhere to limit the number of | |
| # artifacts that end up in the GitHub Release. | |
| keep_originals=false | |
| if [[ "${{ matrix.runner }}" == windows* ]]; then | |
| keep_originals=true | |
| fi | |
| # For compatibility with environments that lack the `zstd` tool we | |
| # additionally create a `.tar.gz` for all platforms and `.zip` for | |
| # Windows alongside every single binary that we publish. The end result is: | |
| # codex-<target>.zst (existing) | |
| # codex-<target>.tar.gz (new) | |
| # codex-<target>.zip (only for Windows) | |
| for f in "$dest"/*; do | |
| base="$(basename "$f")" | |
| # Skip files that are already archives. | |
| if [[ "$base" == *.tar.gz || "$base" == *.tar.zst || "$base" == *.zip || "$base" == *.dmg ]]; then | |
| continue | |
| fi | |
| # Don't try to compress signature bundles. | |
| if [[ "$base" == *.sigstore ]]; then | |
| continue | |
| fi | |
| # Create per-binary tar.gz | |
| tar -C "$dest" -czf "$dest/${base}.tar.gz" "$base" | |
| # Create zip archive for Windows binaries | |
| if [[ "${{ matrix.runner }}" == windows* ]]; then | |
| if [[ "$base" == "codex-${{ matrix.target }}.exe" ]]; then | |
| # Bundle the sandbox helper binaries into the main codex zip so | |
| # WinGet installs include the required helpers next to codex.exe. | |
| bundle_dir="$(mktemp -d)" | |
| runner_src="$dest/codex-command-runner-${{ matrix.target }}.exe" | |
| setup_src="$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe" | |
| if [[ -f "$runner_src" && -f "$setup_src" ]]; then | |
| cp "$dest/$base" "$bundle_dir/$base" | |
| cp "$runner_src" "$bundle_dir/codex-command-runner.exe" | |
| cp "$setup_src" "$bundle_dir/codex-windows-sandbox-setup.exe" | |
| (cd "$bundle_dir" && 7z a "$repo_root/$dest/${base}.zip" .) | |
| else | |
| echo "warning: missing sandbox binaries; falling back to single-binary zip" | |
| (cd "$dest" && 7z a "${base}.zip" "$base") | |
| fi | |
| rm -rf "$bundle_dir" | |
| else | |
| (cd "$dest" && 7z a "${base}.zip" "$base") | |
| fi | |
| fi | |
| # Create .zst; keep originals on Windows, remove elsewhere. | |
| zstd_args=(-T0 -19) | |
| if [[ "${keep_originals}" == false ]]; then | |
| zstd_args+=(--rm) | |
| fi | |
| zstd "${zstd_args[@]}" "$dest/$base" | |
| done | |
| - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: ${{ matrix.target }} | |
| # Upload the per-binary .zst files as well as the new .tar.gz | |
| # equivalents we generated in the previous step. | |
| path: | | |
| codex-rs/dist/${{ matrix.target }}/* | |
| release: | |
| needs: | |
| - build | |
| name: release | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| actions: read | |
| outputs: | |
| version: ${{ steps.release_name.outputs.name }} | |
| tag: ${{ github.ref_name }} | |
| should_publish_npm: ${{ steps.npm_publish_settings.outputs.should_publish }} | |
| npm_tag: ${{ steps.npm_publish_settings.outputs.npm_tag }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Generate release notes from tag commit message | |
| id: release_notes | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # On tag pushes, GITHUB_SHA may be a tag object for annotated tags; | |
| # peel it to the underlying commit. | |
| commit="$(git rev-parse "${GITHUB_SHA}^{commit}")" | |
| notes_path="${RUNNER_TEMP}/release-notes.md" | |
| # Use the commit message for the commit the tag points at (not the | |
| # annotated tag message). | |
| git log -1 --format=%B "${commit}" > "${notes_path}" | |
| # Ensure trailing newline so GitHub's markdown renderer doesn't | |
| # occasionally run the last line into subsequent content. | |
| echo >> "${notes_path}" | |
| echo "path=${notes_path}" >> "${GITHUB_OUTPUT}" | |
| - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: dist | |
| - name: List | |
| run: ls -R dist/ | |
| # This is a temporary fix: we should modify shell-tool-mcp.yml so these | |
| # files do not end up in dist/ in the first place. | |
| - name: Delete entries from dist/ that should not go in the release | |
| run: | | |
| rm -rf dist/shell-tool-mcp* | |
| rm -rf dist/windows-binaries* | |
| # cargo-timing.html appears under multiple target-specific directories. | |
| # If included in files: dist/**, release upload races on duplicate | |
| # asset names and can fail with 404s. | |
| find dist -type f -name 'cargo-timing.html' -delete | |
| find dist -type d -empty -delete | |
| ls -R dist/ | |
| - name: Add config schema release asset | |
| run: | | |
| cp codex-rs/core/config.schema.json dist/config-schema.json | |
| - name: Define release name | |
| id: release_name | |
| run: | | |
| # Extract the version from the tag name, which is in the format | |
| # "rust-v0.1.0". | |
| version="${GITHUB_REF_NAME#rust-v}" | |
| echo "name=${version}" >> $GITHUB_OUTPUT | |
| - name: Determine npm publish settings | |
| id: npm_publish_settings | |
| env: | |
| VERSION: ${{ steps.release_name.outputs.name }} | |
| run: | | |
| set -euo pipefail | |
| version="${VERSION}" | |
| if [[ "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| echo "npm_tag=" >> "$GITHUB_OUTPUT" | |
| elif [[ "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+-alpha\.[0-9]+$ ]]; then | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| echo "npm_tag=alpha" >> "$GITHUB_OUTPUT" | |
| elif [[ "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+-cometix(\.[0-9]+)?$ ]]; then | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| echo "npm_tag=latest" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "should_publish=false" >> "$GITHUB_OUTPUT" | |
| echo "npm_tag=" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5 | |
| with: | |
| run_install: false | |
| - name: Setup Node.js for npm packaging | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: latest | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # stage_npm_packages.py requires DotSlash when staging releases. | |
| - uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2 | |
| - name: Stage npm packages | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_VERSION: ${{ steps.release_name.outputs.name }} | |
| run: | | |
| ./scripts/stage_npm_packages.py \ | |
| --release-version "$RELEASE_VERSION" \ | |
| --package codex | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 | |
| with: | |
| name: ${{ steps.release_name.outputs.name }} | |
| tag_name: ${{ github.ref_name }} | |
| body_path: ${{ steps.release_notes.outputs.path }} | |
| files: dist/** | |
| # Mark as prerelease only when the version has a suffix after x.y.z | |
| # (e.g. -alpha, -beta). Otherwise publish a normal release. | |
| prerelease: ${{ contains(steps.release_name.outputs.name, '-') }} | |
| # @cometix: removed dotslash-publish-release and developers.openai.com deploy | |
| # (not applicable to fork) | |
| # Publish to npm using OIDC authentication. | |
| # July 31, 2025: https://github.blog/changelog/2025-07-31-npm-trusted-publishing-with-oidc-is-generally-available/ | |
| # npm docs: https://docs.npmjs.com/trusted-publishers | |
| publish-npm: | |
| # Publish to npm for stable releases and alpha pre-releases with numeric suffixes. | |
| if: ${{ needs.release.outputs.should_publish_npm == 'true' }} | |
| name: publish-npm | |
| needs: release | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write # Required for OIDC | |
| contents: read | |
| steps: | |
| - name: Setup Node.js | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: latest | |
| registry-url: "https://registry.npmjs.org" | |
| scope: "@cometix" | |
| - name: Download npm tarballs from release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_TAG: ${{ needs.release.outputs.tag }} | |
| RELEASE_VERSION: ${{ needs.release.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| version="$RELEASE_VERSION" | |
| tag="$RELEASE_TAG" | |
| mkdir -p dist/npm | |
| # @cometix: download all npm tarballs (main + platform packages) | |
| gh release download "$tag" \ | |
| --repo "${GITHUB_REPOSITORY}" \ | |
| --pattern "codex-npm-*.tgz" \ | |
| --dir dist/npm | |
| ls -la dist/npm/ | |
| - name: Publish platform packages to npm | |
| env: | |
| VERSION: ${{ needs.release.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| # @cometix: publish platform-specific tarballs first (they use | |
| # dist-tag matching the platform, e.g. linux-x64, darwin-arm64). | |
| for platform_tgz in dist/npm/codex-npm-*-"${VERSION}".tgz; do | |
| [ -f "$platform_tgz" ] || continue | |
| # Extract platform tag from filename: codex-npm-{platform}-{version}.tgz | |
| basename="$(basename "$platform_tgz" .tgz)" | |
| platform_tag="${basename#codex-npm-}" | |
| platform_tag="${platform_tag%-"${VERSION}"}" | |
| echo "Publishing platform package: $platform_tgz (tag: $platform_tag)" | |
| npm publish "$platform_tgz" --tag "$platform_tag" | |
| done | |
| - name: Publish main package to npm | |
| env: | |
| VERSION: ${{ needs.release.outputs.version }} | |
| NPM_TAG: ${{ needs.release.outputs.npm_tag }} | |
| run: | | |
| set -euo pipefail | |
| tag_args=() | |
| if [[ -n "${NPM_TAG}" ]]; then | |
| tag_args+=(--tag "${NPM_TAG}") | |
| fi | |
| # @cometix: publish main package last (it has optionalDependencies | |
| # on platform packages, so those must exist first). | |
| npm publish "${GITHUB_WORKSPACE}/dist/npm/codex-npm-${VERSION}.tgz" "${tag_args[@]}" |