mirror of
https://github.com/openai/codex.git
synced 2026-09-17 12:23:33 +00:00
## What changed - When `CODEX_PROVISIONED_MACOS_CANDIDATE` is `true`, require the provisioned macOS job to succeed and upload its verified packages as release assets. Allow releases to proceed when the job is disabled and skipped. - Include provisioned archives in `codex-package_SHA256SUMS` and remove per-architecture `SHA256SUMS` files before upload. - Publish a `codex-provisioned` DotSlash manifest for macOS ARM64 and x86_64 packages, pointing to `bin/codex`. GitOrigin-RevId: 7e36df484a3b7da6b66180fa31418a6958d1fe77
215 lines
10 KiB
YAML
215 lines
10 KiB
YAML
# Verified side packages, published by rust-release.yml when enabled.
|
|
# The legacy CLI, npm, installer and DMG packages are unchanged.
|
|
# Required secrets in the codesigning environment:
|
|
# - CODEX_CLI_PROVISIONING_PROFILE_BASE64: profile approved for public distribution.
|
|
# - CODEX_CLI_PROVISIONING_PROFILE_SHA256: reviewed lowercase SHA-256 of that profile.
|
|
# - CODEX_CLI_PROVISIONING_TEAM_ID: expected ten-character Apple Team ID.
|
|
# - AKV_CODESIGN_CERTIFICATE_SHA256: required signing certificate pin.
|
|
# Set repository variable CODEX_PROVISIONED_MACOS_CANDIDATE to true to enable
|
|
# candidates on normal tag releases; unset it or set it to false to disable them.
|
|
name: Provisioned macOS CLI candidate
|
|
|
|
on:
|
|
workflow_call:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
CODEX_REPO_ROOT: ${{ github.workspace }}
|
|
|
|
jobs:
|
|
sign:
|
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/rust-v') && vars.CODEX_PROVISIONED_MACOS_CANDIDATE == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 45
|
|
environment:
|
|
name: codesigning
|
|
deployment: false
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
target: [aarch64-apple-darwin, x86_64-apple-darwin]
|
|
env:
|
|
TARGET: ${{ matrix.target }}
|
|
PROVISIONED_MACOS: "true"
|
|
PROFILE_SHA256: ${{ secrets.CODEX_CLI_PROVISIONING_PROFILE_SHA256 }}
|
|
CERTIFICATE_SHA256: ${{ secrets.AKV_CODESIGN_CERTIFICATE_SHA256 }}
|
|
TEAM_ID: ${{ secrets.CODEX_CLI_PROVISIONING_TEAM_ID }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: "3.12"
|
|
- name: Validate the independently approved public-distribution profile
|
|
env:
|
|
PROFILE_BASE64: ${{ secrets.CODEX_CLI_PROVISIONING_PROFILE_BASE64 }}
|
|
run: |
|
|
python3 - <<'PY'
|
|
import base64
|
|
import os
|
|
from pathlib import Path
|
|
profile = Path(os.environ["RUNNER_TEMP"]) / "codex-cli.provisionprofile"
|
|
profile.write_bytes(base64.b64decode("".join(os.environ["PROFILE_BASE64"].split()), validate=True))
|
|
PY
|
|
python3 .github/scripts/macos-signing/provisioned_macos_cli_package.py validate-profile \
|
|
--profile "$RUNNER_TEMP/codex-cli.provisionprofile" --profile-sha256 "$PROFILE_SHA256" \
|
|
--certificate-sha256 "$CERTIFICATE_SHA256" --team-id "$TEAM_ID"
|
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: ${{ matrix.target }}
|
|
path: standard
|
|
- name: Extract the verified package from this tag-release run
|
|
run: |
|
|
python3 - <<'PY'
|
|
import json
|
|
import os
|
|
import tarfile
|
|
from pathlib import Path
|
|
with tarfile.open(f"standard/codex-package-{os.environ['TARGET']}.tar.gz") as archive:
|
|
archive.extractall("package", filter="data")
|
|
metadata = json.loads(Path("package/codex-package.json").read_text())
|
|
if metadata["target"] != os.environ["TARGET"]:
|
|
raise ValueError("Package target does not match this release job")
|
|
PY
|
|
- name: Set up the existing AKV signer
|
|
uses: ./.github/actions/setup-akv-pkcs11-codesigning
|
|
with:
|
|
rcodesign-blob-uri: ${{ secrets.AKV_CODESIGN_RCODESIGN_BLOB_URI }}
|
|
rcodesign-sha256: ${{ secrets.AKV_CODESIGN_RCODESIGN_SHA256 }}
|
|
akv-pkcs11-library-blob-uri: ${{ secrets.AKV_CODESIGN_PKCS11_LIBRARY_BLOB_URI }}
|
|
akv-pkcs11-library-sha256: ${{ secrets.AKV_CODESIGN_PKCS11_LIBRARY_SHA256 }}
|
|
azure-client-id: ${{ secrets.AKV_CODESIGN_AZURE_CLIENT_ID }}
|
|
azure-tenant-id: ${{ secrets.AKV_CODESIGN_TENANT }}
|
|
azure-subscription-id: ${{ secrets.AKV_CODESIGN_SUBSCRIPTION }}
|
|
key-vault-name: ${{ secrets.AKV_CODESIGN_KEY_VAULT_NAME }}
|
|
key-name: ${{ secrets.AKV_CODESIGN_KEY_NAME }}
|
|
key-version: ${{ secrets.AKV_CODESIGN_KEY_VERSION || '' }}
|
|
certificate-sha256: ${{ secrets.AKV_CODESIGN_CERTIFICATE_SHA256 }}
|
|
- name: Sign and notarize the provisioned bundle
|
|
env:
|
|
APPLE_NOTARIZATION_AKV_KEY_NAME: ${{ secrets.AKV_NOTARIZATION_KEY_NAME }}
|
|
APPLE_NOTARIZATION_AKV_KEY_VERSION: ${{ secrets.AKV_NOTARIZATION_KEY_VERSION }}
|
|
run: |
|
|
python3 .github/scripts/macos-signing/sign_macos_cli_package.py sign package \
|
|
--profile "$RUNNER_TEMP/codex-cli.provisionprofile" --profile-sha256 "$PROFILE_SHA256" \
|
|
--certificate-sha256 "$CERTIFICATE_SHA256" --team-id "$TEAM_ID"
|
|
mkdir signed
|
|
tar -czf "signed/codex-provisioned-package-$TARGET.tar.gz" -C package \
|
|
bin codex-resources codex-path codex-package.json CodexCLI.app
|
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: provisioned-macos-signed-candidate-${{ matrix.target }}
|
|
path: signed/*.tar.gz
|
|
if-no-files-found: error
|
|
- name: Retain signing reports
|
|
if: always()
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: provisioned-macos-signing-reports-${{ matrix.target }}
|
|
path: signing-verification/
|
|
if-no-files-found: warn
|
|
|
|
verify:
|
|
needs: sign
|
|
runs-on: macos-15-xlarge
|
|
timeout-minutes: 30
|
|
environment:
|
|
name: codesigning
|
|
deployment: false
|
|
# Read independent profile/certificate expectations without a signing token.
|
|
permissions:
|
|
contents: read
|
|
id-token: none
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
target: [aarch64-apple-darwin, x86_64-apple-darwin]
|
|
env:
|
|
TARGET: ${{ matrix.target }}
|
|
PROVISIONED_MACOS: "true"
|
|
PROFILE_SHA256: ${{ secrets.CODEX_CLI_PROVISIONING_PROFILE_SHA256 }}
|
|
CERTIFICATE_SHA256: ${{ secrets.AKV_CODESIGN_CERTIFICATE_SHA256 }}
|
|
TEAM_ID: ${{ secrets.CODEX_CLI_PROVISIONING_TEAM_ID }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: "3.12"
|
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: provisioned-macos-signed-candidate-${{ matrix.target }}
|
|
path: signed
|
|
- name: Extract candidate and load independent verification profile
|
|
env:
|
|
PROFILE_BASE64: ${{ secrets.CODEX_CLI_PROVISIONING_PROFILE_BASE64 }}
|
|
run: |
|
|
python3 - <<'PY'
|
|
import base64
|
|
import os
|
|
import tarfile
|
|
from pathlib import Path
|
|
profile = Path(os.environ["RUNNER_TEMP"]) / "codex-cli.provisionprofile"
|
|
profile.write_bytes(base64.b64decode("".join(os.environ["PROFILE_BASE64"].split()), validate=True))
|
|
with tarfile.open(f"signed/codex-provisioned-package-{os.environ['TARGET']}.tar.gz") as archive:
|
|
archive.extractall("package", filter="data")
|
|
PY
|
|
- name: Verify signatures, profile, architecture, stapling and Gatekeeper
|
|
run: |
|
|
profile_args=(--profile "$RUNNER_TEMP/codex-cli.provisionprofile"
|
|
--profile-sha256 "$PROFILE_SHA256" --certificate-sha256 "$CERTIFICATE_SHA256"
|
|
--team-id "$TEAM_ID")
|
|
python3 .github/scripts/macos-signing/sign_macos_cli_package.py verify package "${profile_args[@]}"
|
|
xcrun stapler staple package/CodexCLI.app
|
|
xcrun stapler validate package/CodexCLI.app
|
|
spctl --assess --type execute --verbose=4 package/CodexCLI.app
|
|
python3 .github/scripts/macos-signing/sign_macos_cli_package.py verify package "${profile_args[@]}"
|
|
mkdir verified
|
|
tar -czf "verified/codex-provisioned-package-$TARGET.tar.gz" -C package \
|
|
bin codex-resources codex-path codex-package.json CodexCLI.app
|
|
(cd verified && shasum -a 256 "codex-provisioned-package-$TARGET.tar.gz" > SHA256SUMS)
|
|
- uses: ./.github/actions/setup-ci
|
|
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
with:
|
|
version: "0.11.3"
|
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: ${{ matrix.target }}-app-server
|
|
path: app-server
|
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: ${{ matrix.target }}-symbols
|
|
path: symbols
|
|
- name: Test the exact verified package, including sandboxed code mode
|
|
working-directory: scripts/codex_package/smoke_tests
|
|
env:
|
|
PYTHONPATH: ${{ github.workspace }}/sdk/python/src:${{ github.workspace }}/sdk/python/tests
|
|
run: |
|
|
# This repackaging does not change debug code. The normal release's
|
|
# primary symbols omit app-server symbols, so skip symbol-only tests.
|
|
uv run --frozen pytest -v --compression gzip --package-target "$TARGET" \
|
|
--cli-archive "$CODEX_REPO_ROOT/verified/codex-provisioned-package-$TARGET.tar.gz" \
|
|
--app-server-archive "$CODEX_REPO_ROOT/app-server/codex-app-server-package-$TARGET.tar.gz" \
|
|
--symbols-archive "$CODEX_REPO_ROOT/symbols/codex-symbols-$TARGET.tar.gz" \
|
|
test_codex_package.py -k 'not debug_symbols'
|
|
- name: Retain verified candidate only after package tests pass
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: provisioned-macos-verified-candidate-${{ matrix.target }}
|
|
path: verified/*
|
|
if-no-files-found: error
|
|
- name: Retain verification reports
|
|
if: always()
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: provisioned-macos-verification-reports-${{ matrix.target }}
|
|
path: signing-verification/
|
|
if-no-files-found: warn
|