Initial commit: AirCoding V1.0.0 Alpha architecture baseline
Complete architecture document set with multi-model review remediation: - Frozen interface contracts, runtime semantics, DB schemas - Event/tool/error/provider registries - Scheduler and main agent state machines - C4 module/code views, solution architecture, baseline V1 - Multi-model review reports and joint assessment - Phase-gate remediation complete (P0/P1/P2/UX resolved) - Implementation plan with T-000A through T-045 - Reference folders kept as placeholders only
This commit is contained in:
6
reference/openai-codex/.github/CODEOWNERS
vendored
Normal file
6
reference/openai-codex/.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Core crate ownership.
|
||||
/codex-rs/core/ @openai/codex-core-agent-team
|
||||
/codex-rs/ext/extension-api/ @openai/codex-core-agent-team
|
||||
|
||||
# Keep ownership changes reviewed by the same team.
|
||||
/.github/CODEOWNERS @openai/codex-core-agent-team
|
||||
54
reference/openai-codex/.github/ISSUE_TEMPLATE/1-codex-app.yml
vendored
Normal file
54
reference/openai-codex/.github/ISSUE_TEMPLATE/1-codex-app.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: 🖥️ Codex App Bug
|
||||
description: Report an issue with the Codex App
|
||||
labels:
|
||||
- app
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before submitting a new issue, please search for existing issues to see if your issue has already been reported.
|
||||
If it has, please add a 👍 reaction (no need to leave a comment) to the existing issue instead of creating a new one.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: What version of the Codex App are you using (From “About Codex” dialog)?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plan
|
||||
attributes:
|
||||
label: What subscription do you have?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: What platform is your computer?
|
||||
description: |
|
||||
For macOS and Linux: copy the output of `uname -mprs`
|
||||
For Windows: copy the output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in the PowerShell console
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: What issue are you seeing?
|
||||
description: Please include the full error messages and prompts with PII redacted. If possible, please provide text instead of a screenshot.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What steps can reproduce the bug?
|
||||
description: Explain the bug and provide a code snippet that can reproduce it. Please include session id, token limit usage, context window usage if applicable.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What is the expected behavior?
|
||||
description: If possible, please provide text instead of a screenshot.
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else you think we should know?
|
||||
61
reference/openai-codex/.github/ISSUE_TEMPLATE/2-extension.yml
vendored
Normal file
61
reference/openai-codex/.github/ISSUE_TEMPLATE/2-extension.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: 🧑💻 IDE Extension Bug
|
||||
description: Report an issue with the IDE extension
|
||||
labels:
|
||||
- extension
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before submitting a new issue, please search for existing issues to see if your issue has already been reported.
|
||||
If it has, please add a 👍 reaction (no need to leave a comment) to the existing issue instead of creating a new one.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: What version of the IDE extension are you using?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plan
|
||||
attributes:
|
||||
label: What subscription do you have?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: ide
|
||||
attributes:
|
||||
label: Which IDE are you using?
|
||||
description: Like `VS Code`, `Cursor`, `Windsurf`, etc.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: What platform is your computer?
|
||||
description: |
|
||||
For macOS and Linux: copy the output of `uname -mprs`
|
||||
For Windows: copy the output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in the PowerShell console
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: What issue are you seeing?
|
||||
description: Please include the full error messages and prompts with PII redacted. If possible, please provide text instead of a screenshot.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What steps can reproduce the bug?
|
||||
description: Explain the bug and provide a code snippet that can reproduce it.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What is the expected behavior?
|
||||
description: If possible, please provide text instead of a screenshot.
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else you think we should know?
|
||||
81
reference/openai-codex/.github/ISSUE_TEMPLATE/3-cli.yml
vendored
Normal file
81
reference/openai-codex/.github/ISSUE_TEMPLATE/3-cli.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
name: 💻 CLI Bug
|
||||
description: Report an issue in the Codex CLI
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before submitting a new issue, please search for existing issues to see if your issue has already been reported.
|
||||
If it has, please add a 👍 reaction (no need to leave a comment) to the existing issue instead of creating a new one.
|
||||
|
||||
Make sure you are running the [latest](https://npmjs.com/package/@openai/codex) version of Codex CLI. The bug you are experiencing may already have been fixed.
|
||||
|
||||
If your version supports it, please run `codex doctor --json` and paste the output in the "Codex doctor report" field below. This helps us diagnose install, config, auth, terminal, MCP, network, and local state issues.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: What version of Codex CLI is running?
|
||||
description: use `codex --version`
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plan
|
||||
attributes:
|
||||
label: What subscription do you have?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: model
|
||||
attributes:
|
||||
label: Which model were you using?
|
||||
description: Like `gpt-5.2`, `gpt-5.2-codex`, etc.
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: What platform is your computer?
|
||||
description: |
|
||||
For macOS and Linux: copy the output of `uname -mprs`
|
||||
For Windows: copy the output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in the PowerShell console
|
||||
- type: input
|
||||
id: terminal
|
||||
attributes:
|
||||
label: What terminal emulator and version are you using (if applicable)?
|
||||
description: |
|
||||
Also note any multiplexer in use (screen / tmux / zellij).
|
||||
E.g., VS Code, Terminal.app, iTerm2, Ghostty, Windows Terminal (WSL / PowerShell)
|
||||
- type: textarea
|
||||
id: doctor
|
||||
attributes:
|
||||
label: Codex doctor report
|
||||
description: |
|
||||
If available, run `codex doctor --json` and paste the full output here.
|
||||
|
||||
The report is designed to redact secrets, but please review it before submitting.
|
||||
If your Codex version does not support `doctor`, write `not available`.
|
||||
render: json
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: What issue are you seeing?
|
||||
description: Please include the full error messages and prompts with PII redacted. If possible, please provide text instead of a screenshot.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What steps can reproduce the bug?
|
||||
description: Explain the bug and provide a code snippet that can reproduce it. Please include thread id if applicable.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What is the expected behavior?
|
||||
description: If possible, please provide text instead of a screenshot.
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else you think we should know?
|
||||
37
reference/openai-codex/.github/ISSUE_TEMPLATE/4-bug-report.yml
vendored
Normal file
37
reference/openai-codex/.github/ISSUE_TEMPLATE/4-bug-report.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: 🪲 Other Bug
|
||||
description: Report an issue in Codex Web, integrations, or other Codex components
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before submitting a new issue, please search for existing issues to see if your issue has already been reported.
|
||||
If it has, please add a 👍 reaction (no need to leave a comment) to the existing issue instead of creating a new one.
|
||||
|
||||
If you need help or support using Codex and are not reporting a bug, please post on [codex/discussions](https://github.com/openai/codex/discussions), where you can ask questions or engage with others on ideas for how to improve codex.
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: What issue are you seeing?
|
||||
description: Please include the full error messages and prompts with PII redacted. If possible, please provide text instead of a screenshot.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What steps can reproduce the bug?
|
||||
description: Explain the bug and provide a code snippet that can reproduce it.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What is the expected behavior?
|
||||
description: If possible, please provide text instead of a screenshot.
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else you think we should know?
|
||||
32
reference/openai-codex/.github/ISSUE_TEMPLATE/5-feature-request.yml
vendored
Normal file
32
reference/openai-codex/.github/ISSUE_TEMPLATE/5-feature-request.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: 🎁 Feature Request
|
||||
description: Propose a new feature for Codex
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Is Codex missing a feature that you'd like to see? Feel free to propose it here.
|
||||
|
||||
Before you submit a feature:
|
||||
1. Search existing issues for similar features. If you find one, 👍 it rather than opening a new one.
|
||||
2. The Codex team will try to balance the varying needs of the community when prioritizing or rejecting new features. Not all features will be accepted. See [Contributing](https://github.com/openai/codex/blob/main/docs/contributing.md) for more details.
|
||||
|
||||
- type: input
|
||||
id: variant
|
||||
attributes:
|
||||
label: What variant of Codex are you using?
|
||||
description: (e.g., App, IDE Extension, CLI, Web)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: feature
|
||||
attributes:
|
||||
label: What feature would you like to see?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else you think we should know?
|
||||
27
reference/openai-codex/.github/ISSUE_TEMPLATE/6-docs-issue.yml
vendored
Normal file
27
reference/openai-codex/.github/ISSUE_TEMPLATE/6-docs-issue.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: 📗 Documentation Issue
|
||||
description: Tell us if there is missing or incorrect documentation
|
||||
labels: [documentation]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for submitting a documentation request. It helps make Codex better.
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: What is the type of issue?
|
||||
multiple: true
|
||||
options:
|
||||
- Documentation is missing
|
||||
- Documentation is incorrect
|
||||
- Documentation is confusing
|
||||
- Example code is not working
|
||||
- Something else
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What is the issue?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Where did you find it?
|
||||
description: If possible, please provide the URL(s) where you found this issue.
|
||||
49
reference/openai-codex/.github/actions/linux-code-sign/action.yml
vendored
Normal file
49
reference/openai-codex/.github/actions/linux-code-sign/action.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: linux-code-sign
|
||||
description: Sign Linux artifacts with cosign.
|
||||
inputs:
|
||||
target:
|
||||
description: Target triple for the artifacts to sign.
|
||||
required: true
|
||||
artifacts-dir:
|
||||
description: Absolute path to the directory containing built binaries to sign.
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign.
|
||||
default: "codex codex-responses-api-proxy"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
||||
|
||||
- name: Cosign Linux artifacts
|
||||
shell: bash
|
||||
env:
|
||||
ARTIFACTS_DIR: ${{ inputs.artifacts-dir }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
COSIGN_EXPERIMENTAL: "1"
|
||||
COSIGN_YES: "true"
|
||||
COSIGN_OIDC_CLIENT_ID: "sigstore"
|
||||
COSIGN_OIDC_ISSUER: "https://oauth2.sigstore.dev/auth"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
dest="$ARTIFACTS_DIR"
|
||||
if [[ ! -d "$dest" ]]; then
|
||||
echo "Destination $dest does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for binary in ${BINARIES}; do
|
||||
artifact="${dest}/${binary}"
|
||||
if [[ ! -f "$artifact" ]]; then
|
||||
echo "Binary $artifact not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cosign sign-blob \
|
||||
--yes \
|
||||
--bundle "${artifact}.sigstore" \
|
||||
"$artifact"
|
||||
done
|
||||
259
reference/openai-codex/.github/actions/macos-code-sign/action.yml
vendored
Normal file
259
reference/openai-codex/.github/actions/macos-code-sign/action.yml
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
name: macos-code-sign
|
||||
description: Configure, sign, notarize, and clean up macOS code signing artifacts.
|
||||
inputs:
|
||||
target:
|
||||
description: Rust compilation target triple (e.g. aarch64-apple-darwin).
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign and notarize.
|
||||
default: "codex codex-responses-api-proxy"
|
||||
sign-binaries:
|
||||
description: Whether to sign and notarize the macOS binaries.
|
||||
required: false
|
||||
default: "true"
|
||||
sign-dmg:
|
||||
description: Whether to sign and notarize the macOS dmg.
|
||||
required: false
|
||||
default: "true"
|
||||
apple-certificate:
|
||||
description: Base64-encoded Apple signing certificate (P12).
|
||||
required: true
|
||||
apple-certificate-password:
|
||||
description: Password for the signing certificate.
|
||||
required: true
|
||||
apple-notarization-key-p8:
|
||||
description: Base64-encoded Apple notarization key (P8).
|
||||
required: true
|
||||
apple-notarization-key-id:
|
||||
description: Apple notarization key ID.
|
||||
required: true
|
||||
apple-notarization-issuer-id:
|
||||
description: Apple notarization issuer ID.
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure Apple code signing
|
||||
shell: bash
|
||||
env:
|
||||
KEYCHAIN_PASSWORD: actions
|
||||
APPLE_CERTIFICATE: ${{ inputs.apple-certificate }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ inputs.apple-certificate-password }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -z "${APPLE_CERTIFICATE:-}" ]]; then
|
||||
echo "APPLE_CERTIFICATE is required for macOS signing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${APPLE_CERTIFICATE_PASSWORD:-}" ]]; then
|
||||
echo "APPLE_CERTIFICATE_PASSWORD is required for macOS signing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cert_path="${RUNNER_TEMP}/apple_signing_certificate.p12"
|
||||
echo "$APPLE_CERTIFICATE" | base64 -d > "$cert_path"
|
||||
|
||||
keychain_path="${RUNNER_TEMP}/codex-signing.keychain-db"
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" "$keychain_path"
|
||||
security set-keychain-settings -lut 21600 "$keychain_path"
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$keychain_path"
|
||||
|
||||
keychain_args=()
|
||||
cleanup_keychain() {
|
||||
if ((${#keychain_args[@]} > 0)); then
|
||||
security list-keychains -s "${keychain_args[@]}" || true
|
||||
security default-keychain -s "${keychain_args[0]}" || true
|
||||
else
|
||||
security list-keychains -s || true
|
||||
fi
|
||||
if [[ -f "$keychain_path" ]]; then
|
||||
security delete-keychain "$keychain_path" || true
|
||||
fi
|
||||
}
|
||||
|
||||
while IFS= read -r keychain; do
|
||||
[[ -n "$keychain" ]] && keychain_args+=("$keychain")
|
||||
done < <(security list-keychains | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/"//g')
|
||||
|
||||
if ((${#keychain_args[@]} > 0)); then
|
||||
security list-keychains -s "$keychain_path" "${keychain_args[@]}"
|
||||
else
|
||||
security list-keychains -s "$keychain_path"
|
||||
fi
|
||||
|
||||
security default-keychain -s "$keychain_path"
|
||||
security import "$cert_path" -k "$keychain_path" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$keychain_path" > /dev/null
|
||||
|
||||
codesign_hashes=()
|
||||
while IFS= read -r hash; do
|
||||
[[ -n "$hash" ]] && codesign_hashes+=("$hash")
|
||||
done < <(security find-identity -v -p codesigning "$keychain_path" \
|
||||
| sed -n 's/.*\([0-9A-F]\{40\}\).*/\1/p' \
|
||||
| sort -u)
|
||||
|
||||
if ((${#codesign_hashes[@]} == 0)); then
|
||||
echo "No signing identities found in $keychain_path"
|
||||
cleanup_keychain
|
||||
rm -f "$cert_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ((${#codesign_hashes[@]} > 1)); then
|
||||
echo "Multiple signing identities found in $keychain_path:"
|
||||
printf ' %s\n' "${codesign_hashes[@]}"
|
||||
cleanup_keychain
|
||||
rm -f "$cert_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APPLE_CODESIGN_IDENTITY="${codesign_hashes[0]}"
|
||||
|
||||
rm -f "$cert_path"
|
||||
|
||||
echo "APPLE_CODESIGN_IDENTITY=$APPLE_CODESIGN_IDENTITY" >> "$GITHUB_ENV"
|
||||
echo "APPLE_CODESIGN_KEYCHAIN=$keychain_path" >> "$GITHUB_ENV"
|
||||
echo "::add-mask::$APPLE_CODESIGN_IDENTITY"
|
||||
|
||||
- name: Sign macOS binaries
|
||||
if: ${{ inputs.sign-binaries == 'true' }}
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -z "${APPLE_CODESIGN_IDENTITY:-}" ]]; then
|
||||
echo "APPLE_CODESIGN_IDENTITY is required for macOS signing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
keychain_args=()
|
||||
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" && -f "${APPLE_CODESIGN_KEYCHAIN}" ]]; then
|
||||
keychain_args+=(--keychain "${APPLE_CODESIGN_KEYCHAIN}")
|
||||
fi
|
||||
|
||||
entitlements_path="$GITHUB_ACTION_PATH/codex.entitlements.plist"
|
||||
|
||||
for binary in ${BINARIES}; do
|
||||
path="codex-rs/target/${TARGET}/release/${binary}"
|
||||
codesign --force --options runtime --timestamp --entitlements "$entitlements_path" --sign "$APPLE_CODESIGN_IDENTITY" "${keychain_args[@]}" "$path"
|
||||
done
|
||||
|
||||
- name: Notarize macOS binaries
|
||||
if: ${{ inputs.sign-binaries == 'true' }}
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
APPLE_NOTARIZATION_KEY_P8: ${{ inputs.apple-notarization-key-p8 }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ inputs.apple-notarization-key-id }}
|
||||
APPLE_NOTARIZATION_ISSUER_ID: ${{ inputs.apple-notarization-issuer-id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
for var in APPLE_NOTARIZATION_KEY_P8 APPLE_NOTARIZATION_KEY_ID APPLE_NOTARIZATION_ISSUER_ID; do
|
||||
if [[ -z "${!var:-}" ]]; then
|
||||
echo "$var is required for notarization"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
notary_key_path="${RUNNER_TEMP}/notarytool.key.p8"
|
||||
echo "$APPLE_NOTARIZATION_KEY_P8" | base64 -d > "$notary_key_path"
|
||||
cleanup_notary() {
|
||||
rm -f "$notary_key_path"
|
||||
}
|
||||
trap cleanup_notary EXIT
|
||||
|
||||
source "$GITHUB_ACTION_PATH/notary_helpers.sh"
|
||||
|
||||
notarize_binary() {
|
||||
local binary="$1"
|
||||
local source_path="codex-rs/target/${TARGET}/release/${binary}"
|
||||
local archive_path="${RUNNER_TEMP}/${binary}.zip"
|
||||
|
||||
if [[ ! -f "$source_path" ]]; then
|
||||
echo "Binary $source_path not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$archive_path"
|
||||
ditto -c -k --keepParent "$source_path" "$archive_path"
|
||||
|
||||
notarize_submission "$binary" "$archive_path" "$notary_key_path"
|
||||
}
|
||||
|
||||
for binary in ${BINARIES}; do
|
||||
notarize_binary "${binary}"
|
||||
done
|
||||
|
||||
- name: Sign and notarize macOS dmg
|
||||
if: ${{ inputs.sign-dmg == 'true' }}
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
APPLE_NOTARIZATION_KEY_P8: ${{ inputs.apple-notarization-key-p8 }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ inputs.apple-notarization-key-id }}
|
||||
APPLE_NOTARIZATION_ISSUER_ID: ${{ inputs.apple-notarization-issuer-id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
for var in APPLE_CODESIGN_IDENTITY APPLE_NOTARIZATION_KEY_P8 APPLE_NOTARIZATION_KEY_ID APPLE_NOTARIZATION_ISSUER_ID; do
|
||||
if [[ -z "${!var:-}" ]]; then
|
||||
echo "$var is required"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
notary_key_path="${RUNNER_TEMP}/notarytool.key.p8"
|
||||
echo "$APPLE_NOTARIZATION_KEY_P8" | base64 -d > "$notary_key_path"
|
||||
cleanup_notary() {
|
||||
rm -f "$notary_key_path"
|
||||
}
|
||||
trap cleanup_notary EXIT
|
||||
|
||||
source "$GITHUB_ACTION_PATH/notary_helpers.sh"
|
||||
|
||||
dmg_name="codex-${TARGET}.dmg"
|
||||
dmg_path="codex-rs/target/${TARGET}/release/${dmg_name}"
|
||||
|
||||
if [[ ! -f "$dmg_path" ]]; then
|
||||
echo "dmg $dmg_path not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
keychain_args=()
|
||||
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" && -f "${APPLE_CODESIGN_KEYCHAIN}" ]]; then
|
||||
keychain_args+=(--keychain "${APPLE_CODESIGN_KEYCHAIN}")
|
||||
fi
|
||||
|
||||
codesign --force --timestamp --sign "$APPLE_CODESIGN_IDENTITY" "${keychain_args[@]}" "$dmg_path"
|
||||
notarize_submission "$dmg_name" "$dmg_path" "$notary_key_path"
|
||||
xcrun stapler staple "$dmg_path"
|
||||
|
||||
- name: Remove signing keychain
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
env:
|
||||
APPLE_CODESIGN_KEYCHAIN: ${{ env.APPLE_CODESIGN_KEYCHAIN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" ]]; then
|
||||
keychain_args=()
|
||||
while IFS= read -r keychain; do
|
||||
[[ "$keychain" == "$APPLE_CODESIGN_KEYCHAIN" ]] && continue
|
||||
[[ -n "$keychain" ]] && keychain_args+=("$keychain")
|
||||
done < <(security list-keychains | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/"//g')
|
||||
if ((${#keychain_args[@]} > 0)); then
|
||||
security list-keychains -s "${keychain_args[@]}"
|
||||
security default-keychain -s "${keychain_args[0]}"
|
||||
fi
|
||||
|
||||
if [[ -f "$APPLE_CODESIGN_KEYCHAIN" ]]; then
|
||||
security delete-keychain "$APPLE_CODESIGN_KEYCHAIN"
|
||||
fi
|
||||
fi
|
||||
8
reference/openai-codex/.github/actions/macos-code-sign/codex.entitlements.plist
vendored
Normal file
8
reference/openai-codex/.github/actions/macos-code-sign/codex.entitlements.plist
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
46
reference/openai-codex/.github/actions/macos-code-sign/notary_helpers.sh
vendored
Normal file
46
reference/openai-codex/.github/actions/macos-code-sign/notary_helpers.sh
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
notarize_submission() {
|
||||
local label="$1"
|
||||
local path="$2"
|
||||
local notary_key_path="$3"
|
||||
|
||||
if [[ -z "${APPLE_NOTARIZATION_KEY_ID:-}" || -z "${APPLE_NOTARIZATION_ISSUER_ID:-}" ]]; then
|
||||
echo "APPLE_NOTARIZATION_KEY_ID and APPLE_NOTARIZATION_ISSUER_ID are required for notarization"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$notary_key_path" || ! -f "$notary_key_path" ]]; then
|
||||
echo "Notary key file $notary_key_path not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$path" ]]; then
|
||||
echo "Notarization payload $path not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local submission_json
|
||||
submission_json=$(xcrun notarytool submit "$path" \
|
||||
--key "$notary_key_path" \
|
||||
--key-id "$APPLE_NOTARIZATION_KEY_ID" \
|
||||
--issuer "$APPLE_NOTARIZATION_ISSUER_ID" \
|
||||
--output-format json \
|
||||
--wait)
|
||||
|
||||
local status submission_id
|
||||
status=$(printf '%s\n' "$submission_json" | jq -r '.status // "Unknown"')
|
||||
submission_id=$(printf '%s\n' "$submission_json" | jq -r '.id // ""')
|
||||
|
||||
if [[ -z "$submission_id" ]]; then
|
||||
echo "Failed to retrieve submission ID for $label"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "::notice title=Notarization::$label submission ${submission_id} completed with status ${status}"
|
||||
|
||||
if [[ "$status" != "Accepted" ]]; then
|
||||
echo "Notarization failed for ${label} (submission ${submission_id}, status ${status})"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
64
reference/openai-codex/.github/actions/prepare-bazel-ci/action.yml
vendored
Normal file
64
reference/openai-codex/.github/actions/prepare-bazel-ci/action.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: prepare-bazel-ci
|
||||
description: Prepare a Bazel CI job with shared setup, repository cache restore, and execution logs.
|
||||
inputs:
|
||||
target:
|
||||
description: Target triple used for setup and cache namespacing.
|
||||
required: true
|
||||
cache-scope:
|
||||
description: Logical namespace used to keep concurrent Bazel jobs from reserving the same repository cache key.
|
||||
required: true
|
||||
install-test-prereqs:
|
||||
description: Install DotSlash for Bazel-backed test jobs.
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
repository-cache-path:
|
||||
description: Filesystem path used for the Bazel repository cache.
|
||||
value: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
repository-cache-key:
|
||||
description: Primary actions/cache key for the Bazel repository cache.
|
||||
value: ${{ steps.cache_bazel_repository_key.outputs.repository-cache-key }}
|
||||
repository-cache-hit:
|
||||
description: Whether the Bazel repository cache restore found an exact key match.
|
||||
value: ${{ steps.cache_bazel_repository_restore.outputs.cache-hit }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ inputs.target }}
|
||||
install-test-prereqs: ${{ inputs.install-test-prereqs }}
|
||||
|
||||
- name: Compute bazel repository cache key
|
||||
id: cache_bazel_repository_key
|
||||
shell: bash
|
||||
env:
|
||||
CACHE_SCOPE: ${{ inputs.cache-scope }}
|
||||
TARGET: ${{ inputs.target }}
|
||||
CACHE_HASH: ${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
run: |
|
||||
echo "repository-cache-key=bazel-cache-${CACHE_SCOPE}-${TARGET}-${CACHE_HASH}" >> "${GITHUB_OUTPUT}"
|
||||
echo "repository-cache-restore-key=bazel-cache-${CACHE_SCOPE}-${TARGET}-" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
# Restore the Bazel repository cache explicitly so external dependencies
|
||||
# do not need to be re-downloaded on every CI run. Keep restore failures
|
||||
# non-fatal so transient cache-service errors degrade to a cold build
|
||||
# instead of failing the job.
|
||||
- name: Restore bazel repository cache
|
||||
id: cache_bazel_repository_restore
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
key: ${{ steps.cache_bazel_repository_key.outputs.repository-cache-key }}
|
||||
restore-keys: |
|
||||
${{ steps.cache_bazel_repository_key.outputs.repository-cache-restore-key }}
|
||||
|
||||
- name: Set up Bazel execution logs
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
|
||||
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
|
||||
54
reference/openai-codex/.github/actions/run-argument-comment-lint/action.yml
vendored
Normal file
54
reference/openai-codex/.github/actions/run-argument-comment-lint/action.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Run argument comment lint
|
||||
description: Run argument-comment-lint on codex-rs via Bazel.
|
||||
|
||||
inputs:
|
||||
target:
|
||||
description: Runner target passed to setup-bazel-ci.
|
||||
required: true
|
||||
buildbuddy-api-key:
|
||||
description: BuildBuddy API key used by Bazel CI.
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ inputs.target }}
|
||||
install-test-prereqs: true
|
||||
|
||||
- name: Install Linux sandbox build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
||||
|
||||
- name: Run argument comment lint on codex-rs via Bazel
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ inputs.buildbuddy-api-key }}
|
||||
shell: bash
|
||||
run: |
|
||||
bazel_targets="$(./tools/argument-comment-lint/list-bazel-targets.sh)"
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
-- \
|
||||
build \
|
||||
--config=argument-comment-lint \
|
||||
--keep_going \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \
|
||||
-- \
|
||||
${bazel_targets}
|
||||
|
||||
- name: Run argument comment lint on codex-rs via Bazel
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ inputs.buildbuddy-api-key }}
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/run-argument-comment-lint-bazel.sh \
|
||||
--config=argument-comment-lint \
|
||||
--platforms=//:local_windows \
|
||||
--keep_going \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
127
reference/openai-codex/.github/actions/setup-bazel-ci/action.yml
vendored
Normal file
127
reference/openai-codex/.github/actions/setup-bazel-ci/action.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
name: setup-bazel-ci
|
||||
description: Prepare a Bazel CI runner with shared caches and optional test prerequisites.
|
||||
inputs:
|
||||
target:
|
||||
description: Target triple used for cache namespacing.
|
||||
required: true
|
||||
install-test-prereqs:
|
||||
description: Install DotSlash for Bazel-backed test jobs.
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
repository-cache-path:
|
||||
description: Filesystem path used for the Bazel repository cache.
|
||||
value: ${{ steps.configure_bazel_repository_cache.outputs.repository-cache-path }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# Some integration tests rely on DotSlash being installed.
|
||||
# See https://github.com/openai/codex/pull/7617.
|
||||
- name: Install DotSlash
|
||||
if: inputs.install-test-prereqs == 'true'
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- name: Make DotSlash available in PATH (Unix)
|
||||
if: inputs.install-test-prereqs == 'true' && runner.os != 'Windows'
|
||||
shell: bash
|
||||
run: cp "$(which dotslash)" /usr/local/bin
|
||||
|
||||
- name: Make DotSlash available in PATH (Windows)
|
||||
if: inputs.install-test-prereqs == 'true' && runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: Copy-Item (Get-Command dotslash).Source -Destination "$env:LOCALAPPDATA\Microsoft\WindowsApps\dotslash.exe"
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
|
||||
|
||||
- name: Configure Bazel repository cache
|
||||
id: configure_bazel_repository_cache
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Keep the repository cache under HOME on all runners. Windows `D:\a`
|
||||
# cache paths match `.bazelrc`, but `actions/cache/restore` currently
|
||||
# returns HTTP 400 for that path in the Windows clippy job.
|
||||
$repositoryCachePath = Join-Path $HOME '.cache/bazel-repo-cache'
|
||||
"repository-cache-path=$repositoryCachePath" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||
"BAZEL_REPOSITORY_CACHE=$repositoryCachePath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
|
||||
- name: Configure Bazel output root (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Use the shortest available drive to reduce argv/path length issues,
|
||||
# but avoid the drive root because some Windows test launchers mis-handle
|
||||
# MANIFEST paths there.
|
||||
$hasDDrive = Test-Path 'D:\'
|
||||
$bazelOutputUserRoot = if ($hasDDrive) { 'D:\b' } else { 'C:\b' }
|
||||
$repoContentsCache = Join-Path $env:RUNNER_TEMP "bazel-repo-contents-cache-$env:GITHUB_RUN_ID-$env:GITHUB_JOB"
|
||||
"BAZEL_OUTPUT_USER_ROOT=$bazelOutputUserRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
"BAZEL_REPO_CONTENTS_CACHE=$repoContentsCache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
|
||||
- name: Expose MSVC SDK environment (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Bazel exec-side Rust build scripts do not reliably inherit the MSVC developer
|
||||
# shell on GitHub-hosted Windows runners, so discover the latest VS install and
|
||||
# ask `VsDevCmd.bat` to materialize the x64/x64 compiler + SDK environment.
|
||||
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if (-not (Test-Path $vswhere)) {
|
||||
throw "vswhere.exe not found"
|
||||
}
|
||||
|
||||
$installPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>$null
|
||||
if (-not $installPath) {
|
||||
throw "Could not locate a Visual Studio installation with VC tools"
|
||||
}
|
||||
|
||||
$vsDevCmd = Join-Path $installPath 'Common7\Tools\VsDevCmd.bat'
|
||||
if (-not (Test-Path $vsDevCmd)) {
|
||||
throw "VsDevCmd.bat not found at $vsDevCmd"
|
||||
}
|
||||
|
||||
# Keep the export surface explicit: these are the paths and SDK roots that the
|
||||
# MSVC toolchain probes need later when Bazel runs Windows exec-platform build
|
||||
# scripts such as `aws-lc-sys`.
|
||||
$varsToExport = @(
|
||||
'INCLUDE',
|
||||
'LIB',
|
||||
'LIBPATH',
|
||||
'PATH',
|
||||
'UCRTVersion',
|
||||
'UniversalCRTSdkDir',
|
||||
'VCINSTALLDIR',
|
||||
'VCToolsInstallDir',
|
||||
'WindowsLibPath',
|
||||
'WindowsSdkBinPath',
|
||||
'WindowsSdkDir',
|
||||
'WindowsSDKLibVersion',
|
||||
'WindowsSDKVersion'
|
||||
)
|
||||
|
||||
# `VsDevCmd.bat` is a batch file, so invoke it under `cmd.exe`, suppress its
|
||||
# banner, then dump the resulting environment with `set`. Re-export only the
|
||||
# approved keys into `GITHUB_ENV` so later steps inherit the same MSVC context.
|
||||
$envLines = & cmd.exe /c ('"{0}" -no_logo -arch=x64 -host_arch=x64 >nul && set' -f $vsDevCmd)
|
||||
foreach ($line in $envLines) {
|
||||
if ($line -notmatch '^(.*?)=(.*)$') {
|
||||
continue
|
||||
}
|
||||
|
||||
$name = $matches[1]
|
||||
$value = $matches[2]
|
||||
if ($varsToExport -contains $name) {
|
||||
"$name=$value" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
}
|
||||
}
|
||||
|
||||
- name: Compute cache-stable Windows Bazel PATH
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: ./.github/scripts/compute-bazel-windows-path.ps1
|
||||
|
||||
- name: Enable Git long paths (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: git config --global core.longpaths true
|
||||
17
reference/openai-codex/.github/actions/setup-msvc-env/action.yml
vendored
Normal file
17
reference/openai-codex/.github/actions/setup-msvc-env/action.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: setup-msvc-env
|
||||
description: Expose an MSVC developer environment for the requested Windows target.
|
||||
inputs:
|
||||
target:
|
||||
description: Rust target triple that will be built on this Windows runner.
|
||||
required: true
|
||||
host-arch:
|
||||
description: Optional Visual Studio host architecture override.
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Expose MSVC SDK environment
|
||||
shell: pwsh
|
||||
run: '& "$env:GITHUB_ACTION_PATH/setup-msvc-env.ps1" -Target "${{ inputs.target }}" -HostArch "${{ inputs.host-arch }}"'
|
||||
257
reference/openai-codex/.github/actions/setup-msvc-env/setup-msvc-env.ps1
vendored
Normal file
257
reference/openai-codex/.github/actions/setup-msvc-env/setup-msvc-env.ps1
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Target,
|
||||
|
||||
[string]$HostArch = ""
|
||||
)
|
||||
|
||||
# Cargo can cross-compile the Rust code for Windows ARM64 on a Windows x64
|
||||
# runner, but rustup alone does not expose the matching MSVC/UCRT include and
|
||||
# library paths. Ask Visual Studio for the target-specific developer
|
||||
# environment, then persist the relevant variables through GITHUB_ENV so the
|
||||
# later Cargo step sees the same environment as a normal VsDevCmd shell.
|
||||
switch ($Target) {
|
||||
"x86_64-pc-windows-msvc" {
|
||||
$TargetArch = "x64"
|
||||
$RequiredComponent = "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"
|
||||
}
|
||||
"aarch64-pc-windows-msvc" {
|
||||
$TargetArch = "arm64"
|
||||
$RequiredComponent = "Microsoft.VisualStudio.Component.VC.Tools.ARM64"
|
||||
}
|
||||
default {
|
||||
throw "Unsupported Windows MSVC target: $Target"
|
||||
}
|
||||
}
|
||||
|
||||
# VsDevCmd needs both sides of the cross compile: the architecture of the
|
||||
# machine running the tools and the architecture of the binaries being linked.
|
||||
# Infer the host from the runner unless a caller needs to override it.
|
||||
if (-not $HostArch) {
|
||||
$HostArch = if ($env:PROCESSOR_ARCHITEW6432 -eq "ARM64" -or $env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
|
||||
"arm64"
|
||||
} else {
|
||||
"x64"
|
||||
}
|
||||
}
|
||||
|
||||
$VsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if (-not (Test-Path $VsWhere)) {
|
||||
throw "vswhere.exe not found"
|
||||
}
|
||||
|
||||
# Require the target VC tools component, not merely any Visual Studio install,
|
||||
# so an x64 archive producer cannot silently link ARM64 tests with the wrong
|
||||
# SDK/toolchain layout.
|
||||
$InstallPath = & $VsWhere -latest -products * -requires $RequiredComponent -property installationPath 2>$null
|
||||
if (-not $InstallPath) {
|
||||
throw "Could not locate a Visual Studio installation with component $RequiredComponent"
|
||||
}
|
||||
|
||||
$VsDevCmd = Join-Path $InstallPath "Common7\Tools\VsDevCmd.bat"
|
||||
if (-not (Test-Path $VsDevCmd)) {
|
||||
throw "VsDevCmd.bat not found at $VsDevCmd"
|
||||
}
|
||||
|
||||
$VarsToExport = @(
|
||||
"INCLUDE",
|
||||
"LIB",
|
||||
"LIBPATH",
|
||||
"PATH",
|
||||
"UCRTVersion",
|
||||
"UniversalCRTSdkDir",
|
||||
"VCINSTALLDIR",
|
||||
"VCToolsInstallDir",
|
||||
"WindowsLibPath",
|
||||
"WindowsSdkBinPath",
|
||||
"WindowsSdkDir",
|
||||
"WindowsSDKLibVersion",
|
||||
"WindowsSDKVersion"
|
||||
)
|
||||
|
||||
# Run VsDevCmd inside cmd.exe because it is a batch file, then copy just the
|
||||
# variables Cargo/rustc need into the GitHub Actions environment file. PowerShell
|
||||
# cannot mutate the parent composite-action environment directly.
|
||||
$EnvLines = & cmd.exe /c ('"{0}" -no_logo -arch={1} -host_arch={2} >nul && set' -f $VsDevCmd, $TargetArch, $HostArch)
|
||||
$VcToolsInstallDir = $null
|
||||
foreach ($Line in $EnvLines) {
|
||||
if ($Line -notmatch "^(.*?)=(.*)$") {
|
||||
continue
|
||||
}
|
||||
|
||||
$Name = $Matches[1]
|
||||
$Value = $Matches[2]
|
||||
if ($VarsToExport -contains $Name) {
|
||||
if ($Name -ieq "Path") {
|
||||
$Name = "PATH"
|
||||
}
|
||||
if ($Name -eq "VCToolsInstallDir") {
|
||||
$VcToolsInstallDir = $Value
|
||||
}
|
||||
"$Name=$Value" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $VcToolsInstallDir) {
|
||||
throw "VCToolsInstallDir was not exported by VsDevCmd.bat"
|
||||
}
|
||||
|
||||
# Prefer Rust's bundled linker when rustup provides one, then Visual Studio's
|
||||
# LLVM linker, and finally MSVC link.exe. This keeps the cross-compile path close
|
||||
# to Rust's normal Windows MSVC behavior while still working on runner images
|
||||
# where one of those linkers is absent.
|
||||
$Linker = $null
|
||||
$Rustc = Get-Command rustc -ErrorAction SilentlyContinue
|
||||
if ($Rustc) {
|
||||
$Sysroot = (& rustc --print sysroot 2>$null).Trim()
|
||||
$RustHost = & rustc -vV 2>$null | Select-String "^host: " | ForEach-Object { $_.Line.Substring(6) }
|
||||
if ($RustHost) {
|
||||
$RustHost = $RustHost.Trim()
|
||||
}
|
||||
if ($Sysroot -and $RustHost) {
|
||||
$RustLld = Join-Path $Sysroot "lib\rustlib\$RustHost\bin\rust-lld.exe"
|
||||
if (Test-Path $RustLld) {
|
||||
$Linker = $RustLld
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not $Linker) {
|
||||
$Linker = Join-Path $InstallPath "VC\Tools\Llvm\x64\bin\lld-link.exe"
|
||||
}
|
||||
if (-not (Test-Path $Linker)) {
|
||||
$Linker = Join-Path $VcToolsInstallDir "bin\Host${HostArch}\${TargetArch}\link.exe"
|
||||
}
|
||||
if (-not (Test-Path $Linker)) {
|
||||
throw "Windows linker not found at $Linker"
|
||||
}
|
||||
|
||||
# rustc passes `/arm64hazardfree` for ARM64 MSVC links. The lld variants on our
|
||||
# Windows x64 archive producers reject that flag, including when rustc places it
|
||||
# inside a response file. Compile a tiny forwarding wrapper that strips only
|
||||
# that unsupported flag, then delegate every other argument to the real linker.
|
||||
if ($TargetArch -eq "arm64" -and (Split-Path -Leaf $Linker) -match "lld") {
|
||||
$WrapperDir = Join-Path $env:RUNNER_TEMP "msvc-lld-wrapper"
|
||||
New-Item -Path $WrapperDir -ItemType Directory -Force | Out-Null
|
||||
$WrapperPath = Join-Path $WrapperDir "lld-link-wrapper.exe"
|
||||
$WrapperSource = @'
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
var linker = Environment.GetEnvironmentVariable("MSVC_REAL_LINKER");
|
||||
if (string.IsNullOrEmpty(linker))
|
||||
{
|
||||
Console.Error.WriteLine("MSVC_REAL_LINKER is not set");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var startInfo = new ProcessStartInfo(linker)
|
||||
{
|
||||
UseShellExecute = false,
|
||||
};
|
||||
var filteredArgs = new List<string> { "-flavor", "link", "/defaultlib:ucrt", "/nodefaultlib:libucrt" };
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (!string.Equals(arg, "/arm64hazardfree", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
filteredArgs.Add(QuoteArgument(FilterResponseFile(arg)));
|
||||
}
|
||||
}
|
||||
startInfo.Arguments = string.Join(" ", filteredArgs);
|
||||
|
||||
using var process = Process.Start(startInfo);
|
||||
if (process is null)
|
||||
{
|
||||
Console.Error.WriteLine($"Failed to start linker: {linker}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
return process.ExitCode;
|
||||
}
|
||||
|
||||
private static string FilterResponseFile(string argument)
|
||||
{
|
||||
if (argument.Length < 2 || argument[0] != '@')
|
||||
{
|
||||
return argument;
|
||||
}
|
||||
|
||||
var responsePath = argument.Substring(1);
|
||||
if (!File.Exists(responsePath))
|
||||
{
|
||||
return argument;
|
||||
}
|
||||
|
||||
var filteredResponsePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".rsp");
|
||||
var responseContents = Regex.Replace(
|
||||
File.ReadAllText(responsePath),
|
||||
"/arm64hazardfree",
|
||||
string.Empty,
|
||||
RegexOptions.IgnoreCase);
|
||||
File.WriteAllText(filteredResponsePath, responseContents);
|
||||
return "@" + filteredResponsePath;
|
||||
}
|
||||
|
||||
private static string QuoteArgument(string argument)
|
||||
{
|
||||
if (argument.Length == 0)
|
||||
{
|
||||
return "\"\"";
|
||||
}
|
||||
if (argument.IndexOfAny(new[] { ' ', '\t', '"' }) < 0)
|
||||
{
|
||||
return argument;
|
||||
}
|
||||
|
||||
var quoted = new StringBuilder("\"");
|
||||
var backslashes = 0;
|
||||
foreach (var character in argument)
|
||||
{
|
||||
if (character == '\\')
|
||||
{
|
||||
backslashes++;
|
||||
continue;
|
||||
}
|
||||
if (character == '"')
|
||||
{
|
||||
quoted.Append('\\', (backslashes * 2) + 1);
|
||||
quoted.Append(character);
|
||||
backslashes = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
quoted.Append('\\', backslashes);
|
||||
backslashes = 0;
|
||||
quoted.Append(character);
|
||||
}
|
||||
quoted.Append('\\', backslashes * 2);
|
||||
quoted.Append('"');
|
||||
return quoted.ToString();
|
||||
}
|
||||
}
|
||||
'@
|
||||
$WrapperSourcePath = Join-Path $WrapperDir "lld-link-wrapper.cs"
|
||||
$WrapperSource | Out-File -FilePath $WrapperSourcePath -Encoding utf8
|
||||
$Csc = Join-Path $InstallPath "MSBuild\Current\Bin\Roslyn\csc.exe"
|
||||
if (-not (Test-Path $Csc)) {
|
||||
throw "csc.exe not found at $Csc"
|
||||
}
|
||||
& $Csc /nologo /target:exe /out:$WrapperPath $WrapperSourcePath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to compile lld-link wrapper"
|
||||
}
|
||||
"MSVC_REAL_LINKER=$Linker" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
$Linker = $WrapperPath
|
||||
}
|
||||
|
||||
Write-Output "Using Windows linker: $Linker"
|
||||
$CargoTarget = $Target.ToUpperInvariant().Replace("-", "_")
|
||||
"CARGO_TARGET_${CargoTarget}_LINKER=$Linker" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
42
reference/openai-codex/.github/actions/setup-rusty-v8/action.yml
vendored
Normal file
42
reference/openai-codex/.github/actions/setup-rusty-v8/action.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: setup-rusty-v8
|
||||
description: Download and verify Codex-built rusty_v8 artifacts for Cargo builds.
|
||||
inputs:
|
||||
target:
|
||||
description: Rust target triple with Codex-built V8 release artifacts.
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure rusty_v8 artifact overrides and verify checksums
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
|
||||
release_tag="rusty-v8-v${version}"
|
||||
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
|
||||
binding_dir="${RUNNER_TEMP}/rusty_v8"
|
||||
archive_path="${binding_dir}/librusty_v8_release_${TARGET}.a.gz"
|
||||
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
|
||||
checksums_path="${binding_dir}/rusty_v8_release_${TARGET}.sha256"
|
||||
|
||||
mkdir -p "${binding_dir}"
|
||||
curl -fsSL "${base_url}/librusty_v8_release_${TARGET}.a.gz" -o "${archive_path}"
|
||||
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
|
||||
curl -fsSL "${base_url}/rusty_v8_release_${TARGET}.sha256" -o "${checksums_path}"
|
||||
|
||||
if [[ "$(wc -l < "${checksums_path}")" -ne 2 ]]; then
|
||||
echo "Expected exactly two checksums for ${TARGET} in ${checksums_path}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
(cd "${binding_dir}" && sha256sum -c "${checksums_path}")
|
||||
else
|
||||
(cd "${binding_dir}" && shasum -a 256 -c "${checksums_path}")
|
||||
fi
|
||||
echo "RUSTY_V8_ARCHIVE=${archive_path}" >> "${GITHUB_ENV}"
|
||||
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "${GITHUB_ENV}"
|
||||
73
reference/openai-codex/.github/actions/windows-code-sign/action.yml
vendored
Normal file
73
reference/openai-codex/.github/actions/windows-code-sign/action.yml
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
name: windows-code-sign
|
||||
description: Sign Windows binaries with Azure Trusted Signing.
|
||||
inputs:
|
||||
target:
|
||||
description: Target triple for the artifacts to sign.
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign.
|
||||
default: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner"
|
||||
client-id:
|
||||
description: Azure Trusted Signing client ID.
|
||||
required: true
|
||||
tenant-id:
|
||||
description: Azure tenant ID for Trusted Signing.
|
||||
required: true
|
||||
subscription-id:
|
||||
description: Azure subscription ID for Trusted Signing.
|
||||
required: true
|
||||
endpoint:
|
||||
description: Azure Trusted Signing endpoint.
|
||||
required: true
|
||||
account-name:
|
||||
description: Azure Trusted Signing account name.
|
||||
required: true
|
||||
certificate-profile-name:
|
||||
description: Certificate profile name for signing.
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Azure login for Trusted Signing (OIDC)
|
||||
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0
|
||||
with:
|
||||
client-id: ${{ inputs.client-id }}
|
||||
tenant-id: ${{ inputs.tenant-id }}
|
||||
subscription-id: ${{ inputs.subscription-id }}
|
||||
|
||||
- name: Prepare file list
|
||||
id: prepare
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
{
|
||||
echo "files<<EOF"
|
||||
for binary in ${BINARIES}; do
|
||||
echo "${GITHUB_WORKSPACE}/codex-rs/target/${TARGET}/release/${binary}.exe"
|
||||
done
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Sign Windows binaries with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@1d365fec12862c4aa68fcac418143d73f0cea293 # v0.5.11
|
||||
with:
|
||||
endpoint: ${{ inputs.endpoint }}
|
||||
trusted-signing-account-name: ${{ inputs.account-name }}
|
||||
certificate-profile-name: ${{ inputs.certificate-profile-name }}
|
||||
exclude-environment-credential: true
|
||||
exclude-workload-identity-credential: true
|
||||
exclude-managed-identity-credential: true
|
||||
exclude-shared-token-cache-credential: true
|
||||
exclude-visual-studio-credential: true
|
||||
exclude-visual-studio-code-credential: true
|
||||
exclude-azure-cli-credential: false
|
||||
exclude-azure-powershell-credential: true
|
||||
exclude-azure-developer-cli-credential: true
|
||||
exclude-interactive-browser-credential: true
|
||||
cache-dependencies: false
|
||||
files: ${{ steps.prepare.outputs.files }}
|
||||
10
reference/openai-codex/.github/blob-size-allowlist.txt
vendored
Normal file
10
reference/openai-codex/.github/blob-size-allowlist.txt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Paths are matched exactly, relative to the repository root.
|
||||
# Keep this list short and limited to intentional large checked-in assets.
|
||||
|
||||
.github/codex-cli-splash.png
|
||||
MODULE.bazel.lock
|
||||
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
|
||||
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
|
||||
codex-rs/tui/tests/fixtures/oss-story.jsonl
|
||||
codex-rs/tui_app_server/tests/fixtures/oss-story.jsonl
|
||||
codex-rs/tui/src/app.rs
|
||||
BIN
reference/openai-codex/.github/codex-cli-splash.png
vendored
Normal file
BIN
reference/openai-codex/.github/codex-cli-splash.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 818 KiB |
3
reference/openai-codex/.github/codex/home/config.toml
vendored
Normal file
3
reference/openai-codex/.github/codex/home/config.toml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
model = "gpt-5.1"
|
||||
|
||||
# Consider setting [mcp_servers] here!
|
||||
9
reference/openai-codex/.github/codex/labels/codex-attempt.md
vendored
Normal file
9
reference/openai-codex/.github/codex/labels/codex-attempt.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Attempt to solve the reported issue.
|
||||
|
||||
If a code change is required, create a new branch, commit the fix, and open a pull request that resolves the problem.
|
||||
|
||||
Here is the original GitHub issue that triggered this run:
|
||||
|
||||
### {CODEX_ACTION_ISSUE_TITLE}
|
||||
|
||||
{CODEX_ACTION_ISSUE_BODY}
|
||||
7
reference/openai-codex/.github/codex/labels/codex-review.md
vendored
Normal file
7
reference/openai-codex/.github/codex/labels/codex-review.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Review this PR and respond with a very concise final message, formatted in Markdown.
|
||||
|
||||
There should be a summary of the changes (1-2 sentences) and a few bullet points if necessary.
|
||||
|
||||
Then provide the **review** (1-2 sentences plus bullet points, friendly tone).
|
||||
|
||||
{CODEX_ACTION_GITHUB_EVENT_PATH} contains the JSON that triggered this GitHub workflow. It contains the `base` and `head` refs that define this PR. Both refs are available locally.
|
||||
139
reference/openai-codex/.github/codex/labels/codex-rust-review.md
vendored
Normal file
139
reference/openai-codex/.github/codex/labels/codex-rust-review.md
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
Review this PR and respond with a very concise final message, formatted in Markdown.
|
||||
|
||||
There should be a summary of the changes (1-2 sentences) and a few bullet points if necessary.
|
||||
|
||||
Then provide the **review** (1-2 sentences plus bullet points, friendly tone).
|
||||
|
||||
Things to look out for when doing the review:
|
||||
|
||||
## General Principles
|
||||
|
||||
- **Make sure the pull request body explains the motivation behind the change.** If the author has failed to do this, call it out, and if you think you can deduce the motivation behind the change, propose copy.
|
||||
- Ideally, the PR body also contains a small summary of the change. For small changes, the PR title may be sufficient.
|
||||
- Each PR should ideally do one conceptual thing. For example, if a PR does a refactoring as well as introducing a new feature, push back and suggest the refactoring be done in a separate PR. This makes things easier for the reviewer, as refactoring changes can often be far-reaching, yet quick to review.
|
||||
- When introducing new code, be on the lookout for code that duplicates existing code. When found, propose a way to refactor the existing code such that it should be reused.
|
||||
|
||||
## Code Organization
|
||||
|
||||
- Each crate in the Cargo workspace in `codex-rs` has a specific purpose: make a note if you believe new code is not introduced in the correct crate.
|
||||
- When possible, try to keep the `core` crate as small as possible. Non-core but shared logic is often a good candidate for `codex-rs/common`.
|
||||
- Be wary of large files and offer suggestions for how to break things into more reasonably-sized files.
|
||||
- Rust files should generally be organized such that the public parts of the API appear near the top of the file and helper functions go below. This is analogous to the "inverted pyramid" structure that is favored in journalism.
|
||||
|
||||
## Assertions in Tests
|
||||
|
||||
Assert the equality of the entire objects instead of doing "piecemeal comparisons," performing `assert_eq!()` on individual fields.
|
||||
|
||||
Note that unit tests also function as "executable documentation." As shown in the following example, "piecemeal comparisons" are often more verbose, provide less coverage, and are not as useful as executable documentation.
|
||||
|
||||
For example, suppose you have the following enum:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Message {
|
||||
Request {
|
||||
id: String,
|
||||
method: String,
|
||||
params: Option<serde_json::Value>,
|
||||
},
|
||||
Notification {
|
||||
method: String,
|
||||
params: Option<serde_json::Value>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
This is an example of a _piecemeal_ comparison:
|
||||
|
||||
```rust
|
||||
// BAD: Piecemeal Comparison
|
||||
|
||||
#[test]
|
||||
fn test_get_latest_messages() {
|
||||
let messages = get_latest_messages();
|
||||
assert_eq!(messages.len(), 2);
|
||||
|
||||
let m0 = &messages[0];
|
||||
match m0 {
|
||||
Message::Request { id, method, params } => {
|
||||
assert_eq!(id, "123");
|
||||
assert_eq!(method, "subscribe");
|
||||
assert_eq!(
|
||||
*params,
|
||||
Some(json!({
|
||||
"conversation_id": "x42z86"
|
||||
}))
|
||||
)
|
||||
}
|
||||
Message::Notification { .. } => {
|
||||
panic!("expected Request");
|
||||
}
|
||||
}
|
||||
|
||||
let m1 = &messages[1];
|
||||
match m1 {
|
||||
Message::Request { .. } => {
|
||||
panic!("expected Notification");
|
||||
}
|
||||
Message::Notification { method, params } => {
|
||||
assert_eq!(method, "log");
|
||||
assert_eq!(
|
||||
*params,
|
||||
Some(json!({
|
||||
"level": "info",
|
||||
"message": "subscribed"
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a _deep_ comparison:
|
||||
|
||||
```rust
|
||||
// GOOD: Verify the entire structure with a single assert_eq!().
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_get_latest_messages() {
|
||||
let messages = get_latest_messages();
|
||||
|
||||
assert_eq!(
|
||||
vec![
|
||||
Message::Request {
|
||||
id: "123".to_string(),
|
||||
method: "subscribe".to_string(),
|
||||
params: Some(json!({
|
||||
"conversation_id": "x42z86"
|
||||
})),
|
||||
},
|
||||
Message::Notification {
|
||||
method: "log".to_string(),
|
||||
params: Some(json!({
|
||||
"level": "info",
|
||||
"message": "subscribed"
|
||||
})),
|
||||
},
|
||||
],
|
||||
messages,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## More Tactical Rust Things To Look Out For
|
||||
|
||||
- Do not use `unsafe` (unless you have a really, really good reason like using an operating system API directly and no safe wrapper exists). For example, there are cases where it is tempting to use `unsafe` in order to use `std::env::set_var()`, but this indeed `unsafe` and has led to race conditions on multiple occasions. (When this happens, find a mechanism other than environment variables to use for configuration.)
|
||||
- Encourage the use of small enums or the newtype pattern in Rust if it helps readability without adding significant cognitive load or lines of code.
|
||||
- If you see opportunities for the changes in a diff to use more idiomatic Rust, please make specific recommendations. For example, favor the use of expressions over `return`.
|
||||
- When modifying a `Cargo.toml` file, make sure that dependency lists stay alphabetically sorted. Also consider whether a new dependency is added to the appropriate place (e.g., `[dependencies]` versus `[dev-dependencies]`)
|
||||
|
||||
## Pull Request Body
|
||||
|
||||
- If the nature of the change seems to have a visual component (which is often the case for changes to `codex-rs/tui`), recommend including a screenshot or video to demonstrate the change, if appropriate.
|
||||
- References to existing GitHub issues and PRs are encouraged, where appropriate, though you likely do not have network access, so may not be able to help here.
|
||||
|
||||
# PR Information
|
||||
|
||||
{CODEX_ACTION_GITHUB_EVENT_PATH} contains the JSON that triggered this GitHub workflow. It contains the `base` and `head` refs that define this PR. Both refs are available locally.
|
||||
7
reference/openai-codex/.github/codex/labels/codex-triage.md
vendored
Normal file
7
reference/openai-codex/.github/codex/labels/codex-triage.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Troubleshoot whether the reported issue is valid.
|
||||
|
||||
Provide a concise and respectful comment summarizing the findings.
|
||||
|
||||
### {CODEX_ACTION_ISSUE_TITLE}
|
||||
|
||||
{CODEX_ACTION_ISSUE_BODY}
|
||||
42
reference/openai-codex/.github/dependabot.yaml
vendored
Normal file
42
reference/openai-codex/.github/dependabot.yaml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#package-ecosystem-
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: bun
|
||||
directory: .github/actions/codex
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: cargo
|
||||
directories:
|
||||
- codex-rs
|
||||
- codex-rs/*
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: devcontainers
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: docker
|
||||
directory: codex-cli
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: rust-toolchain
|
||||
directory: codex-rs
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
24
reference/openai-codex/.github/dotslash-argument-comment-lint-config.json
vendored
Normal file
24
reference/openai-codex/.github/dotslash-argument-comment-lint-config.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"outputs": {
|
||||
"argument-comment-lint": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"regex": "^argument-comment-lint-aarch64-apple-darwin\\.tar\\.gz$",
|
||||
"path": "argument-comment-lint/bin/argument-comment-lint"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"regex": "^argument-comment-lint-x86_64-unknown-linux-gnu\\.tar\\.gz$",
|
||||
"path": "argument-comment-lint/bin/argument-comment-lint"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^argument-comment-lint-aarch64-unknown-linux-gnu\\.tar\\.gz$",
|
||||
"path": "argument-comment-lint/bin/argument-comment-lint"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"regex": "^argument-comment-lint-x86_64-pc-windows-msvc\\.zip$",
|
||||
"path": "argument-comment-lint/bin/argument-comment-lint.exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
reference/openai-codex/.github/dotslash-config.json
vendored
Normal file
124
reference/openai-codex/.github/dotslash-config.json
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"outputs": {
|
||||
"codex": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"regex": "^codex-package-aarch64-apple-darwin\\.tar\\.zst$",
|
||||
"path": "bin/codex"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"regex": "^codex-package-x86_64-apple-darwin\\.tar\\.zst$",
|
||||
"path": "bin/codex"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"regex": "^codex-package-x86_64-unknown-linux-musl\\.tar\\.zst$",
|
||||
"path": "bin/codex"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^codex-package-aarch64-unknown-linux-musl\\.tar\\.zst$",
|
||||
"path": "bin/codex"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-package-x86_64-pc-windows-msvc\\.tar\\.zst$",
|
||||
"path": "bin/codex.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-package-aarch64-pc-windows-msvc\\.tar\\.zst$",
|
||||
"path": "bin/codex.exe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-app-server": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"regex": "^codex-app-server-package-aarch64-apple-darwin\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"regex": "^codex-app-server-package-x86_64-apple-darwin\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"regex": "^codex-app-server-package-x86_64-unknown-linux-musl\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^codex-app-server-package-aarch64-unknown-linux-musl\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-app-server-package-x86_64-pc-windows-msvc\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-app-server-package-aarch64-pc-windows-msvc\\.tar\\.zst$",
|
||||
"path": "bin/codex-app-server.exe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-responses-api-proxy": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"regex": "^codex-responses-api-proxy-aarch64-apple-darwin\\.zst$",
|
||||
"path": "codex-responses-api-proxy"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"regex": "^codex-responses-api-proxy-x86_64-apple-darwin\\.zst$",
|
||||
"path": "codex-responses-api-proxy"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"regex": "^codex-responses-api-proxy-x86_64-unknown-linux-musl\\.zst$",
|
||||
"path": "codex-responses-api-proxy"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^codex-responses-api-proxy-aarch64-unknown-linux-musl\\.zst$",
|
||||
"path": "codex-responses-api-proxy"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-responses-api-proxy-x86_64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-responses-api-proxy.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-responses-api-proxy-aarch64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-responses-api-proxy.exe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bwrap": {
|
||||
"platforms": {
|
||||
"linux-x86_64": {
|
||||
"regex": "^bwrap-x86_64-unknown-linux-musl\\.zst$",
|
||||
"path": "bwrap"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^bwrap-aarch64-unknown-linux-musl\\.zst$",
|
||||
"path": "bwrap"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-command-runner": {
|
||||
"platforms": {
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-command-runner-x86_64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-command-runner.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-command-runner-aarch64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-command-runner.exe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-windows-sandbox-setup": {
|
||||
"platforms": {
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-windows-sandbox-setup-x86_64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-windows-sandbox-setup.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-windows-sandbox-setup-aarch64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-windows-sandbox-setup.exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
reference/openai-codex/.github/dotslash-zsh-config.json
vendored
Normal file
28
reference/openai-codex/.github/dotslash-zsh-config.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"outputs": {
|
||||
"codex-zsh": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"name": "codex-zsh-aarch64-apple-darwin.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"path": "codex-zsh/bin/zsh"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"name": "codex-zsh-x86_64-apple-darwin.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"path": "codex-zsh/bin/zsh"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"name": "codex-zsh-x86_64-unknown-linux-musl.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"path": "codex-zsh/bin/zsh"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"name": "codex-zsh-aarch64-unknown-linux-musl.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"path": "codex-zsh/bin/zsh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
reference/openai-codex/.github/pull_request_template.md
vendored
Normal file
8
reference/openai-codex/.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# External (non-OpenAI) Pull Request Requirements
|
||||
|
||||
External code contributions are by invitation only. Please read the dedicated "Contributing" markdown file for details:
|
||||
https://github.com/openai/codex/blob/main/docs/contributing.md
|
||||
|
||||
If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes.
|
||||
|
||||
Include a link to a bug report or enhancement request.
|
||||
172
reference/openai-codex/.github/scripts/build-codex-package-archive.sh
vendored
Normal file
172
reference/openai-codex/.github/scripts/build-codex-package-archive.sh
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: build-codex-package-archive.sh \
|
||||
--target <rust-target> \
|
||||
--bundle <primary|app-server> \
|
||||
--entrypoint-dir <dir> \
|
||||
--archive-dir <dir> \
|
||||
[--bwrap-bin <path>] \
|
||||
[--codex-command-runner-bin <path>] \
|
||||
[--codex-windows-sandbox-setup-bin <path>] \
|
||||
[--target-suffixed-entrypoint]
|
||||
EOF
|
||||
}
|
||||
|
||||
target=""
|
||||
bundle=""
|
||||
entrypoint_dir=""
|
||||
archive_dir=""
|
||||
target_suffixed_entrypoint="false"
|
||||
resource_args=()
|
||||
bwrap_bin_provided="false"
|
||||
command_runner_bin_provided="false"
|
||||
sandbox_setup_bin_provided="false"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--target)
|
||||
target="${2:?--target requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
--bundle)
|
||||
bundle="${2:?--bundle requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
--entrypoint-dir)
|
||||
entrypoint_dir="${2:?--entrypoint-dir requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
--archive-dir)
|
||||
archive_dir="${2:?--archive-dir requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
--bwrap-bin)
|
||||
resource_args+=(--bwrap-bin "${2:?--bwrap-bin requires a value}")
|
||||
bwrap_bin_provided="true"
|
||||
shift 2
|
||||
;;
|
||||
--codex-command-runner-bin)
|
||||
resource_args+=(
|
||||
--codex-command-runner-bin
|
||||
"${2:?--codex-command-runner-bin requires a value}"
|
||||
)
|
||||
command_runner_bin_provided="true"
|
||||
shift 2
|
||||
;;
|
||||
--codex-windows-sandbox-setup-bin)
|
||||
resource_args+=(
|
||||
--codex-windows-sandbox-setup-bin
|
||||
"${2:?--codex-windows-sandbox-setup-bin requires a value}"
|
||||
)
|
||||
sandbox_setup_bin_provided="true"
|
||||
shift 2
|
||||
;;
|
||||
--target-suffixed-entrypoint)
|
||||
target_suffixed_entrypoint="true"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected argument: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$target" || -z "$bundle" || -z "$entrypoint_dir" || -z "$archive_dir" ]]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$bundle" in
|
||||
primary)
|
||||
variant="codex"
|
||||
entrypoint="codex"
|
||||
archive_stem="codex-package"
|
||||
;;
|
||||
app-server)
|
||||
variant="codex-app-server"
|
||||
entrypoint="codex-app-server"
|
||||
archive_stem="codex-app-server-package"
|
||||
;;
|
||||
*)
|
||||
echo "No Codex package variant for bundle: $bundle" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exe_suffix=""
|
||||
case "$target" in
|
||||
*windows*)
|
||||
exe_suffix=".exe"
|
||||
;;
|
||||
esac
|
||||
|
||||
entrypoint_name="$entrypoint"
|
||||
if [[ "$target_suffixed_entrypoint" == "true" ]]; then
|
||||
entrypoint_name="${entrypoint_name}-${target}"
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
*linux*)
|
||||
bwrap_bin="${entrypoint_dir%/}/bwrap"
|
||||
if [[ "$bwrap_bin_provided" == "false" && -f "$bwrap_bin" ]]; then
|
||||
resource_args+=(--bwrap-bin "$bwrap_bin")
|
||||
fi
|
||||
;;
|
||||
*windows*)
|
||||
command_runner_bin="${entrypoint_dir%/}/codex-command-runner.exe"
|
||||
sandbox_setup_bin="${entrypoint_dir%/}/codex-windows-sandbox-setup.exe"
|
||||
if [[ "$command_runner_bin_provided" == "false" && -f "$command_runner_bin" ]]; then
|
||||
resource_args+=(--codex-command-runner-bin "$command_runner_bin")
|
||||
fi
|
||||
if [[ "$sandbox_setup_bin_provided" == "false" && -f "$sandbox_setup_bin" ]]; then
|
||||
resource_args+=(--codex-windows-sandbox-setup-bin "$sandbox_setup_bin")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
repo_root="${GITHUB_WORKSPACE:-}"
|
||||
if [[ -z "$repo_root" ]]; then
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
fi
|
||||
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python_bin="python3"
|
||||
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}"
|
||||
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_args=(
|
||||
"${repo_root}/scripts/build_codex_package.py"
|
||||
--target "$target"
|
||||
--variant "$variant"
|
||||
--entrypoint-bin "${entrypoint_dir%/}/${entrypoint_name}${exe_suffix}"
|
||||
--cargo-profile release
|
||||
--package-dir "$package_dir"
|
||||
--archive-output "$gzip_archive_path"
|
||||
--archive-output "$zstd_archive_path"
|
||||
)
|
||||
if ((${#resource_args[@]} > 0)); then
|
||||
python_args+=("${resource_args[@]}")
|
||||
fi
|
||||
python_args+=(--force)
|
||||
|
||||
"$python_bin" "${python_args[@]}"
|
||||
61
reference/openai-codex/.github/scripts/build-zsh-release-artifact.sh
vendored
Executable file
61
reference/openai-codex/.github/scripts/build-zsh-release-artifact.sh
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$#" -ne 1 ]]; then
|
||||
echo "usage: $0 <archive-path>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
archive_path="$1"
|
||||
workspace="${GITHUB_WORKSPACE:?missing GITHUB_WORKSPACE}"
|
||||
zsh_commit="${ZSH_COMMIT:?missing ZSH_COMMIT}"
|
||||
zsh_patch="${ZSH_PATCH:?missing ZSH_PATCH}"
|
||||
temp_root="${RUNNER_TEMP:-/tmp}"
|
||||
work_root="$(mktemp -d "${temp_root%/}/codex-zsh-release.XXXXXX")"
|
||||
trap 'rm -rf "$work_root"' EXIT
|
||||
|
||||
source_root="${work_root}/zsh"
|
||||
package_root="${work_root}/codex-zsh"
|
||||
wrapper_path="${work_root}/exec-wrapper"
|
||||
stdout_path="${work_root}/stdout.txt"
|
||||
wrapper_log_path="${work_root}/wrapper.log"
|
||||
|
||||
git clone https://git.code.sf.net/p/zsh/code "$source_root"
|
||||
cd "$source_root"
|
||||
git checkout "$zsh_commit"
|
||||
git apply "${workspace}/${zsh_patch}"
|
||||
./Util/preconfig
|
||||
./configure
|
||||
|
||||
cores="$(command -v nproc >/dev/null 2>&1 && nproc || getconf _NPROCESSORS_ONLN)"
|
||||
make -j"${cores}"
|
||||
|
||||
cat > "$wrapper_path" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
: "${CODEX_WRAPPER_LOG:?missing CODEX_WRAPPER_LOG}"
|
||||
printf '%s\n' "$@" > "$CODEX_WRAPPER_LOG"
|
||||
file="$1"
|
||||
shift
|
||||
if [[ "$#" -eq 0 ]]; then
|
||||
exec "$file"
|
||||
fi
|
||||
arg0="$1"
|
||||
shift
|
||||
exec -a "$arg0" "$file" "$@"
|
||||
EOF
|
||||
chmod +x "$wrapper_path"
|
||||
|
||||
CODEX_WRAPPER_LOG="$wrapper_log_path" \
|
||||
EXEC_WRAPPER="$wrapper_path" \
|
||||
"${source_root}/Src/zsh" -fc '/bin/echo smoke-zsh' > "$stdout_path"
|
||||
|
||||
grep -Fx "smoke-zsh" "$stdout_path"
|
||||
grep -Fx "/bin/echo" "$wrapper_log_path"
|
||||
|
||||
mkdir -p "$package_root/bin" "$(dirname "${workspace}/${archive_path}")"
|
||||
cp "${source_root}/Src/zsh" "$package_root/bin/zsh"
|
||||
chmod +x "$package_root/bin/zsh"
|
||||
|
||||
(cd "$work_root" && tar -czf "${workspace}/${archive_path}" codex-zsh)
|
||||
113
reference/openai-codex/.github/scripts/compute-bazel-windows-path.ps1
vendored
Normal file
113
reference/openai-codex/.github/scripts/compute-bazel-windows-path.ps1
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
<#
|
||||
BuildBuddy cache keys include the action and test environment, so Bazel should
|
||||
not inherit the full hosted-runner PATH on Windows. That PATH includes volatile
|
||||
tool entries, such as Maven, that can change independently of this repo and
|
||||
cause avoidable cache misses.
|
||||
|
||||
This script derives a smaller, cache-stable PATH that keeps the Windows
|
||||
toolchain entries Bazel-backed CI tasks need: MSVC and Windows SDK paths,
|
||||
MinGW runtime DLL paths for gnullvm-built tests, Git, PowerShell, Node, Python,
|
||||
DotSlash, and the standard Windows system directories.
|
||||
`setup-bazel-ci` runs this after exporting the MSVC environment, and the script
|
||||
publishes the result via `GITHUB_ENV` as `CODEX_BAZEL_WINDOWS_PATH` so later
|
||||
steps can pass that explicit PATH to Bazel.
|
||||
#>
|
||||
|
||||
$stablePathEntries = New-Object System.Collections.Generic.List[string]
|
||||
$seenEntries = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$windowsAppsPath = if ([string]::IsNullOrWhiteSpace($env:LOCALAPPDATA)) {
|
||||
$null
|
||||
} else {
|
||||
"$($env:LOCALAPPDATA)\Microsoft\WindowsApps"
|
||||
}
|
||||
$windowsDir = if ($env:WINDIR) {
|
||||
$env:WINDIR
|
||||
} elseif ($env:SystemRoot) {
|
||||
$env:SystemRoot
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
function Add-StablePathEntry {
|
||||
param([string]$PathEntry)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($PathEntry)) {
|
||||
return
|
||||
}
|
||||
|
||||
if ($seenEntries.Add($PathEntry)) {
|
||||
[void]$stablePathEntries.Add($PathEntry)
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pathEntry in ($env:PATH -split ';')) {
|
||||
if ([string]::IsNullOrWhiteSpace($pathEntry)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
$pathEntry -like '*Microsoft Visual Studio*' -or
|
||||
$pathEntry -like '*Windows Kits*' -or
|
||||
$pathEntry -like '*Microsoft SDKs*' -or
|
||||
$pathEntry -eq 'C:\mingw64\bin' -or
|
||||
$pathEntry -like 'C:\msys64\*\bin' -or
|
||||
$pathEntry -like 'C:\Program Files\Git\*' -or
|
||||
$pathEntry -like 'C:\Program Files\PowerShell\*' -or
|
||||
$pathEntry -like 'C:\hostedtoolcache\windows\node\*' -or
|
||||
$pathEntry -like 'C:\hostedtoolcache\windows\Python\*' -or
|
||||
$pathEntry -eq 'D:\a\_temp\install-dotslash\bin' -or
|
||||
($windowsDir -and ($pathEntry -eq $windowsDir -or $pathEntry -like "${windowsDir}\*"))
|
||||
) {
|
||||
Add-StablePathEntry $pathEntry
|
||||
}
|
||||
}
|
||||
|
||||
$gitCommand = Get-Command git -ErrorAction SilentlyContinue
|
||||
if ($gitCommand) {
|
||||
Add-StablePathEntry (Split-Path $gitCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$nodeCommand = Get-Command node -ErrorAction SilentlyContinue
|
||||
if ($nodeCommand) {
|
||||
Add-StablePathEntry (Split-Path $nodeCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$python3Command = Get-Command python3 -ErrorAction SilentlyContinue
|
||||
if ($python3Command) {
|
||||
Add-StablePathEntry (Split-Path $python3Command.Source -Parent)
|
||||
}
|
||||
|
||||
$pythonCommand = Get-Command python -ErrorAction SilentlyContinue
|
||||
if ($pythonCommand) {
|
||||
Add-StablePathEntry (Split-Path $pythonCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$pwshCommand = Get-Command pwsh -ErrorAction SilentlyContinue
|
||||
if ($pwshCommand) {
|
||||
Add-StablePathEntry (Split-Path $pwshCommand.Source -Parent)
|
||||
}
|
||||
|
||||
foreach ($mingwPath in @('C:\mingw64\bin', 'C:\msys64\mingw64\bin', 'C:\msys64\ucrt64\bin')) {
|
||||
if (Test-Path $mingwPath) {
|
||||
Add-StablePathEntry $mingwPath
|
||||
}
|
||||
}
|
||||
|
||||
if ($windowsAppsPath) {
|
||||
Add-StablePathEntry $windowsAppsPath
|
||||
}
|
||||
|
||||
if ($stablePathEntries.Count -eq 0) {
|
||||
throw 'Failed to derive cache-stable Windows PATH.'
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($env:GITHUB_ENV)) {
|
||||
throw 'GITHUB_ENV must be set.'
|
||||
}
|
||||
|
||||
$stablePath = $stablePathEntries -join ';'
|
||||
Write-Host 'Derived CODEX_BAZEL_WINDOWS_PATH entries:'
|
||||
foreach ($pathEntry in $stablePathEntries) {
|
||||
Write-Host " $pathEntry"
|
||||
}
|
||||
"CODEX_BAZEL_WINDOWS_PATH=$stablePath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
279
reference/openai-codex/.github/scripts/install-musl-build-tools.sh
vendored
Normal file
279
reference/openai-codex/.github/scripts/install-musl-build-tools.sh
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
: "${TARGET:?TARGET environment variable is required}"
|
||||
: "${GITHUB_ENV:?GITHUB_ENV environment variable is required}"
|
||||
|
||||
apt_update_args=()
|
||||
if [[ -n "${APT_UPDATE_ARGS:-}" ]]; then
|
||||
# shellcheck disable=SC2206
|
||||
apt_update_args=(${APT_UPDATE_ARGS})
|
||||
fi
|
||||
|
||||
apt_install_args=()
|
||||
if [[ -n "${APT_INSTALL_ARGS:-}" ]]; then
|
||||
# shellcheck disable=SC2206
|
||||
apt_install_args=(${APT_INSTALL_ARGS})
|
||||
fi
|
||||
|
||||
sudo apt-get update "${apt_update_args[@]}"
|
||||
sudo apt-get install -y "${apt_install_args[@]}" ca-certificates curl musl-tools pkg-config libcap-dev g++ clang libc++-dev libc++abi-dev lld xz-utils
|
||||
|
||||
case "${TARGET}" in
|
||||
x86_64-unknown-linux-musl)
|
||||
arch="x86_64"
|
||||
;;
|
||||
aarch64-unknown-linux-musl)
|
||||
arch="aarch64"
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected musl target: ${TARGET}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
libcap_version="2.75"
|
||||
libcap_sha256="de4e7e064c9ba451d5234dd46e897d7c71c96a9ebf9a0c445bc04f4742d83632"
|
||||
libcap_tarball_name="libcap-${libcap_version}.tar.xz"
|
||||
libcap_download_url="https://mirrors.edge.kernel.org/pub/linux/libs/security/linux-privs/libcap2/${libcap_tarball_name}"
|
||||
|
||||
# Use the musl toolchain as the Rust linker to avoid Zig injecting its own CRT.
|
||||
if command -v "${arch}-linux-musl-gcc" >/dev/null; then
|
||||
musl_linker="$(command -v "${arch}-linux-musl-gcc")"
|
||||
elif command -v musl-gcc >/dev/null; then
|
||||
musl_linker="$(command -v musl-gcc)"
|
||||
else
|
||||
echo "musl gcc not found after install; arch=${arch}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
zig_target="${TARGET/-unknown-linux-musl/-linux-musl}"
|
||||
runner_temp="${RUNNER_TEMP:-/tmp}"
|
||||
tool_root="${runner_temp}/codex-musl-tools-${TARGET}"
|
||||
mkdir -p "${tool_root}"
|
||||
|
||||
libcap_root="${tool_root}/libcap-${libcap_version}"
|
||||
libcap_src_root="${libcap_root}/src"
|
||||
libcap_prefix="${libcap_root}/prefix"
|
||||
libcap_pkgconfig_dir="${libcap_prefix}/lib/pkgconfig"
|
||||
|
||||
if [[ ! -f "${libcap_prefix}/lib/libcap.a" ]]; then
|
||||
mkdir -p "${libcap_src_root}" "${libcap_prefix}/lib" "${libcap_prefix}/include/sys" "${libcap_prefix}/include/linux" "${libcap_pkgconfig_dir}"
|
||||
libcap_tarball="${libcap_root}/${libcap_tarball_name}"
|
||||
|
||||
curl -fsSL "${libcap_download_url}" -o "${libcap_tarball}"
|
||||
echo "${libcap_sha256} ${libcap_tarball}" | sha256sum -c -
|
||||
|
||||
tar -xJf "${libcap_tarball}" -C "${libcap_src_root}"
|
||||
libcap_source_dir="${libcap_src_root}/libcap-${libcap_version}"
|
||||
make -C "${libcap_source_dir}/libcap" -j"$(nproc)" \
|
||||
CC="${musl_linker}" \
|
||||
AR=ar \
|
||||
RANLIB=ranlib
|
||||
|
||||
cp "${libcap_source_dir}/libcap/libcap.a" "${libcap_prefix}/lib/libcap.a"
|
||||
cp "${libcap_source_dir}/libcap/include/uapi/linux/capability.h" "${libcap_prefix}/include/linux/capability.h"
|
||||
cp "${libcap_source_dir}/libcap/../libcap/include/sys/capability.h" "${libcap_prefix}/include/sys/capability.h"
|
||||
|
||||
cat > "${libcap_pkgconfig_dir}/libcap.pc" <<EOF
|
||||
prefix=${libcap_prefix}
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${prefix}/lib
|
||||
includedir=\${prefix}/include
|
||||
|
||||
Name: libcap
|
||||
Description: Linux capabilities
|
||||
Version: ${libcap_version}
|
||||
Libs: -L\${libdir} -lcap
|
||||
Cflags: -I\${includedir}
|
||||
EOF
|
||||
fi
|
||||
|
||||
sysroot=""
|
||||
if command -v zig >/dev/null; then
|
||||
zig_bin="$(command -v zig)"
|
||||
cc="${tool_root}/zigcc"
|
||||
cxx="${tool_root}/zigcxx"
|
||||
|
||||
cat >"${cc}" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
args=()
|
||||
skip_next=0
|
||||
pending_include=0
|
||||
for arg in "\$@"; do
|
||||
if [[ "\${pending_include}" -eq 1 ]]; then
|
||||
pending_include=0
|
||||
if [[ "\${arg}" == /usr/include || "\${arg}" == /usr/include/* ]]; then
|
||||
# Keep host-only headers available, but after the target sysroot headers.
|
||||
args+=("-idirafter" "\${arg}")
|
||||
else
|
||||
args+=("-I" "\${arg}")
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "\${skip_next}" -eq 1 ]]; then
|
||||
skip_next=0
|
||||
continue
|
||||
fi
|
||||
case "\${arg}" in
|
||||
--target)
|
||||
skip_next=1
|
||||
continue
|
||||
;;
|
||||
--target=*|-target=*|-target)
|
||||
# Drop any explicit --target/-target flags. Zig expects -target and
|
||||
# rejects Rust triples like *-unknown-linux-musl.
|
||||
if [[ "\${arg}" == "-target" ]]; then
|
||||
skip_next=1
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
-I)
|
||||
pending_include=1
|
||||
continue
|
||||
;;
|
||||
-I/usr/include|-I/usr/include/*)
|
||||
# Avoid making glibc headers win over musl headers.
|
||||
args+=("-idirafter" "\${arg#-I}")
|
||||
continue
|
||||
;;
|
||||
-Wp,-U_FORTIFY_SOURCE)
|
||||
# aws-lc-sys emits this GCC preprocessor forwarding form in debug
|
||||
# builds, but zig cc expects the define flag directly.
|
||||
args+=("-U_FORTIFY_SOURCE")
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
args+=("\${arg}")
|
||||
done
|
||||
|
||||
exec "${zig_bin}" cc -target "${zig_target}" "\${args[@]}"
|
||||
EOF
|
||||
cat >"${cxx}" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
args=()
|
||||
skip_next=0
|
||||
pending_include=0
|
||||
for arg in "\$@"; do
|
||||
if [[ "\${pending_include}" -eq 1 ]]; then
|
||||
pending_include=0
|
||||
if [[ "\${arg}" == /usr/include || "\${arg}" == /usr/include/* ]]; then
|
||||
# Keep host-only headers available, but after the target sysroot headers.
|
||||
args+=("-idirafter" "\${arg}")
|
||||
else
|
||||
args+=("-I" "\${arg}")
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "\${skip_next}" -eq 1 ]]; then
|
||||
skip_next=0
|
||||
continue
|
||||
fi
|
||||
case "\${arg}" in
|
||||
--target)
|
||||
# Drop explicit --target and its value: we always pass zig's -target below.
|
||||
skip_next=1
|
||||
continue
|
||||
;;
|
||||
--target=*|-target=*|-target)
|
||||
# Zig expects -target and rejects Rust triples like *-unknown-linux-musl.
|
||||
if [[ "\${arg}" == "-target" ]]; then
|
||||
skip_next=1
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
-I)
|
||||
pending_include=1
|
||||
continue
|
||||
;;
|
||||
-I/usr/include|-I/usr/include/*)
|
||||
# Avoid making glibc headers win over musl headers.
|
||||
args+=("-idirafter" "\${arg#-I}")
|
||||
continue
|
||||
;;
|
||||
-Wp,-U_FORTIFY_SOURCE)
|
||||
# aws-lc-sys emits this GCC forwarding form in debug builds; zig c++
|
||||
# expects the define flag directly.
|
||||
args+=("-U_FORTIFY_SOURCE")
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
args+=("\${arg}")
|
||||
done
|
||||
|
||||
exec "${zig_bin}" c++ -target "${zig_target}" "\${args[@]}"
|
||||
EOF
|
||||
chmod +x "${cc}" "${cxx}"
|
||||
|
||||
sysroot="$("${zig_bin}" cc -target "${zig_target}" -print-sysroot 2>/dev/null || true)"
|
||||
else
|
||||
cc="${musl_linker}"
|
||||
|
||||
if command -v "${arch}-linux-musl-g++" >/dev/null; then
|
||||
cxx="$(command -v "${arch}-linux-musl-g++")"
|
||||
elif command -v musl-g++ >/dev/null; then
|
||||
cxx="$(command -v musl-g++)"
|
||||
else
|
||||
cxx="${cc}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${sysroot}" && "${sysroot}" != "/" ]]; then
|
||||
echo "BORING_BSSL_SYSROOT=${sysroot}" >> "$GITHUB_ENV"
|
||||
boring_sysroot_var="BORING_BSSL_SYSROOT_${TARGET}"
|
||||
boring_sysroot_var="${boring_sysroot_var//-/_}"
|
||||
echo "${boring_sysroot_var}=${sysroot}" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
cflags="-pthread"
|
||||
cxxflags="-pthread"
|
||||
if [[ "${TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||
# BoringSSL enables -Wframe-larger-than=25344 under clang and treats warnings as errors.
|
||||
cflags="${cflags} -Wno-error=frame-larger-than"
|
||||
cxxflags="${cxxflags} -Wno-error=frame-larger-than"
|
||||
fi
|
||||
|
||||
echo "CFLAGS=${cflags}" >> "$GITHUB_ENV"
|
||||
echo "CXXFLAGS=${cxxflags}" >> "$GITHUB_ENV"
|
||||
echo "CC=${cc}" >> "$GITHUB_ENV"
|
||||
echo "TARGET_CC=${cc}" >> "$GITHUB_ENV"
|
||||
target_cc_var="CC_${TARGET}"
|
||||
target_cc_var="${target_cc_var//-/_}"
|
||||
echo "${target_cc_var}=${cc}" >> "$GITHUB_ENV"
|
||||
echo "CXX=${cxx}" >> "$GITHUB_ENV"
|
||||
echo "TARGET_CXX=${cxx}" >> "$GITHUB_ENV"
|
||||
target_cxx_var="CXX_${TARGET}"
|
||||
target_cxx_var="${target_cxx_var//-/_}"
|
||||
echo "${target_cxx_var}=${cxx}" >> "$GITHUB_ENV"
|
||||
|
||||
cargo_linker_var="CARGO_TARGET_${TARGET^^}_LINKER"
|
||||
cargo_linker_var="${cargo_linker_var//-/_}"
|
||||
echo "${cargo_linker_var}=${musl_linker}" >> "$GITHUB_ENV"
|
||||
|
||||
echo "CMAKE_C_COMPILER=${cc}" >> "$GITHUB_ENV"
|
||||
echo "CMAKE_CXX_COMPILER=${cxx}" >> "$GITHUB_ENV"
|
||||
echo "CMAKE_ARGS=-DCMAKE_HAVE_THREADS_LIBRARY=1 -DCMAKE_USE_PTHREADS_INIT=1 -DCMAKE_THREAD_LIBS_INIT=-pthread -DTHREADS_PREFER_PTHREAD_FLAG=ON" >> "$GITHUB_ENV"
|
||||
|
||||
# Allow pkg-config resolution during cross-compilation.
|
||||
echo "PKG_CONFIG_ALLOW_CROSS=1" >> "$GITHUB_ENV"
|
||||
pkg_config_path="${libcap_pkgconfig_dir}"
|
||||
if [[ -n "${PKG_CONFIG_PATH:-}" ]]; then
|
||||
pkg_config_path="${pkg_config_path}:${PKG_CONFIG_PATH}"
|
||||
fi
|
||||
echo "PKG_CONFIG_PATH=${pkg_config_path}" >> "$GITHUB_ENV"
|
||||
pkg_config_path_var="PKG_CONFIG_PATH_${TARGET}"
|
||||
pkg_config_path_var="${pkg_config_path_var//-/_}"
|
||||
echo "${pkg_config_path_var}=${libcap_pkgconfig_dir}" >> "$GITHUB_ENV"
|
||||
|
||||
if [[ -n "${sysroot}" && "${sysroot}" != "/" ]]; then
|
||||
echo "PKG_CONFIG_SYSROOT_DIR=${sysroot}" >> "$GITHUB_ENV"
|
||||
pkg_config_sysroot_var="PKG_CONFIG_SYSROOT_DIR_${TARGET}"
|
||||
pkg_config_sysroot_var="${pkg_config_sysroot_var//-/_}"
|
||||
echo "${pkg_config_sysroot_var}=${sysroot}" >> "$GITHUB_ENV"
|
||||
fi
|
||||
80
reference/openai-codex/.github/scripts/run-argument-comment-lint-bazel.sh
vendored
Executable file
80
reference/openai-codex/.github/scripts/run-argument-comment-lint-bazel.sh
vendored
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
bazel_lint_args=("$@")
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
has_host_platform_override=0
|
||||
for arg in "${bazel_lint_args[@]}"; do
|
||||
if [[ "$arg" == --host_platform=* ]]; then
|
||||
has_host_platform_override=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $has_host_platform_override -eq 0 ]]; then
|
||||
# The nightly Windows lint toolchain is registered with an MSVC exec
|
||||
# platform even though the lint target platform stays on `windows-gnullvm`.
|
||||
# Override the host platform here so the exec-side helper binaries actually
|
||||
# match the registered toolchain set.
|
||||
bazel_lint_args+=("--host_platform=//:local_windows_msvc")
|
||||
fi
|
||||
|
||||
# Native Windows lint runs need exec-side Rust helper binaries and proc-macros
|
||||
# to use rust-lld instead of the C++ linker path. The default `none`
|
||||
# preference resolves to `cc` when a cc_toolchain is present, which currently
|
||||
# routes these exec actions through clang++ with an argument shape it cannot
|
||||
# consume.
|
||||
bazel_lint_args+=("--@rules_rust//rust/settings:toolchain_linker_preference=rust")
|
||||
|
||||
# Some Rust top-level targets are still intentionally incompatible with the
|
||||
# local Windows MSVC exec platform. Skip those explicit targets so the native
|
||||
# lint aspect can run across the compatible crate graph instead of failing the
|
||||
# whole build after analysis.
|
||||
bazel_lint_args+=("--skip_incompatible_explicit_targets")
|
||||
fi
|
||||
|
||||
read_query_labels() {
|
||||
local query="$1"
|
||||
local query_stdout
|
||||
local query_stderr
|
||||
query_stdout="$(mktemp)"
|
||||
query_stderr="$(mktemp)"
|
||||
|
||||
if ! ./.github/scripts/run-bazel-query-ci.sh \
|
||||
--keep_going \
|
||||
--output=label \
|
||||
-- "$query" >"$query_stdout" 2>"$query_stderr"; then
|
||||
cat "$query_stderr" >&2
|
||||
rm -f "$query_stdout" "$query_stderr"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "$query_stdout"
|
||||
rm -f "$query_stdout" "$query_stderr"
|
||||
}
|
||||
|
||||
final_build_targets=(//codex-rs/...)
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
# Bazel's local Windows platform currently lacks a default test toolchain for
|
||||
# `rust_test`, so target the concrete Rust crate rules directly. The lint
|
||||
# aspect still walks their crate graph, which preserves incremental reuse for
|
||||
# non-test code while avoiding non-Rust wrapper targets such as platform_data.
|
||||
final_build_targets=()
|
||||
while IFS= read -r label; do
|
||||
[[ -n "$label" ]] || continue
|
||||
final_build_targets+=("$label")
|
||||
done < <(read_query_labels 'kind("rust_(library|binary|proc_macro) rule", //codex-rs/...)')
|
||||
|
||||
if [[ ${#final_build_targets[@]} -eq 0 ]]; then
|
||||
echo "Failed to discover Windows Bazel lint targets." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
-- \
|
||||
build \
|
||||
"${bazel_lint_args[@]}" \
|
||||
-- \
|
||||
"${final_build_targets[@]}"
|
||||
453
reference/openai-codex/.github/scripts/run-bazel-ci.sh
vendored
Executable file
453
reference/openai-codex/.github/scripts/run-bazel-ci.sh
vendored
Executable file
@@ -0,0 +1,453 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
print_failed_bazel_test_logs=0
|
||||
print_failed_bazel_action_summary=0
|
||||
remote_download_toplevel=0
|
||||
windows_msvc_host_platform=0
|
||||
windows_cross_compile=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--print-failed-test-logs)
|
||||
print_failed_bazel_test_logs=1
|
||||
shift
|
||||
;;
|
||||
--print-failed-action-summary)
|
||||
print_failed_bazel_action_summary=1
|
||||
shift
|
||||
;;
|
||||
--remote-download-toplevel)
|
||||
remote_download_toplevel=1
|
||||
shift
|
||||
;;
|
||||
--windows-msvc-host-platform)
|
||||
windows_msvc_host_platform=1
|
||||
shift
|
||||
;;
|
||||
--windows-cross-compile)
|
||||
windows_cross_compile=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "Usage: $0 [--print-failed-test-logs] [--print-failed-action-summary] [--remote-download-toplevel] [--windows-msvc-host-platform] [--windows-cross-compile] -- <bazel args> -- <targets>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bazel_startup_args=()
|
||||
if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then
|
||||
bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
|
||||
fi
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' bazel "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
bazel "$@"
|
||||
}
|
||||
|
||||
ci_config=ci-linux
|
||||
case "${RUNNER_OS:-}" in
|
||||
macOS)
|
||||
ci_config=ci-macos
|
||||
;;
|
||||
Windows)
|
||||
if [[ $windows_cross_compile -eq 1 ]]; then
|
||||
ci_config=ci-windows-cross
|
||||
else
|
||||
ci_config=ci-windows
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
print_bazel_test_log_tails() {
|
||||
local console_log="$1"
|
||||
local testlogs_dir
|
||||
local -a bazel_info_cmd=(bazel)
|
||||
local -a bazel_info_args=(info)
|
||||
|
||||
if (( ${#bazel_startup_args[@]} > 0 )); then
|
||||
bazel_info_cmd+=("${bazel_startup_args[@]}")
|
||||
fi
|
||||
|
||||
# `bazel info` needs the same CI config as the failed test invocation so
|
||||
# platform-specific output roots match. On Windows, omitting `ci-windows`
|
||||
# would point at `local_windows-fastbuild` even when the test ran with the
|
||||
# MSVC host platform under `local_windows_msvc-fastbuild`.
|
||||
if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
bazel_info_args+=(
|
||||
"--config=${ci_config}"
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
)
|
||||
fi
|
||||
# Only pass flags that affect Bazel's output-root selection or repository
|
||||
# lookup. Test/build-only flags such as execution logs or remote download
|
||||
# mode can make `bazel info` fail, which would hide the real test log path.
|
||||
for arg in "${post_config_bazel_args[@]}"; do
|
||||
case "$arg" in
|
||||
--host_platform=* | --repo_contents_cache=* | --repository_cache=*)
|
||||
bazel_info_args+=("$arg")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
testlogs_dir="$(run_bazel "${bazel_info_cmd[@]:1}" \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
"${bazel_info_args[@]}" \
|
||||
bazel-testlogs 2>/dev/null || echo bazel-testlogs)"
|
||||
|
||||
local failed_targets=()
|
||||
while IFS= read -r target; do
|
||||
failed_targets+=("$target")
|
||||
done < <(
|
||||
grep -E '^(FAIL: //|ERROR: .* Testing //)' "$console_log" \
|
||||
| sed -E 's#^FAIL: (//[^ ]+).*#\1#; s#^ERROR: .* Testing (//[^ ]+) failed:.*#\1#' \
|
||||
| sort -u
|
||||
)
|
||||
|
||||
if [[ ${#failed_targets[@]} -eq 0 ]]; then
|
||||
echo "No failed Bazel test targets were found in console output."
|
||||
return
|
||||
fi
|
||||
|
||||
for target in "${failed_targets[@]}"; do
|
||||
local rel_path="${target#//}"
|
||||
rel_path="${rel_path/://}"
|
||||
local test_log="${testlogs_dir}/${rel_path}/test.log"
|
||||
local reported_test_log
|
||||
reported_test_log="$(grep -F "FAIL: ${target} " "$console_log" | sed -nE 's#.* \(see (.*[\\/]test\.log)\).*#\1#p' | head -n 1 || true)"
|
||||
if [[ -n "$reported_test_log" ]]; then
|
||||
reported_test_log="${reported_test_log//\\//}"
|
||||
test_log="$reported_test_log"
|
||||
fi
|
||||
|
||||
echo "::group::Bazel test log tail for ${target}"
|
||||
if [[ -f "$test_log" ]]; then
|
||||
tail -n 200 "$test_log"
|
||||
else
|
||||
echo "Missing test log: $test_log"
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
done
|
||||
}
|
||||
|
||||
print_bazel_action_failure_summary() {
|
||||
local console_log="$1"
|
||||
local escaped_summary
|
||||
local summary
|
||||
|
||||
summary="$(
|
||||
awk '
|
||||
function clean(line) {
|
||||
gsub(sprintf("%c", 27) "\\[[0-9;]*m", "", line)
|
||||
sub(/^.*\t[^\t]*\t[0-9TZ:._-]+ /, "", line)
|
||||
return line
|
||||
}
|
||||
|
||||
function is_diagnostic(line) {
|
||||
return line ~ /^(error(\[[^]]+\])?:|warning:|note:|help:)/ ||
|
||||
line ~ /^[[:space:]]+-->/ ||
|
||||
line ~ /^[[:space:]]*[0-9]+[[:space:]]+\|/ ||
|
||||
line ~ /^[[:space:]]*\|/ ||
|
||||
line ~ /^[[:space:]]+= (note|help):/ ||
|
||||
line ~ /^[[:space:]]*\^[[:space:]^~-]*$/ ||
|
||||
line ~ /^For more information/ ||
|
||||
line ~ /^error: aborting/
|
||||
}
|
||||
|
||||
{
|
||||
line = clean($0)
|
||||
}
|
||||
|
||||
line ~ /^ERROR: .* failed:/ {
|
||||
if (printed) {
|
||||
print ""
|
||||
}
|
||||
print line
|
||||
in_failure = 1
|
||||
seen_diagnostic = 0
|
||||
printed = 1
|
||||
next
|
||||
}
|
||||
|
||||
in_failure && is_diagnostic(line) {
|
||||
print line
|
||||
seen_diagnostic = 1
|
||||
next
|
||||
}
|
||||
|
||||
in_failure && seen_diagnostic && line == "" {
|
||||
print ""
|
||||
next
|
||||
}
|
||||
|
||||
in_failure && seen_diagnostic {
|
||||
in_failure = 0
|
||||
seen_diagnostic = 0
|
||||
next
|
||||
}
|
||||
' "$console_log"
|
||||
)"
|
||||
|
||||
if [[ -z "$summary" ]]; then
|
||||
summary="$(grep -E '^ERROR: |^FAILED: ' "$console_log" | tail -n 50 || true)"
|
||||
fi
|
||||
|
||||
if [[ -z "$summary" ]]; then
|
||||
echo "No Bazel action failures were found in the captured console output."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
|
||||
escaped_summary="$(
|
||||
printf '%s' "$summary" \
|
||||
| awk 'BEGIN { ORS = "" } {
|
||||
gsub(/%/, "%25")
|
||||
gsub(/\r/, "%0D")
|
||||
print sep $0
|
||||
sep = "%0A"
|
||||
}'
|
||||
)"
|
||||
echo "::error title=Bazel failed action diagnostics::${escaped_summary}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Bazel failed action diagnostics:"
|
||||
echo "--------------------------------"
|
||||
printf '%s\n' "$summary"
|
||||
echo "--------------------------------"
|
||||
}
|
||||
|
||||
bazel_args=()
|
||||
bazel_targets=()
|
||||
found_target_separator=0
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--" && $found_target_separator -eq 0 ]]; then
|
||||
found_target_separator=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $found_target_separator -eq 0 ]]; then
|
||||
bazel_args+=("$arg")
|
||||
else
|
||||
bazel_targets+=("$arg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#bazel_args[@]} -eq 0 || ${#bazel_targets[@]} -eq 0 ]]; then
|
||||
echo "Expected Bazel args and targets separated by --" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_cross_compile -eq 1 && -z "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
# Fork PRs do not receive the BuildBuddy secret needed for the remote
|
||||
# cross-compile config. Preserve the previous local Windows build shape.
|
||||
windows_msvc_host_platform=1
|
||||
fi
|
||||
|
||||
post_config_bazel_args=()
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_msvc_host_platform -eq 1 ]]; then
|
||||
has_host_platform_override=0
|
||||
for arg in "${bazel_args[@]}"; do
|
||||
if [[ "$arg" == --host_platform=* ]]; then
|
||||
has_host_platform_override=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $has_host_platform_override -eq 0 ]]; then
|
||||
# Use the MSVC Windows platform for jobs that need helper binaries like
|
||||
# Rust test wrappers and V8 generators to resolve a compatible toolchain.
|
||||
# Callers that need a different Windows target platform should pass an
|
||||
# explicit `--platforms=...` flag.
|
||||
post_config_bazel_args+=("--host_platform=//:local_windows_msvc")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $remote_download_toplevel -eq 1 ]]; then
|
||||
# Override the CI config's remote_download_minimal setting when callers need
|
||||
# the built artifact to exist on disk after the command completes.
|
||||
post_config_bazel_args+=(--remote_download_toplevel)
|
||||
fi
|
||||
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_cross_compile -eq 1 && -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
# `--enable_platform_specific_config` expands `common:windows` on Windows
|
||||
# hosts after ordinary rc configs, which can override `ci-windows-cross`'s
|
||||
# RBE host platform. Repeat the host platform on the command line so V8 and
|
||||
# other genrules execute on Linux RBE workers instead of Git Bash locally.
|
||||
#
|
||||
# Bazel also derives the default genrule shell from the client host. Without
|
||||
# an explicit shell executable, remote Linux actions can be asked to run
|
||||
# `C:\Program Files\Git\usr\bin\bash.exe`.
|
||||
post_config_bazel_args+=(--host_platform=//:rbe --shell_executable=/bin/bash)
|
||||
fi
|
||||
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_cross_compile -eq 1 && -z "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
# The Windows cross-compile config depends on remote execution. Fork PRs do
|
||||
# not receive the BuildBuddy secret, so fall back to the existing local build
|
||||
# shape and keep its lower concurrency cap.
|
||||
post_config_bazel_args+=(--jobs=8)
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPO_CONTENTS_CACHE:-}" ]]; then
|
||||
# Windows self-hosted runners can run multiple Bazel jobs concurrently. Give
|
||||
# each job its own repo contents cache so they do not fight over the shared
|
||||
# path configured in `ci-windows`.
|
||||
post_config_bazel_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}")
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then
|
||||
post_config_bazel_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}")
|
||||
fi
|
||||
|
||||
if [[ -n "${CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR:-}" ]]; then
|
||||
post_config_bazel_args+=(
|
||||
"--execution_log_compact_file=${CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR}/execution-log-${bazel_args[0]}-${GITHUB_JOB:-local}-$$.zst"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
pass_windows_build_env=1
|
||||
if [[ $windows_cross_compile -eq 1 && -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
# Remote build actions execute on Linux RBE workers. Passing the Windows
|
||||
# runner's build environment there makes Bazel genrules try to execute
|
||||
# C:\Program Files\Git\usr\bin\bash.exe on Linux.
|
||||
pass_windows_build_env=0
|
||||
fi
|
||||
|
||||
if [[ $pass_windows_build_env -eq 1 ]]; then
|
||||
windows_action_env_vars=(
|
||||
INCLUDE
|
||||
LIB
|
||||
LIBPATH
|
||||
UCRTVersion
|
||||
UniversalCRTSdkDir
|
||||
VCINSTALLDIR
|
||||
VCToolsInstallDir
|
||||
WindowsLibPath
|
||||
WindowsSdkBinPath
|
||||
WindowsSdkDir
|
||||
WindowsSDKLibVersion
|
||||
WindowsSDKVersion
|
||||
)
|
||||
|
||||
for env_var in "${windows_action_env_vars[@]}"; do
|
||||
if [[ -n "${!env_var:-}" ]]; then
|
||||
post_config_bazel_args+=("--action_env=${env_var}" "--host_action_env=${env_var}")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z "${CODEX_BAZEL_WINDOWS_PATH:-}" ]]; then
|
||||
echo "CODEX_BAZEL_WINDOWS_PATH must be set for Windows Bazel CI." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $pass_windows_build_env -eq 1 ]]; then
|
||||
post_config_bazel_args+=(
|
||||
"--action_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}"
|
||||
"--host_action_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}"
|
||||
)
|
||||
elif [[ $windows_cross_compile -eq 1 ]]; then
|
||||
# Remote build actions run on Linux RBE workers. Give their shell snippets
|
||||
# a Linux PATH while preserving CODEX_BAZEL_WINDOWS_PATH below for local
|
||||
# Windows test execution.
|
||||
post_config_bazel_args+=(
|
||||
"--action_env=PATH=/usr/bin:/bin"
|
||||
"--host_action_env=PATH=/usr/bin:/bin"
|
||||
)
|
||||
fi
|
||||
post_config_bazel_args+=("--test_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}")
|
||||
fi
|
||||
|
||||
bazel_console_log="$(mktemp)"
|
||||
trap 'rm -f "$bazel_console_log"' EXIT
|
||||
|
||||
bazel_cmd=(bazel)
|
||||
if (( ${#bazel_startup_args[@]} > 0 )); then
|
||||
bazel_cmd+=("${bazel_startup_args[@]}")
|
||||
fi
|
||||
|
||||
if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
echo "BuildBuddy API key is available; using remote Bazel configuration."
|
||||
# Work around Bazel 9 remote repo contents cache / overlay materialization failures
|
||||
# seen in CI (for example "is not a symlink" or permission errors while
|
||||
# materializing external repos such as rules_perl). We still use BuildBuddy for
|
||||
# remote execution/cache; this only disables the startup-level repo contents cache.
|
||||
bazel_run_args=(
|
||||
"${bazel_args[@]}"
|
||||
"--config=${ci_config}"
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
)
|
||||
if (( ${#post_config_bazel_args[@]} > 0 )); then
|
||||
bazel_run_args+=("${post_config_bazel_args[@]}")
|
||||
fi
|
||||
set +e
|
||||
run_bazel "${bazel_cmd[@]:1}" \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
"${bazel_run_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}" \
|
||||
2>&1 | tee "$bazel_console_log"
|
||||
bazel_status=${PIPESTATUS[0]}
|
||||
set -e
|
||||
else
|
||||
echo "BuildBuddy API key is not available; using local Bazel configuration."
|
||||
# Keep fork/community PRs on Bazel but disable remote services that are
|
||||
# configured in .bazelrc and require auth.
|
||||
#
|
||||
# Flag docs:
|
||||
# - Command-line reference: https://bazel.build/reference/command-line-reference
|
||||
# - Remote caching overview: https://bazel.build/remote/caching
|
||||
# - Remote execution overview: https://bazel.build/remote/rbe
|
||||
# - Build Event Protocol overview: https://bazel.build/remote/bep
|
||||
#
|
||||
# --noexperimental_remote_repo_contents_cache:
|
||||
# disable remote repo contents cache enabled in .bazelrc startup options.
|
||||
# https://bazel.build/reference/command-line-reference#startup_options-flag--experimental_remote_repo_contents_cache
|
||||
# --remote_cache= and --remote_executor=:
|
||||
# clear remote cache/execution endpoints configured in .bazelrc.
|
||||
# https://bazel.build/reference/command-line-reference#common_options-flag--remote_cache
|
||||
# https://bazel.build/reference/command-line-reference#common_options-flag--remote_executor
|
||||
bazel_run_args=(
|
||||
"${bazel_args[@]}"
|
||||
--remote_cache=
|
||||
--remote_executor=
|
||||
)
|
||||
if (( ${#post_config_bazel_args[@]} > 0 )); then
|
||||
bazel_run_args+=("${post_config_bazel_args[@]}")
|
||||
fi
|
||||
set +e
|
||||
run_bazel "${bazel_cmd[@]:1}" \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
"${bazel_run_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}" \
|
||||
2>&1 | tee "$bazel_console_log"
|
||||
bazel_status=${PIPESTATUS[0]}
|
||||
set -e
|
||||
fi
|
||||
|
||||
if [[ ${bazel_status:-0} -ne 0 ]]; then
|
||||
if [[ $print_failed_bazel_action_summary -eq 1 ]]; then
|
||||
print_bazel_action_failure_summary "$bazel_console_log"
|
||||
fi
|
||||
if [[ $print_failed_bazel_test_logs -eq 1 ]]; then
|
||||
print_bazel_test_log_tails "$bazel_console_log"
|
||||
fi
|
||||
exit "$bazel_status"
|
||||
fi
|
||||
84
reference/openai-codex/.github/scripts/run-bazel-query-ci.sh
vendored
Executable file
84
reference/openai-codex/.github/scripts/run-bazel-query-ci.sh
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Run Bazel queries with the same CI startup settings as the main build/test
|
||||
# invocation so target-discovery queries can reuse the same Bazel server.
|
||||
|
||||
query_args=()
|
||||
windows_cross_compile=0
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--windows-cross-compile)
|
||||
windows_cross_compile=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
query_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $0 [--windows-cross-compile] [<bazel query args>...] -- <query expression>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
query_expression="$1"
|
||||
|
||||
ci_config=ci-linux
|
||||
case "${RUNNER_OS:-}" in
|
||||
macOS)
|
||||
ci_config=ci-macos
|
||||
;;
|
||||
Windows)
|
||||
if [[ $windows_cross_compile -eq 1 ]]; then
|
||||
ci_config=ci-windows-cross
|
||||
else
|
||||
ci_config=ci-windows
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
bazel_startup_args=()
|
||||
if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then
|
||||
bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
|
||||
fi
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' bazel "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
bazel "$@"
|
||||
}
|
||||
|
||||
bazel_query_args=(--noexperimental_remote_repo_contents_cache query)
|
||||
if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
bazel_query_args+=(
|
||||
"--config=${ci_config}"
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPO_CONTENTS_CACHE:-}" ]]; then
|
||||
bazel_query_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}")
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then
|
||||
bazel_query_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}")
|
||||
fi
|
||||
|
||||
bazel_query_args+=("${query_args[@]}" "$query_expression")
|
||||
|
||||
if (( ${#bazel_startup_args[@]} > 0 )); then
|
||||
run_bazel "${bazel_startup_args[@]}" "${bazel_query_args[@]}"
|
||||
else
|
||||
run_bazel "${bazel_query_args[@]}"
|
||||
fi
|
||||
412
reference/openai-codex/.github/scripts/rusty_v8_bazel.py
vendored
Normal file
412
reference/openai-codex/.github/scripts/rusty_v8_bazel.py
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import gzip
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
from rusty_v8_module_bazel import (
|
||||
RustyV8ChecksumError,
|
||||
check_module_bazel,
|
||||
rusty_v8_http_file_versions,
|
||||
update_module_bazel,
|
||||
)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
MODULE_BAZEL = ROOT / "MODULE.bazel"
|
||||
RUSTY_V8_CHECKSUMS_DIR = ROOT / "third_party" / "v8"
|
||||
RELEASE_ARTIFACT_PROFILE = "release"
|
||||
SANDBOX_ARTIFACT_PROFILE = "ptrcomp_sandbox_release"
|
||||
ARTIFACT_BAZEL_CONFIGS = ["rusty-v8-upstream-libcxx"]
|
||||
|
||||
|
||||
def bazel_remote_args() -> list[str]:
|
||||
buildbuddy_api_key = os.environ.get("BUILDBUDDY_API_KEY")
|
||||
if not buildbuddy_api_key:
|
||||
return []
|
||||
return [f"--remote_header=x-buildbuddy-api-key={buildbuddy_api_key}"]
|
||||
|
||||
|
||||
def bazel_execroot() -> Path:
|
||||
result = subprocess.run(
|
||||
["bazel", "info", "execution_root"],
|
||||
cwd=ROOT,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return Path(result.stdout.strip())
|
||||
|
||||
|
||||
def bazel_output_base() -> Path:
|
||||
result = subprocess.run(
|
||||
["bazel", "info", "output_base"],
|
||||
cwd=ROOT,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return Path(result.stdout.strip())
|
||||
|
||||
|
||||
def bazel_output_path(path: str) -> Path:
|
||||
if path.startswith("external/"):
|
||||
return bazel_output_base() / path
|
||||
return bazel_execroot() / path
|
||||
|
||||
|
||||
def bazel_output_files(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> list[Path]:
|
||||
expression = "set(" + " ".join(labels) + ")"
|
||||
bazel_configs = bazel_configs or []
|
||||
result = subprocess.run(
|
||||
[
|
||||
"bazel",
|
||||
"cquery",
|
||||
"-c",
|
||||
compilation_mode,
|
||||
f"--platforms=@llvm//platforms:{platform}",
|
||||
*[f"--config={config}" for config in bazel_configs],
|
||||
*bazel_remote_args(),
|
||||
"--output=files",
|
||||
expression,
|
||||
],
|
||||
cwd=ROOT,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return [bazel_output_path(line.strip()) for line in result.stdout.splitlines() if line.strip()]
|
||||
|
||||
|
||||
def bazel_build(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
download_toplevel: bool = False,
|
||||
) -> None:
|
||||
bazel_configs = bazel_configs or []
|
||||
download_args = ["--remote_download_toplevel"] if download_toplevel else []
|
||||
subprocess.run(
|
||||
[
|
||||
"bazel",
|
||||
"build",
|
||||
"-c",
|
||||
compilation_mode,
|
||||
f"--platforms=@llvm//platforms:{platform}",
|
||||
*[f"--config={config}" for config in bazel_configs],
|
||||
*bazel_remote_args(),
|
||||
*download_args,
|
||||
*labels,
|
||||
],
|
||||
cwd=ROOT,
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def ensure_bazel_output_files(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> list[Path]:
|
||||
# Bazel output paths can be reused across config flips, so existence alone
|
||||
# does not prove the files match the requested flags.
|
||||
bazel_build(
|
||||
platform,
|
||||
labels,
|
||||
compilation_mode,
|
||||
bazel_configs,
|
||||
download_toplevel=True,
|
||||
)
|
||||
outputs = bazel_output_files(platform, labels, compilation_mode, bazel_configs)
|
||||
missing = [str(path) for path in outputs if not path.exists()]
|
||||
if missing:
|
||||
raise SystemExit(f"missing built outputs for {labels}: {missing}")
|
||||
return outputs
|
||||
|
||||
|
||||
def artifact_bazel_configs(bazel_configs: list[str] | None = None) -> list[str]:
|
||||
configured = list(ARTIFACT_BAZEL_CONFIGS)
|
||||
for config in bazel_configs or []:
|
||||
if config not in configured:
|
||||
configured.append(config)
|
||||
return configured
|
||||
|
||||
|
||||
def release_pair_label(target: str, sandbox: bool = False) -> str:
|
||||
target_suffix = target.replace("-", "_")
|
||||
pair_kind = "sandbox_release_pair" if sandbox else "release_pair"
|
||||
return f"//third_party/v8:rusty_v8_{pair_kind}_{target_suffix}"
|
||||
|
||||
|
||||
def resolved_v8_crate_version() -> str:
|
||||
cargo_lock = tomllib.loads((ROOT / "codex-rs" / "Cargo.lock").read_text())
|
||||
versions = sorted(
|
||||
{
|
||||
package["version"]
|
||||
for package in cargo_lock["package"]
|
||||
if package["name"] == "v8"
|
||||
}
|
||||
)
|
||||
if len(versions) == 1:
|
||||
return versions[0]
|
||||
if len(versions) > 1:
|
||||
raise SystemExit(f"expected exactly one resolved v8 version, found: {versions}")
|
||||
|
||||
module_bazel = (ROOT / "MODULE.bazel").read_text()
|
||||
matches = sorted(
|
||||
set(
|
||||
re.findall(
|
||||
r'https://static\.crates\.io/crates/v8/v8-([0-9]+\.[0-9]+\.[0-9]+)\.crate',
|
||||
module_bazel,
|
||||
)
|
||||
)
|
||||
)
|
||||
if len(matches) != 1:
|
||||
raise SystemExit(
|
||||
"expected exactly one pinned v8 crate version in MODULE.bazel, "
|
||||
f"found: {matches}"
|
||||
)
|
||||
return matches[0]
|
||||
|
||||
|
||||
def rusty_v8_checksum_manifest_path(version: str) -> Path:
|
||||
return RUSTY_V8_CHECKSUMS_DIR / f"rusty_v8_{version.replace('.', '_')}.sha256"
|
||||
|
||||
|
||||
def command_version(version: str | None) -> str:
|
||||
if version is not None:
|
||||
return version
|
||||
|
||||
manifest_versions = rusty_v8_http_file_versions(MODULE_BAZEL.read_text())
|
||||
if len(manifest_versions) == 1:
|
||||
return manifest_versions[0]
|
||||
if len(manifest_versions) > 1:
|
||||
raise SystemExit(
|
||||
"expected at most one rusty_v8 http_file version in MODULE.bazel, "
|
||||
f"found: {manifest_versions}; pass --version explicitly"
|
||||
)
|
||||
|
||||
return resolved_v8_crate_version()
|
||||
|
||||
|
||||
def command_manifest_path(manifest: Path | None, version: str) -> Path:
|
||||
if manifest is None:
|
||||
return rusty_v8_checksum_manifest_path(version)
|
||||
if manifest.is_absolute():
|
||||
return manifest
|
||||
return ROOT / manifest
|
||||
|
||||
|
||||
def staged_archive_name(target: str, source_path: Path, artifact_profile: str) -> str:
|
||||
if target.endswith("-pc-windows-msvc"):
|
||||
return f"rusty_v8_{artifact_profile}_{target}.lib.gz"
|
||||
return f"librusty_v8_{artifact_profile}_{target}.a.gz"
|
||||
|
||||
|
||||
def staged_binding_name(target: str, artifact_profile: str) -> str:
|
||||
return f"src_binding_{artifact_profile}_{target}.rs"
|
||||
|
||||
|
||||
def staged_checksums_name(target: str, artifact_profile: str) -> str:
|
||||
return f"rusty_v8_{artifact_profile}_{target}.sha256"
|
||||
|
||||
|
||||
def stage_artifacts(
|
||||
target: str,
|
||||
lib_path: Path,
|
||||
binding_path: Path,
|
||||
output_dir: Path,
|
||||
sandbox: bool,
|
||||
) -> None:
|
||||
missing_paths = [str(path) for path in [lib_path, binding_path] if not path.exists()]
|
||||
if missing_paths:
|
||||
raise SystemExit(f"missing release outputs for {target}: {missing_paths}")
|
||||
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
artifact_profile = SANDBOX_ARTIFACT_PROFILE if sandbox else RELEASE_ARTIFACT_PROFILE
|
||||
staged_library = output_dir / staged_archive_name(target, lib_path, artifact_profile)
|
||||
staged_binding = output_dir / staged_binding_name(target, artifact_profile)
|
||||
|
||||
with lib_path.open("rb") as src, staged_library.open("wb") as dst:
|
||||
with gzip.GzipFile(
|
||||
filename="",
|
||||
mode="wb",
|
||||
fileobj=dst,
|
||||
compresslevel=6,
|
||||
mtime=0,
|
||||
) as gz:
|
||||
shutil.copyfileobj(src, gz)
|
||||
|
||||
shutil.copyfile(binding_path, staged_binding)
|
||||
|
||||
staged_checksums = output_dir / staged_checksums_name(target, artifact_profile)
|
||||
with staged_checksums.open("w", encoding="utf-8") as checksums:
|
||||
for path in [staged_library, staged_binding]:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as artifact:
|
||||
for chunk in iter(lambda: artifact.read(1024 * 1024), b""):
|
||||
digest.update(chunk)
|
||||
checksums.write(f"{digest.hexdigest()} {path.name}\n")
|
||||
|
||||
print(staged_library)
|
||||
print(staged_binding)
|
||||
print(staged_checksums)
|
||||
|
||||
|
||||
def upstream_release_pair_paths(source_root: Path, target: str) -> tuple[Path, Path]:
|
||||
lib_name = "rusty_v8.lib" if target.endswith("-pc-windows-msvc") else "librusty_v8.a"
|
||||
gn_out = source_root / "target" / target / "release" / "gn_out"
|
||||
return gn_out / "obj" / lib_name, gn_out / "src_binding.rs"
|
||||
|
||||
|
||||
def stage_upstream_release_pair(
|
||||
source_root: Path,
|
||||
target: str,
|
||||
output_dir: Path,
|
||||
sandbox: bool = False,
|
||||
) -> None:
|
||||
lib_path, binding_path = upstream_release_pair_paths(source_root, target)
|
||||
stage_artifacts(target, lib_path, binding_path, output_dir, sandbox)
|
||||
|
||||
|
||||
def stage_release_pair(
|
||||
platform: str,
|
||||
target: str,
|
||||
output_dir: Path,
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
sandbox: bool = False,
|
||||
) -> None:
|
||||
bazel_configs = artifact_bazel_configs(bazel_configs)
|
||||
outputs = ensure_bazel_output_files(
|
||||
platform,
|
||||
[release_pair_label(target, sandbox)],
|
||||
compilation_mode,
|
||||
bazel_configs,
|
||||
)
|
||||
|
||||
try:
|
||||
lib_path = next(path for path in outputs if path.suffix in {".a", ".lib"})
|
||||
except StopIteration as exc:
|
||||
raise SystemExit(f"missing static library output for {target}") from exc
|
||||
|
||||
try:
|
||||
binding_path = next(path for path in outputs if path.suffix == ".rs")
|
||||
except StopIteration as exc:
|
||||
raise SystemExit(f"missing Rust binding output for {target}") from exc
|
||||
|
||||
stage_artifacts(target, lib_path, binding_path, output_dir, sandbox)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
stage_release_pair_parser = subparsers.add_parser("stage-release-pair")
|
||||
stage_release_pair_parser.add_argument("--platform", required=True)
|
||||
stage_release_pair_parser.add_argument("--target", required=True)
|
||||
stage_release_pair_parser.add_argument("--output-dir", required=True)
|
||||
stage_release_pair_parser.add_argument("--sandbox", action="store_true")
|
||||
stage_release_pair_parser.add_argument(
|
||||
"--bazel-config",
|
||||
action="append",
|
||||
default=[],
|
||||
dest="bazel_configs",
|
||||
)
|
||||
stage_release_pair_parser.add_argument(
|
||||
"--compilation-mode",
|
||||
default="fastbuild",
|
||||
choices=["fastbuild", "opt", "dbg"],
|
||||
)
|
||||
|
||||
stage_upstream_release_pair_parser = subparsers.add_parser(
|
||||
"stage-upstream-release-pair"
|
||||
)
|
||||
stage_upstream_release_pair_parser.add_argument("--source-root", type=Path, required=True)
|
||||
stage_upstream_release_pair_parser.add_argument("--target", required=True)
|
||||
stage_upstream_release_pair_parser.add_argument("--output-dir", required=True)
|
||||
stage_upstream_release_pair_parser.add_argument("--sandbox", action="store_true")
|
||||
|
||||
subparsers.add_parser("resolved-v8-crate-version")
|
||||
|
||||
check_module_bazel_parser = subparsers.add_parser("check-module-bazel")
|
||||
check_module_bazel_parser.add_argument("--version")
|
||||
check_module_bazel_parser.add_argument("--manifest", type=Path)
|
||||
check_module_bazel_parser.add_argument(
|
||||
"--module-bazel",
|
||||
type=Path,
|
||||
default=MODULE_BAZEL,
|
||||
)
|
||||
|
||||
update_module_bazel_parser = subparsers.add_parser("update-module-bazel")
|
||||
update_module_bazel_parser.add_argument("--version")
|
||||
update_module_bazel_parser.add_argument("--manifest", type=Path)
|
||||
update_module_bazel_parser.add_argument(
|
||||
"--module-bazel",
|
||||
type=Path,
|
||||
default=MODULE_BAZEL,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
if args.command == "stage-release-pair":
|
||||
stage_release_pair(
|
||||
platform=args.platform,
|
||||
target=args.target,
|
||||
output_dir=Path(args.output_dir),
|
||||
compilation_mode=args.compilation_mode,
|
||||
bazel_configs=args.bazel_configs,
|
||||
sandbox=args.sandbox,
|
||||
)
|
||||
return 0
|
||||
if args.command == "stage-upstream-release-pair":
|
||||
stage_upstream_release_pair(
|
||||
source_root=args.source_root,
|
||||
target=args.target,
|
||||
output_dir=Path(args.output_dir),
|
||||
sandbox=args.sandbox,
|
||||
)
|
||||
return 0
|
||||
if args.command == "resolved-v8-crate-version":
|
||||
print(resolved_v8_crate_version())
|
||||
return 0
|
||||
if args.command == "check-module-bazel":
|
||||
version = command_version(args.version)
|
||||
manifest_path = command_manifest_path(args.manifest, version)
|
||||
try:
|
||||
check_module_bazel(args.module_bazel, manifest_path, version)
|
||||
except RustyV8ChecksumError as exc:
|
||||
raise SystemExit(str(exc)) from exc
|
||||
return 0
|
||||
if args.command == "update-module-bazel":
|
||||
version = command_version(args.version)
|
||||
manifest_path = command_manifest_path(args.manifest, version)
|
||||
try:
|
||||
update_module_bazel(args.module_bazel, manifest_path, version)
|
||||
except RustyV8ChecksumError as exc:
|
||||
raise SystemExit(str(exc)) from exc
|
||||
return 0
|
||||
raise SystemExit(f"unsupported command: {args.command}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
243
reference/openai-codex/.github/scripts/rusty_v8_module_bazel.py
vendored
Normal file
243
reference/openai-codex/.github/scripts/rusty_v8_module_bazel.py
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SHA256_RE = re.compile(r"[0-9a-f]{64}")
|
||||
HTTP_FILE_BLOCK_RE = re.compile(r"(?ms)^http_file\(\n.*?^\)\n?")
|
||||
HTTP_FILE_VERSION_RE = re.compile(r"^rusty_v8_([0-9]+)_([0-9]+)_([0-9]+)_")
|
||||
|
||||
|
||||
class RustyV8ChecksumError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RustyV8HttpFile:
|
||||
start: int
|
||||
end: int
|
||||
block: str
|
||||
name: str
|
||||
downloaded_file_path: str
|
||||
sha256: str | None
|
||||
|
||||
|
||||
def parse_checksum_manifest(path: Path) -> dict[str, str]:
|
||||
try:
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
except FileNotFoundError as exc:
|
||||
raise RustyV8ChecksumError(f"missing checksum manifest: {path}") from exc
|
||||
|
||||
checksums: dict[str, str] = {}
|
||||
for line_number, line in enumerate(lines, 1):
|
||||
if not line.strip():
|
||||
continue
|
||||
parts = line.split()
|
||||
if len(parts) != 2:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: expected '<sha256> <filename>'"
|
||||
)
|
||||
checksum, filename = parts
|
||||
if not SHA256_RE.fullmatch(checksum):
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: invalid SHA-256 digest for {filename}"
|
||||
)
|
||||
if not filename or filename in {".", ".."} or "/" in filename:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: expected a bare artifact filename"
|
||||
)
|
||||
if filename in checksums:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: duplicate checksum for {filename}"
|
||||
)
|
||||
checksums[filename] = checksum
|
||||
|
||||
if not checksums:
|
||||
raise RustyV8ChecksumError(f"empty checksum manifest: {path}")
|
||||
return checksums
|
||||
|
||||
|
||||
def string_field(block: str, field: str) -> str | None:
|
||||
# Matches one-line string fields inside http_file blocks, e.g. `sha256 = "...",`.
|
||||
match = re.search(rf'^\s*{re.escape(field)}\s*=\s*"([^"]+)",\s*$', block, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def rusty_v8_http_files(module_bazel: str, version: str) -> list[RustyV8HttpFile]:
|
||||
version_slug = version.replace(".", "_")
|
||||
name_prefix = f"rusty_v8_{version_slug}_"
|
||||
entries = []
|
||||
for match in HTTP_FILE_BLOCK_RE.finditer(module_bazel):
|
||||
block = match.group(0)
|
||||
name = string_field(block, "name")
|
||||
if not name or not name.startswith(name_prefix):
|
||||
continue
|
||||
downloaded_file_path = string_field(block, "downloaded_file_path")
|
||||
if not downloaded_file_path:
|
||||
raise RustyV8ChecksumError(
|
||||
f"MODULE.bazel {name} is missing downloaded_file_path"
|
||||
)
|
||||
entries.append(
|
||||
RustyV8HttpFile(
|
||||
start=match.start(),
|
||||
end=match.end(),
|
||||
block=block,
|
||||
name=name,
|
||||
downloaded_file_path=downloaded_file_path,
|
||||
sha256=string_field(block, "sha256"),
|
||||
)
|
||||
)
|
||||
return entries
|
||||
|
||||
|
||||
def rusty_v8_http_file_versions(module_bazel: str) -> list[str]:
|
||||
versions = set()
|
||||
for match in HTTP_FILE_BLOCK_RE.finditer(module_bazel):
|
||||
name = string_field(match.group(0), "name")
|
||||
if not name:
|
||||
continue
|
||||
version_match = HTTP_FILE_VERSION_RE.match(name)
|
||||
if version_match:
|
||||
versions.add(".".join(version_match.groups()))
|
||||
return sorted(versions)
|
||||
|
||||
|
||||
def module_entry_set_errors(
|
||||
entries: list[RustyV8HttpFile],
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> list[str]:
|
||||
errors = []
|
||||
if not entries:
|
||||
errors.append(f"MODULE.bazel has no rusty_v8 http_file entries for {version}")
|
||||
return errors
|
||||
|
||||
module_files: dict[str, RustyV8HttpFile] = {}
|
||||
duplicate_files = set()
|
||||
for entry in entries:
|
||||
if entry.downloaded_file_path in module_files:
|
||||
duplicate_files.add(entry.downloaded_file_path)
|
||||
module_files[entry.downloaded_file_path] = entry
|
||||
|
||||
for filename in sorted(duplicate_files):
|
||||
errors.append(f"MODULE.bazel has duplicate http_file entries for {filename}")
|
||||
|
||||
for filename in sorted(set(module_files) - set(checksums)):
|
||||
entry = module_files[filename]
|
||||
errors.append(f"MODULE.bazel {entry.name} has no checksum in the manifest")
|
||||
|
||||
for filename in sorted(set(checksums) - set(module_files)):
|
||||
errors.append(f"manifest has {filename}, but MODULE.bazel has no http_file")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def module_checksum_errors(
|
||||
entries: list[RustyV8HttpFile],
|
||||
checksums: dict[str, str],
|
||||
) -> list[str]:
|
||||
errors = []
|
||||
for entry in entries:
|
||||
expected = checksums.get(entry.downloaded_file_path)
|
||||
if expected is None:
|
||||
continue
|
||||
if entry.sha256 is None:
|
||||
errors.append(f"MODULE.bazel {entry.name} is missing sha256")
|
||||
elif entry.sha256 != expected:
|
||||
errors.append(
|
||||
f"MODULE.bazel {entry.name} has sha256 {entry.sha256}, "
|
||||
f"expected {expected}"
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def raise_checksum_errors(message: str, errors: list[str]) -> None:
|
||||
if errors:
|
||||
formatted_errors = "\n".join(f"- {error}" for error in errors)
|
||||
raise RustyV8ChecksumError(f"{message}:\n{formatted_errors}")
|
||||
|
||||
|
||||
def check_module_bazel_text(
|
||||
module_bazel: str,
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> None:
|
||||
entries = rusty_v8_http_files(module_bazel, version)
|
||||
errors = [
|
||||
*module_entry_set_errors(entries, checksums, version),
|
||||
*module_checksum_errors(entries, checksums),
|
||||
]
|
||||
raise_checksum_errors("rusty_v8 MODULE.bazel checksum drift", errors)
|
||||
|
||||
|
||||
def block_with_sha256(block: str, checksum: str) -> str:
|
||||
sha256_line_re = re.compile(r'(?m)^(\s*)sha256\s*=\s*"[0-9a-f]+",\s*$')
|
||||
if sha256_line_re.search(block):
|
||||
return sha256_line_re.sub(
|
||||
lambda match: f'{match.group(1)}sha256 = "{checksum}",',
|
||||
block,
|
||||
count=1,
|
||||
)
|
||||
|
||||
downloaded_file_path_match = re.search(
|
||||
r'(?m)^(\s*)downloaded_file_path\s*=\s*"[^"]+",\n',
|
||||
block,
|
||||
)
|
||||
if not downloaded_file_path_match:
|
||||
raise RustyV8ChecksumError("http_file block is missing downloaded_file_path")
|
||||
insert_at = downloaded_file_path_match.end()
|
||||
indent = downloaded_file_path_match.group(1)
|
||||
return f'{block[:insert_at]}{indent}sha256 = "{checksum}",\n{block[insert_at:]}'
|
||||
|
||||
|
||||
def update_module_bazel_text(
|
||||
module_bazel: str,
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> str:
|
||||
entries = rusty_v8_http_files(module_bazel, version)
|
||||
errors = module_entry_set_errors(entries, checksums, version)
|
||||
raise_checksum_errors("cannot update rusty_v8 MODULE.bazel checksums", errors)
|
||||
|
||||
updated = []
|
||||
previous_end = 0
|
||||
for entry in entries:
|
||||
updated.append(module_bazel[previous_end : entry.start])
|
||||
updated.append(
|
||||
block_with_sha256(entry.block, checksums[entry.downloaded_file_path])
|
||||
)
|
||||
previous_end = entry.end
|
||||
updated.append(module_bazel[previous_end:])
|
||||
return "".join(updated)
|
||||
|
||||
|
||||
def check_module_bazel(
|
||||
module_bazel_path: Path,
|
||||
manifest_path: Path,
|
||||
version: str,
|
||||
) -> None:
|
||||
checksums = parse_checksum_manifest(manifest_path)
|
||||
module_bazel = module_bazel_path.read_text(encoding="utf-8")
|
||||
check_module_bazel_text(module_bazel, checksums, version)
|
||||
print(f"{module_bazel_path} rusty_v8 {version} checksums match {manifest_path}")
|
||||
|
||||
|
||||
def update_module_bazel(
|
||||
module_bazel_path: Path,
|
||||
manifest_path: Path,
|
||||
version: str,
|
||||
) -> None:
|
||||
checksums = parse_checksum_manifest(manifest_path)
|
||||
module_bazel = module_bazel_path.read_text(encoding="utf-8")
|
||||
updated_module_bazel = update_module_bazel_text(module_bazel, checksums, version)
|
||||
if updated_module_bazel == module_bazel:
|
||||
print(f"{module_bazel_path} rusty_v8 {version} checksums are already current")
|
||||
return
|
||||
module_bazel_path.write_text(updated_module_bazel, encoding="utf-8")
|
||||
print(f"updated {module_bazel_path} rusty_v8 {version} checksums")
|
||||
62
reference/openai-codex/.github/scripts/setup-dev-drive.ps1
vendored
Normal file
62
reference/openai-codex/.github/scripts/setup-dev-drive.ps1
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# Configure a fast drive for Windows CI jobs.
|
||||
#
|
||||
# GitHub-hosted Windows runners do not always expose a secondary D: volume. When
|
||||
# they do not, try to create a Dev Drive VHD and fall back to C: if the runner
|
||||
# image does not allow that provisioning path.
|
||||
|
||||
function Use-FallbackDrive {
|
||||
param([string]$Reason)
|
||||
|
||||
Write-Warning "$Reason Falling back to C:"
|
||||
return "C:"
|
||||
}
|
||||
|
||||
function Invoke-BestEffort {
|
||||
param([scriptblock]$Script, [string]$Description)
|
||||
|
||||
try {
|
||||
& $Script
|
||||
} catch {
|
||||
Write-Warning "$Description failed: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path "D:\") {
|
||||
Write-Output "Using existing drive at D:"
|
||||
$Drive = "D:"
|
||||
} else {
|
||||
try {
|
||||
$VhdPath = Join-Path $env:RUNNER_TEMP "codex-dev-drive.vhdx"
|
||||
$SizeBytes = 64GB
|
||||
|
||||
if (Test-Path $VhdPath) {
|
||||
Remove-Item -Path $VhdPath -Force
|
||||
}
|
||||
|
||||
New-VHD -Path $VhdPath -SizeBytes $SizeBytes -Dynamic -ErrorAction Stop | Out-Null
|
||||
$Mounted = Mount-VHD -Path $VhdPath -Passthru -ErrorAction Stop
|
||||
$Disk = $Mounted | Get-Disk -ErrorAction Stop
|
||||
$Disk | Initialize-Disk -PartitionStyle GPT -ErrorAction Stop
|
||||
$Partition = $Disk | New-Partition -AssignDriveLetter -UseMaximumSize -ErrorAction Stop
|
||||
$Volume = $Partition | Format-Volume -FileSystem ReFS -NewFileSystemLabel "CodexDevDrive" -DevDrive -Confirm:$false -Force -ErrorAction Stop
|
||||
|
||||
$Drive = "$($Volume.DriveLetter):"
|
||||
|
||||
Invoke-BestEffort { fsutil devdrv trust $Drive } "Trusting Dev Drive $Drive"
|
||||
Invoke-BestEffort { fsutil devdrv enable /disallowAv } "Disabling AV filter attachment for Dev Drives"
|
||||
Invoke-BestEffort { fsutil devdrv query $Drive } "Querying Dev Drive $Drive"
|
||||
|
||||
Write-Output "Using Dev Drive at $Drive"
|
||||
} catch {
|
||||
$Drive = Use-FallbackDrive "Failed to create Dev Drive: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
$Tmp = "$Drive\codex-tmp"
|
||||
New-Item -Path $Tmp -ItemType Directory -Force | Out-Null
|
||||
|
||||
@(
|
||||
"DEV_DRIVE=$Drive"
|
||||
"TMP=$Tmp"
|
||||
"TEMP=$Tmp"
|
||||
) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
413
reference/openai-codex/.github/scripts/test_rusty_v8_bazel.py
vendored
Normal file
413
reference/openai-codex/.github/scripts/test_rusty_v8_bazel.py
vendored
Normal file
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import textwrap
|
||||
import unittest
|
||||
from os import environ
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from unittest.mock import patch
|
||||
|
||||
import rusty_v8_bazel
|
||||
import rusty_v8_module_bazel
|
||||
|
||||
|
||||
class RustyV8BazelTest(unittest.TestCase):
|
||||
def test_consumer_selectors_track_resolved_crate_version(self) -> None:
|
||||
build_bazel = (
|
||||
rusty_v8_bazel.ROOT / "third_party" / "v8" / "BUILD.bazel"
|
||||
).read_text()
|
||||
version_suffix = rusty_v8_bazel.resolved_v8_crate_version().replace(".", "_")
|
||||
|
||||
for selector in [
|
||||
"aarch64_apple_darwin_bazel",
|
||||
"aarch64_pc_windows_gnullvm",
|
||||
"aarch64_pc_windows_msvc",
|
||||
"aarch64_unknown_linux_gnu_bazel",
|
||||
"aarch64_unknown_linux_musl_release_base",
|
||||
"x86_64_apple_darwin_bazel",
|
||||
"x86_64_pc_windows_gnullvm",
|
||||
"x86_64_pc_windows_msvc",
|
||||
"x86_64_unknown_linux_gnu_bazel",
|
||||
"x86_64_unknown_linux_musl_release",
|
||||
]:
|
||||
self.assertIn(
|
||||
f":v8_{version_suffix}_{selector}",
|
||||
build_bazel,
|
||||
)
|
||||
|
||||
for selector in [
|
||||
"aarch64_apple_darwin",
|
||||
"aarch64_pc_windows_gnullvm",
|
||||
"aarch64_pc_windows_msvc",
|
||||
"aarch64_unknown_linux_gnu",
|
||||
"aarch64_unknown_linux_musl",
|
||||
"x86_64_apple_darwin",
|
||||
"x86_64_pc_windows_gnullvm",
|
||||
"x86_64_pc_windows_msvc",
|
||||
"x86_64_unknown_linux_gnu",
|
||||
"x86_64_unknown_linux_musl",
|
||||
]:
|
||||
self.assertIn(
|
||||
f":src_binding_release_{selector}_{version_suffix}_release",
|
||||
build_bazel,
|
||||
)
|
||||
|
||||
def test_command_version_tracks_remaining_http_file_assets(self) -> None:
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
module_bazel = Path(temp_dir) / "MODULE.bazel"
|
||||
module_bazel.write_text(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
urls = ["https://example.test/archive.gz"],
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
with patch.object(rusty_v8_bazel, "MODULE_BAZEL", module_bazel):
|
||||
self.assertEqual("146.4.0", rusty_v8_bazel.command_version(None))
|
||||
|
||||
def test_artifact_bazel_configs_always_enable_upstream_libcxx(self) -> None:
|
||||
self.assertEqual(
|
||||
["rusty-v8-upstream-libcxx"],
|
||||
rusty_v8_bazel.artifact_bazel_configs(),
|
||||
)
|
||||
self.assertEqual(
|
||||
["rusty-v8-upstream-libcxx", "v8-release-compat"],
|
||||
rusty_v8_bazel.artifact_bazel_configs(["v8-release-compat"]),
|
||||
)
|
||||
self.assertEqual(
|
||||
["rusty-v8-upstream-libcxx", "v8-release-compat"],
|
||||
rusty_v8_bazel.artifact_bazel_configs(
|
||||
["rusty-v8-upstream-libcxx", "v8-release-compat"]
|
||||
),
|
||||
)
|
||||
|
||||
def test_bazel_remote_args_include_buildbuddy_header_when_present(self) -> None:
|
||||
with patch.dict(environ, {"BUILDBUDDY_API_KEY": "token"}, clear=False):
|
||||
self.assertEqual(
|
||||
["--remote_header=x-buildbuddy-api-key=token"],
|
||||
rusty_v8_bazel.bazel_remote_args(),
|
||||
)
|
||||
|
||||
with patch.dict(environ, {}, clear=True):
|
||||
self.assertEqual([], rusty_v8_bazel.bazel_remote_args())
|
||||
|
||||
def test_release_pair_labels_and_staged_names_distinguish_sandbox_artifacts(self) -> None:
|
||||
self.assertEqual(
|
||||
"//third_party/v8:rusty_v8_release_pair_x86_64_unknown_linux_musl",
|
||||
rusty_v8_bazel.release_pair_label("x86_64-unknown-linux-musl"),
|
||||
)
|
||||
self.assertEqual(
|
||||
"//third_party/v8:rusty_v8_sandbox_release_pair_x86_64_unknown_linux_musl",
|
||||
rusty_v8_bazel.release_pair_label("x86_64-unknown-linux-musl", sandbox=True),
|
||||
)
|
||||
self.assertEqual(
|
||||
"//third_party/v8:rusty_v8_sandbox_release_pair_x86_64_apple_darwin",
|
||||
rusty_v8_bazel.release_pair_label("x86_64-apple-darwin", sandbox=True),
|
||||
)
|
||||
self.assertEqual(
|
||||
"librusty_v8_release_x86_64-unknown-linux-musl.a.gz",
|
||||
rusty_v8_bazel.staged_archive_name(
|
||||
"x86_64-unknown-linux-musl",
|
||||
Path("libv8.a"),
|
||||
rusty_v8_bazel.RELEASE_ARTIFACT_PROFILE,
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
"rusty_v8_ptrcomp_sandbox_release_x86_64-pc-windows-msvc.lib.gz",
|
||||
rusty_v8_bazel.staged_archive_name(
|
||||
"x86_64-pc-windows-msvc",
|
||||
Path("v8.a"),
|
||||
rusty_v8_bazel.SANDBOX_ARTIFACT_PROFILE,
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
"src_binding_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.rs",
|
||||
rusty_v8_bazel.staged_binding_name(
|
||||
"x86_64-unknown-linux-musl",
|
||||
rusty_v8_bazel.SANDBOX_ARTIFACT_PROFILE,
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
"rusty_v8_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.sha256",
|
||||
rusty_v8_bazel.staged_checksums_name(
|
||||
"x86_64-unknown-linux-musl",
|
||||
rusty_v8_bazel.SANDBOX_ARTIFACT_PROFILE,
|
||||
),
|
||||
)
|
||||
|
||||
def test_stage_artifacts(self) -> None:
|
||||
with TemporaryDirectory() as source_dir, TemporaryDirectory() as output_dir:
|
||||
source_root = Path(source_dir)
|
||||
archive = source_root / "librusty_v8.a"
|
||||
binding = source_root / "src_binding.rs"
|
||||
archive.write_bytes(b"archive")
|
||||
binding.write_text("binding")
|
||||
|
||||
rusty_v8_bazel.stage_artifacts(
|
||||
"aarch64-apple-darwin",
|
||||
archive,
|
||||
binding,
|
||||
Path(output_dir),
|
||||
sandbox=True,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
"librusty_v8_ptrcomp_sandbox_release_aarch64-apple-darwin.a.gz",
|
||||
"src_binding_ptrcomp_sandbox_release_aarch64-apple-darwin.rs",
|
||||
"rusty_v8_ptrcomp_sandbox_release_aarch64-apple-darwin.sha256",
|
||||
},
|
||||
{path.name for path in Path(output_dir).iterdir()},
|
||||
)
|
||||
|
||||
def test_upstream_release_pair_paths(self) -> None:
|
||||
self.assertEqual(
|
||||
(
|
||||
Path(
|
||||
"/tmp/rusty_v8/target/x86_64-apple-darwin/release/gn_out/obj/"
|
||||
"librusty_v8.a"
|
||||
),
|
||||
Path(
|
||||
"/tmp/rusty_v8/target/x86_64-apple-darwin/release/gn_out/"
|
||||
"src_binding.rs"
|
||||
),
|
||||
),
|
||||
rusty_v8_bazel.upstream_release_pair_paths(
|
||||
Path("/tmp/rusty_v8"),
|
||||
"x86_64-apple-darwin",
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
(
|
||||
Path(
|
||||
"/tmp/rusty_v8/target/x86_64-pc-windows-msvc/release/gn_out/"
|
||||
"obj/rusty_v8.lib"
|
||||
),
|
||||
Path(
|
||||
"/tmp/rusty_v8/target/x86_64-pc-windows-msvc/release/gn_out/"
|
||||
"src_binding.rs"
|
||||
),
|
||||
),
|
||||
rusty_v8_bazel.upstream_release_pair_paths(
|
||||
Path("/tmp/rusty_v8"),
|
||||
"x86_64-pc-windows-msvc",
|
||||
),
|
||||
)
|
||||
|
||||
def test_stage_upstream_release_pair(self) -> None:
|
||||
with TemporaryDirectory() as source_dir, TemporaryDirectory() as output_dir:
|
||||
source_root = Path(source_dir)
|
||||
gn_out = (
|
||||
source_root
|
||||
/ "target"
|
||||
/ "x86_64-pc-windows-msvc"
|
||||
/ "release"
|
||||
/ "gn_out"
|
||||
)
|
||||
(gn_out / "obj").mkdir(parents=True)
|
||||
(gn_out / "obj" / "rusty_v8.lib").write_bytes(b"archive")
|
||||
(gn_out / "src_binding.rs").write_text("binding")
|
||||
|
||||
rusty_v8_bazel.stage_upstream_release_pair(
|
||||
source_root,
|
||||
"x86_64-pc-windows-msvc",
|
||||
Path(output_dir),
|
||||
sandbox=True,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
"rusty_v8_ptrcomp_sandbox_release_x86_64-pc-windows-msvc.lib.gz",
|
||||
"src_binding_ptrcomp_sandbox_release_x86_64-pc-windows-msvc.rs",
|
||||
"rusty_v8_ptrcomp_sandbox_release_x86_64-pc-windows-msvc.sha256",
|
||||
},
|
||||
{path.name for path in Path(output_dir).iterdir()},
|
||||
)
|
||||
|
||||
def test_ensure_bazel_output_files_rebuilds_existing_outputs(self) -> None:
|
||||
with TemporaryDirectory() as output_dir:
|
||||
output = Path(output_dir) / "libv8.a"
|
||||
output.write_bytes(b"archive")
|
||||
|
||||
with (
|
||||
patch.object(rusty_v8_bazel, "bazel_build") as bazel_build,
|
||||
patch.object(
|
||||
rusty_v8_bazel,
|
||||
"bazel_output_files",
|
||||
return_value=[output],
|
||||
) as bazel_output_files,
|
||||
):
|
||||
self.assertEqual(
|
||||
[output],
|
||||
rusty_v8_bazel.ensure_bazel_output_files(
|
||||
"macos_arm64",
|
||||
["//third_party/v8:pair"],
|
||||
"opt",
|
||||
["rusty-v8-upstream-libcxx"],
|
||||
),
|
||||
)
|
||||
|
||||
bazel_build.assert_called_once_with(
|
||||
"macos_arm64",
|
||||
["//third_party/v8:pair"],
|
||||
"opt",
|
||||
["rusty-v8-upstream-libcxx"],
|
||||
download_toplevel=True,
|
||||
)
|
||||
bazel_output_files.assert_called_once_with(
|
||||
"macos_arm64",
|
||||
["//third_party/v8:pair"],
|
||||
"opt",
|
||||
["rusty-v8-upstream-libcxx"],
|
||||
)
|
||||
|
||||
def test_update_module_bazel_replaces_and_inserts_sha256(self) -> None:
|
||||
module_bazel = textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
urls = [
|
||||
"https://example.test/src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_145_0_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
urls = [
|
||||
"https://example.test/old.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
)
|
||||
checksums = {
|
||||
"librusty_v8_release_x86_64-unknown-linux-gnu.a.gz": (
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
),
|
||||
"src_binding_release_x86_64-unknown-linux-musl.rs": (
|
||||
"2222222222222222222222222222222222222222222222222222222222222222"
|
||||
),
|
||||
}
|
||||
|
||||
updated = rusty_v8_module_bazel.update_module_bazel_text(
|
||||
module_bazel,
|
||||
checksums,
|
||||
"146.4.0",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
sha256 = "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
urls = [
|
||||
"https://example.test/src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_145_0_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
urls = [
|
||||
"https://example.test/old.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
),
|
||||
updated,
|
||||
)
|
||||
rusty_v8_module_bazel.check_module_bazel_text(updated, checksums, "146.4.0")
|
||||
|
||||
def test_check_module_bazel_rejects_manifest_drift(self) -> None:
|
||||
module_bazel = textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
)
|
||||
checksums = {
|
||||
"librusty_v8_release_x86_64-unknown-linux-gnu.a.gz": (
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
),
|
||||
"orphan.gz": (
|
||||
"2222222222222222222222222222222222222222222222222222222222222222"
|
||||
),
|
||||
}
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
rusty_v8_module_bazel.RustyV8ChecksumError,
|
||||
"manifest has orphan.gz",
|
||||
):
|
||||
rusty_v8_module_bazel.check_module_bazel_text(
|
||||
module_bazel,
|
||||
checksums,
|
||||
"146.4.0",
|
||||
)
|
||||
|
||||
def test_rusty_v8_http_file_versions(self) -> None:
|
||||
module_bazel = textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "archive.gz",
|
||||
urls = ["https://example.test/archive.gz"],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_147_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "new-archive.gz",
|
||||
urls = ["https://example.test/new-archive.gz"],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "unrelated_archive",
|
||||
downloaded_file_path = "other.gz",
|
||||
urls = ["https://example.test/other.gz"],
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
["146.4.0", "147.4.0"],
|
||||
rusty_v8_module_bazel.rusty_v8_http_file_versions(module_bazel),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
234
reference/openai-codex/.github/scripts/verify_bazel_clippy_lints.py
vendored
Normal file
234
reference/openai-codex/.github/scripts/verify_bazel_clippy_lints.py
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
DEFAULT_CARGO_TOML = ROOT / "codex-rs" / "Cargo.toml"
|
||||
DEFAULT_BAZELRC = ROOT / ".bazelrc"
|
||||
BAZEL_CLIPPY_FLAG_PREFIX = "build:clippy --@rules_rust//rust/settings:clippy_flag="
|
||||
BAZEL_SPECIAL_FLAGS = {"-Dwarnings"}
|
||||
VALID_LEVELS = {"allow", "warn", "deny", "forbid"}
|
||||
LONG_FLAG_RE = re.compile(
|
||||
r"^--(?P<level>allow|warn|deny|forbid)=clippy::(?P<lint>[a-z0-9_]+)$"
|
||||
)
|
||||
SHORT_FLAG_RE = re.compile(r"^-(?P<level>[AWDF])clippy::(?P<lint>[a-z0-9_]+)$")
|
||||
SHORT_LEVEL_NAMES = {
|
||||
"A": "allow",
|
||||
"W": "warn",
|
||||
"D": "deny",
|
||||
"F": "forbid",
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Verify that Bazel clippy flags in .bazelrc stay in sync with "
|
||||
"codex-rs/Cargo.toml [workspace.lints.clippy]."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cargo-toml",
|
||||
type=Path,
|
||||
default=DEFAULT_CARGO_TOML,
|
||||
help="Path to the workspace Cargo.toml to inspect.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bazelrc",
|
||||
type=Path,
|
||||
default=DEFAULT_BAZELRC,
|
||||
help="Path to the .bazelrc file to inspect.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
cargo_toml = args.cargo_toml.resolve()
|
||||
bazelrc = args.bazelrc.resolve()
|
||||
|
||||
cargo_lints = load_workspace_clippy_lints(cargo_toml)
|
||||
bazel_lints = load_bazel_clippy_lints(bazelrc)
|
||||
|
||||
missing = sorted(cargo_lints.keys() - bazel_lints.keys())
|
||||
extra = sorted(bazel_lints.keys() - cargo_lints.keys())
|
||||
mismatched = sorted(
|
||||
lint
|
||||
for lint in cargo_lints.keys() & bazel_lints.keys()
|
||||
if cargo_lints[lint] != bazel_lints[lint]
|
||||
)
|
||||
|
||||
if missing or extra or mismatched:
|
||||
print_sync_error(
|
||||
cargo_toml=cargo_toml,
|
||||
bazelrc=bazelrc,
|
||||
cargo_lints=cargo_lints,
|
||||
bazel_lints=bazel_lints,
|
||||
missing=missing,
|
||||
extra=extra,
|
||||
mismatched=mismatched,
|
||||
)
|
||||
return 1
|
||||
|
||||
print(
|
||||
"Bazel clippy flags in "
|
||||
f"{display_path(bazelrc)} match "
|
||||
f"{display_path(cargo_toml)} [workspace.lints.clippy]."
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def load_workspace_clippy_lints(cargo_toml: Path) -> dict[str, str]:
|
||||
workspace = tomllib.loads(cargo_toml.read_text())["workspace"]
|
||||
clippy_lints = workspace["lints"]["clippy"]
|
||||
parsed: dict[str, str] = {}
|
||||
for lint, level in clippy_lints.items():
|
||||
if not isinstance(level, str):
|
||||
raise SystemExit(
|
||||
f"expected string lint level for clippy::{lint} in {cargo_toml}, got {level!r}"
|
||||
)
|
||||
normalized = level.strip().lower()
|
||||
if normalized not in VALID_LEVELS:
|
||||
raise SystemExit(
|
||||
f"unsupported lint level {level!r} for clippy::{lint} in {cargo_toml}"
|
||||
)
|
||||
parsed[lint] = normalized
|
||||
return parsed
|
||||
|
||||
|
||||
def load_bazel_clippy_lints(bazelrc: Path) -> dict[str, str]:
|
||||
parsed: dict[str, str] = {}
|
||||
line_numbers: dict[str, int] = {}
|
||||
|
||||
for lineno, line in enumerate(bazelrc.read_text().splitlines(), start=1):
|
||||
if not line.startswith(BAZEL_CLIPPY_FLAG_PREFIX):
|
||||
continue
|
||||
|
||||
flag = line.removeprefix(BAZEL_CLIPPY_FLAG_PREFIX).strip()
|
||||
if flag in BAZEL_SPECIAL_FLAGS:
|
||||
continue
|
||||
|
||||
parsed_flag = parse_bazel_lint_flag(flag)
|
||||
if parsed_flag is None:
|
||||
continue
|
||||
|
||||
lint, level = parsed_flag
|
||||
if lint in parsed:
|
||||
raise SystemExit(
|
||||
f"duplicate Bazel clippy entry for clippy::{lint} at "
|
||||
f"{bazelrc}:{line_numbers[lint]} and {bazelrc}:{lineno}"
|
||||
)
|
||||
parsed[lint] = level
|
||||
line_numbers[lint] = lineno
|
||||
|
||||
return parsed
|
||||
|
||||
|
||||
def parse_bazel_lint_flag(flag: str) -> tuple[str, str] | None:
|
||||
long_match = LONG_FLAG_RE.match(flag)
|
||||
if long_match:
|
||||
return long_match["lint"], long_match["level"]
|
||||
|
||||
short_match = SHORT_FLAG_RE.match(flag)
|
||||
if short_match:
|
||||
return short_match["lint"], SHORT_LEVEL_NAMES[short_match["level"]]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def print_sync_error(
|
||||
*,
|
||||
cargo_toml: Path,
|
||||
bazelrc: Path,
|
||||
cargo_lints: dict[str, str],
|
||||
bazel_lints: dict[str, str],
|
||||
missing: list[str],
|
||||
extra: list[str],
|
||||
mismatched: list[str],
|
||||
) -> None:
|
||||
cargo_toml_display = display_path(cargo_toml)
|
||||
bazelrc_display = display_path(bazelrc)
|
||||
example_manifest = find_workspace_lints_example_manifest()
|
||||
|
||||
print(
|
||||
"ERROR: Bazel clippy flags are out of sync with Cargo workspace clippy lints.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(file=sys.stderr)
|
||||
print(
|
||||
f"Cargo defines the source of truth in {cargo_toml_display} "
|
||||
"[workspace.lints.clippy].",
|
||||
file=sys.stderr,
|
||||
)
|
||||
if example_manifest is not None:
|
||||
print(
|
||||
"Cargo applies those lint levels to member crates that opt into "
|
||||
f"`[lints] workspace = true`, for example {example_manifest}.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
"Bazel clippy does not ingest Cargo lint levels automatically, and "
|
||||
"`clippy.toml` can configure lint behavior but cannot set allow/warn/deny/forbid.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
f"Update {bazelrc_display} so its `build:clippy` "
|
||||
"`clippy_flag` entries match Cargo.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
if missing:
|
||||
print(file=sys.stderr)
|
||||
print("Missing Bazel entries:", file=sys.stderr)
|
||||
for lint in missing:
|
||||
print(f" {render_bazelrc_line(lint, cargo_lints[lint])}", file=sys.stderr)
|
||||
|
||||
if mismatched:
|
||||
print(file=sys.stderr)
|
||||
print("Mismatched lint levels:", file=sys.stderr)
|
||||
for lint in mismatched:
|
||||
cargo_level = cargo_lints[lint]
|
||||
bazel_level = bazel_lints[lint]
|
||||
print(
|
||||
f" clippy::{lint}: Cargo has {cargo_level}, Bazel has {bazel_level}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
f" expected: {render_bazelrc_line(lint, cargo_level)}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
if extra:
|
||||
print(file=sys.stderr)
|
||||
print("Extra Bazel entries with no Cargo counterpart:", file=sys.stderr)
|
||||
for lint in extra:
|
||||
print(f" {render_bazelrc_line(lint, bazel_lints[lint])}", file=sys.stderr)
|
||||
|
||||
|
||||
def render_bazelrc_line(lint: str, level: str) -> str:
|
||||
return f"{BAZEL_CLIPPY_FLAG_PREFIX}--{level}=clippy::{lint}"
|
||||
|
||||
|
||||
def display_path(path: Path) -> str:
|
||||
try:
|
||||
return str(path.relative_to(ROOT))
|
||||
except ValueError:
|
||||
return str(path)
|
||||
|
||||
|
||||
def find_workspace_lints_example_manifest() -> str | None:
|
||||
for cargo_toml in sorted((ROOT / "codex-rs").glob("**/Cargo.toml")):
|
||||
if cargo_toml == DEFAULT_CARGO_TOML:
|
||||
continue
|
||||
data = tomllib.loads(cargo_toml.read_text())
|
||||
if data.get("lints", {}).get("workspace") is True:
|
||||
return str(cargo_toml.relative_to(ROOT))
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
391
reference/openai-codex/.github/scripts/verify_cargo_workspace_manifests.py
vendored
Normal file
391
reference/openai-codex/.github/scripts/verify_cargo_workspace_manifests.py
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Verify that codex-rs Cargo manifests follow workspace manifest policy.
|
||||
|
||||
Checks:
|
||||
- Crates inherit `[workspace.package]` metadata.
|
||||
- Crates opt into `[lints] workspace = true`.
|
||||
- Crate names follow the codex-rs directory naming conventions.
|
||||
- Workspace manifests do not introduce workspace crate feature toggles.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
CARGO_RS_ROOT = ROOT / "codex-rs"
|
||||
WORKSPACE_PACKAGE_FIELDS = ("version", "edition", "license")
|
||||
TOP_LEVEL_NAME_EXCEPTIONS = {
|
||||
"windows-sandbox-rs": "codex-windows-sandbox",
|
||||
}
|
||||
UTILITY_NAME_EXCEPTIONS = {
|
||||
"path-utils": "codex-utils-path",
|
||||
}
|
||||
MANIFEST_FEATURE_EXCEPTIONS = {
|
||||
"codex-rs/code-mode/Cargo.toml": {"sandbox": ("v8/v8_enable_sandbox",)},
|
||||
"codex-rs/v8-poc/Cargo.toml": {"sandbox": ("v8/v8_enable_sandbox",)},
|
||||
}
|
||||
OPTIONAL_DEPENDENCY_EXCEPTIONS = set()
|
||||
INTERNAL_DEPENDENCY_FEATURE_EXCEPTIONS = {}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
internal_package_names = workspace_package_names()
|
||||
used_manifest_feature_exceptions: set[str] = set()
|
||||
used_optional_dependency_exceptions: set[tuple[str, str, str]] = set()
|
||||
used_internal_dependency_feature_exceptions: set[tuple[str, str, str]] = set()
|
||||
failures_by_path: dict[str, list[str]] = {}
|
||||
|
||||
for path in manifests_to_verify():
|
||||
if errors := manifest_errors(
|
||||
path,
|
||||
internal_package_names,
|
||||
used_manifest_feature_exceptions,
|
||||
used_optional_dependency_exceptions,
|
||||
used_internal_dependency_feature_exceptions,
|
||||
):
|
||||
failures_by_path[manifest_key(path)] = errors
|
||||
|
||||
add_unused_exception_errors(
|
||||
failures_by_path,
|
||||
used_manifest_feature_exceptions,
|
||||
used_optional_dependency_exceptions,
|
||||
used_internal_dependency_feature_exceptions,
|
||||
)
|
||||
|
||||
if not failures_by_path:
|
||||
return 0
|
||||
|
||||
print(
|
||||
"Cargo manifests under codex-rs must inherit workspace package metadata, "
|
||||
"opt into workspace lints, and avoid introducing new workspace crate "
|
||||
"features."
|
||||
)
|
||||
print(
|
||||
"Workspace crate features are disallowed because our Bazel build setup "
|
||||
"does not honor them today, which can let issues hidden behind feature "
|
||||
"gates go unnoticed, and because they add extra crate build "
|
||||
"permutations we want to avoid."
|
||||
)
|
||||
print(
|
||||
"Cargo only applies `codex-rs/Cargo.toml` `[workspace.lints.clippy]` "
|
||||
"entries to a crate when that crate declares:"
|
||||
)
|
||||
print()
|
||||
print("[lints]")
|
||||
print("workspace = true")
|
||||
print()
|
||||
print(
|
||||
"Without that opt-in, `cargo clippy` can miss violations that Bazel clippy "
|
||||
"catches."
|
||||
)
|
||||
print()
|
||||
print(
|
||||
"Package-name checks apply to `codex-rs/<crate>/Cargo.toml` and "
|
||||
"`codex-rs/utils/<crate>/Cargo.toml`."
|
||||
)
|
||||
print(
|
||||
"Workspace crate features are forbidden; add a targeted exception here "
|
||||
"only if there is a deliberate temporary migration in flight."
|
||||
)
|
||||
print()
|
||||
for path in sorted(failures_by_path):
|
||||
errors = failures_by_path[path]
|
||||
print(f"{path}:")
|
||||
for error in errors:
|
||||
print(f" - {error}")
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def manifest_errors(
|
||||
path: Path,
|
||||
internal_package_names: set[str],
|
||||
used_manifest_feature_exceptions: set[str],
|
||||
used_optional_dependency_exceptions: set[tuple[str, str, str]],
|
||||
used_internal_dependency_feature_exceptions: set[tuple[str, str, str]],
|
||||
) -> list[str]:
|
||||
manifest = load_manifest(path)
|
||||
package = manifest.get("package")
|
||||
if not isinstance(package, dict) and path != CARGO_RS_ROOT / "Cargo.toml":
|
||||
return []
|
||||
|
||||
errors = []
|
||||
if isinstance(package, dict):
|
||||
for field in WORKSPACE_PACKAGE_FIELDS:
|
||||
if not is_workspace_reference(package.get(field)):
|
||||
errors.append(f"set `{field}.workspace = true` in `[package]`")
|
||||
|
||||
lints = manifest.get("lints")
|
||||
if not (isinstance(lints, dict) and lints.get("workspace") is True):
|
||||
errors.append("add `[lints]` with `workspace = true`")
|
||||
|
||||
expected_name = expected_package_name(path)
|
||||
if expected_name is not None:
|
||||
actual_name = package.get("name")
|
||||
if actual_name != expected_name:
|
||||
errors.append(
|
||||
f"set `[package].name` to `{expected_name}` (found `{actual_name}`)"
|
||||
)
|
||||
|
||||
path_key = manifest_key(path)
|
||||
features = manifest.get("features")
|
||||
if features is not None:
|
||||
normalized_features = normalize_feature_mapping(features)
|
||||
expected_features = MANIFEST_FEATURE_EXCEPTIONS.get(path_key)
|
||||
if expected_features is None:
|
||||
errors.append(
|
||||
"remove `[features]`; new workspace crate features are not allowed"
|
||||
)
|
||||
else:
|
||||
used_manifest_feature_exceptions.add(path_key)
|
||||
if normalized_features != expected_features:
|
||||
errors.append(
|
||||
"limit `[features]` to the existing exception list while "
|
||||
"workspace crate features are being removed "
|
||||
f"(expected {render_feature_mapping(expected_features)})"
|
||||
)
|
||||
|
||||
for section_name, dependencies in dependency_sections(manifest):
|
||||
for dependency_name, dependency in dependencies.items():
|
||||
if not isinstance(dependency, dict):
|
||||
continue
|
||||
|
||||
if dependency.get("optional") is True:
|
||||
exception_key = (path_key, section_name, dependency_name)
|
||||
if exception_key in OPTIONAL_DEPENDENCY_EXCEPTIONS:
|
||||
used_optional_dependency_exceptions.add(exception_key)
|
||||
else:
|
||||
errors.append(
|
||||
"remove `optional = true` from "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}`; "
|
||||
"new optional dependencies are not allowed because they "
|
||||
"create crate features"
|
||||
)
|
||||
|
||||
if not is_internal_dependency(path, dependency_name, dependency, internal_package_names):
|
||||
continue
|
||||
|
||||
dependency_features = dependency.get("features")
|
||||
if dependency_features is not None:
|
||||
normalized_dependency_features = normalize_string_list(
|
||||
dependency_features
|
||||
)
|
||||
exception_key = (path_key, section_name, dependency_name)
|
||||
expected_dependency_features = (
|
||||
INTERNAL_DEPENDENCY_FEATURE_EXCEPTIONS.get(exception_key)
|
||||
)
|
||||
if expected_dependency_features is None:
|
||||
errors.append(
|
||||
"remove `features = [...]` from workspace dependency "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}`; "
|
||||
"new workspace crate feature activations are not allowed"
|
||||
)
|
||||
else:
|
||||
used_internal_dependency_feature_exceptions.add(exception_key)
|
||||
if normalized_dependency_features != expected_dependency_features:
|
||||
errors.append(
|
||||
"limit workspace dependency features on "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}` "
|
||||
"to the existing exception list while workspace crate "
|
||||
"features are being removed "
|
||||
f"(expected {render_string_list(expected_dependency_features)})"
|
||||
)
|
||||
|
||||
if dependency.get("default-features") is False:
|
||||
errors.append(
|
||||
"remove `default-features = false` from workspace dependency "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}`; "
|
||||
"new workspace crate feature toggles are not allowed"
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def expected_package_name(path: Path) -> str | None:
|
||||
parts = path.relative_to(CARGO_RS_ROOT).parts
|
||||
if len(parts) == 2 and parts[1] == "Cargo.toml":
|
||||
directory = parts[0]
|
||||
return TOP_LEVEL_NAME_EXCEPTIONS.get(
|
||||
directory,
|
||||
directory if directory.startswith("codex-") else f"codex-{directory}",
|
||||
)
|
||||
if len(parts) == 3 and parts[0] == "utils" and parts[2] == "Cargo.toml":
|
||||
directory = parts[1]
|
||||
return UTILITY_NAME_EXCEPTIONS.get(directory, f"codex-utils-{directory}")
|
||||
return None
|
||||
|
||||
|
||||
def is_workspace_reference(value: object) -> bool:
|
||||
return isinstance(value, dict) and value.get("workspace") is True
|
||||
|
||||
|
||||
def manifest_key(path: Path) -> str:
|
||||
return str(path.relative_to(ROOT))
|
||||
|
||||
|
||||
def normalize_feature_mapping(value: object) -> dict[str, tuple[str, ...]] | None:
|
||||
if not isinstance(value, dict):
|
||||
return None
|
||||
|
||||
normalized = {}
|
||||
for key, features in value.items():
|
||||
if not isinstance(key, str):
|
||||
return None
|
||||
normalized_features = normalize_string_list(features)
|
||||
if normalized_features is None:
|
||||
return None
|
||||
normalized[key] = normalized_features
|
||||
return normalized
|
||||
|
||||
|
||||
def normalize_string_list(value: object) -> tuple[str, ...] | None:
|
||||
if not isinstance(value, list) or not all(isinstance(item, str) for item in value):
|
||||
return None
|
||||
return tuple(value)
|
||||
|
||||
|
||||
def render_feature_mapping(features: dict[str, tuple[str, ...]]) -> str:
|
||||
entries = [
|
||||
f"{name} = {render_string_list(items)}" for name, items in features.items()
|
||||
]
|
||||
return ", ".join(entries)
|
||||
|
||||
|
||||
def render_string_list(items: tuple[str, ...]) -> str:
|
||||
return "[" + ", ".join(f'"{item}"' for item in items) + "]"
|
||||
|
||||
|
||||
def dependency_sections(manifest: dict) -> list[tuple[str, dict]]:
|
||||
sections = []
|
||||
for section_name in ("dependencies", "dev-dependencies", "build-dependencies"):
|
||||
dependencies = manifest.get(section_name)
|
||||
if isinstance(dependencies, dict):
|
||||
sections.append((section_name, dependencies))
|
||||
|
||||
workspace = manifest.get("workspace")
|
||||
if isinstance(workspace, dict):
|
||||
workspace_dependencies = workspace.get("dependencies")
|
||||
if isinstance(workspace_dependencies, dict):
|
||||
sections.append(("workspace.dependencies", workspace_dependencies))
|
||||
|
||||
target = manifest.get("target")
|
||||
if not isinstance(target, dict):
|
||||
return sections
|
||||
|
||||
for target_name, tables in target.items():
|
||||
if not isinstance(tables, dict):
|
||||
continue
|
||||
for section_name in ("dependencies", "dev-dependencies", "build-dependencies"):
|
||||
dependencies = tables.get(section_name)
|
||||
if isinstance(dependencies, dict):
|
||||
sections.append((f"target.{target_name}.{section_name}", dependencies))
|
||||
|
||||
return sections
|
||||
|
||||
|
||||
def dependency_entry_label(section_name: str, dependency_name: str) -> str:
|
||||
return f"[{section_name}].{dependency_name}"
|
||||
|
||||
|
||||
def is_internal_dependency(
|
||||
manifest_path: Path,
|
||||
dependency_name: str,
|
||||
dependency: dict,
|
||||
internal_package_names: set[str],
|
||||
) -> bool:
|
||||
package_name = dependency.get("package", dependency_name)
|
||||
if isinstance(package_name, str) and package_name in internal_package_names:
|
||||
return True
|
||||
|
||||
dependency_path = dependency.get("path")
|
||||
if not isinstance(dependency_path, str):
|
||||
return False
|
||||
|
||||
resolved_dependency_path = (manifest_path.parent / dependency_path).resolve()
|
||||
try:
|
||||
resolved_dependency_path.relative_to(CARGO_RS_ROOT)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def add_unused_exception_errors(
|
||||
failures_by_path: dict[str, list[str]],
|
||||
used_manifest_feature_exceptions: set[str],
|
||||
used_optional_dependency_exceptions: set[tuple[str, str, str]],
|
||||
used_internal_dependency_feature_exceptions: set[tuple[str, str, str]],
|
||||
) -> None:
|
||||
for path_key in sorted(
|
||||
set(MANIFEST_FEATURE_EXCEPTIONS) - used_manifest_feature_exceptions
|
||||
):
|
||||
add_failure(
|
||||
failures_by_path,
|
||||
path_key,
|
||||
"remove the stale `[features]` exception from "
|
||||
"`MANIFEST_FEATURE_EXCEPTIONS`",
|
||||
)
|
||||
|
||||
for path_key, section_name, dependency_name in sorted(
|
||||
OPTIONAL_DEPENDENCY_EXCEPTIONS - used_optional_dependency_exceptions
|
||||
):
|
||||
add_failure(
|
||||
failures_by_path,
|
||||
path_key,
|
||||
"remove the stale optional-dependency exception for "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}` from "
|
||||
"`OPTIONAL_DEPENDENCY_EXCEPTIONS`",
|
||||
)
|
||||
|
||||
for path_key, section_name, dependency_name in sorted(
|
||||
set(INTERNAL_DEPENDENCY_FEATURE_EXCEPTIONS)
|
||||
- used_internal_dependency_feature_exceptions
|
||||
):
|
||||
add_failure(
|
||||
failures_by_path,
|
||||
path_key,
|
||||
"remove the stale internal dependency feature exception for "
|
||||
f"`{dependency_entry_label(section_name, dependency_name)}` from "
|
||||
"`INTERNAL_DEPENDENCY_FEATURE_EXCEPTIONS`",
|
||||
)
|
||||
|
||||
|
||||
def add_failure(failures_by_path: dict[str, list[str]], path_key: str, error: str) -> None:
|
||||
failures_by_path.setdefault(path_key, []).append(error)
|
||||
|
||||
|
||||
def workspace_package_names() -> set[str]:
|
||||
package_names = set()
|
||||
for path in cargo_manifests():
|
||||
manifest = load_manifest(path)
|
||||
package = manifest.get("package")
|
||||
if not isinstance(package, dict):
|
||||
continue
|
||||
package_name = package.get("name")
|
||||
if isinstance(package_name, str):
|
||||
package_names.add(package_name)
|
||||
return package_names
|
||||
|
||||
|
||||
def load_manifest(path: Path) -> dict:
|
||||
return tomllib.loads(path.read_text())
|
||||
|
||||
|
||||
def cargo_manifests() -> list[Path]:
|
||||
return sorted(
|
||||
path
|
||||
for path in CARGO_RS_ROOT.rglob("Cargo.toml")
|
||||
if path != CARGO_RS_ROOT / "Cargo.toml"
|
||||
)
|
||||
|
||||
|
||||
def manifests_to_verify() -> list[Path]:
|
||||
return [CARGO_RS_ROOT / "Cargo.toml", *cargo_manifests()]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
89
reference/openai-codex/.github/scripts/verify_tui_core_boundary.py
vendored
Normal file
89
reference/openai-codex/.github/scripts/verify_tui_core_boundary.py
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Verify codex-tui does not depend on or import codex-core directly."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
TUI_ROOT = ROOT / "codex-rs" / "tui"
|
||||
TUI_MANIFEST = TUI_ROOT / "Cargo.toml"
|
||||
FORBIDDEN_PACKAGE = "codex-core"
|
||||
FORBIDDEN_SOURCE_PATTERNS = (
|
||||
re.compile(r"\bcodex_core::"),
|
||||
re.compile(r"\buse\s+codex_core\b"),
|
||||
re.compile(r"\bextern\s+crate\s+codex_core\b"),
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
failures = []
|
||||
failures.extend(manifest_failures())
|
||||
failures.extend(source_failures())
|
||||
|
||||
if not failures:
|
||||
return 0
|
||||
|
||||
print("codex-tui must not depend on or import codex-core directly.")
|
||||
print(
|
||||
"Use the app-server protocol/client boundary instead; temporary embedded "
|
||||
"startup gaps belong behind codex_app_server_client::legacy_core."
|
||||
)
|
||||
print()
|
||||
for failure in failures:
|
||||
print(f"- {failure}")
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def manifest_failures() -> list[str]:
|
||||
manifest = tomllib.loads(TUI_MANIFEST.read_text())
|
||||
failures = []
|
||||
for section_name, dependencies in dependency_sections(manifest):
|
||||
if FORBIDDEN_PACKAGE in dependencies:
|
||||
failures.append(
|
||||
f"{relative_path(TUI_MANIFEST)} declares `{FORBIDDEN_PACKAGE}` "
|
||||
f"in `[{section_name}]`"
|
||||
)
|
||||
return failures
|
||||
|
||||
|
||||
def dependency_sections(manifest: dict) -> list[tuple[str, dict]]:
|
||||
sections: list[tuple[str, dict]] = []
|
||||
for section_name in ("dependencies", "dev-dependencies", "build-dependencies"):
|
||||
dependencies = manifest.get(section_name)
|
||||
if isinstance(dependencies, dict):
|
||||
sections.append((section_name, dependencies))
|
||||
|
||||
for target_name, target in manifest.get("target", {}).items():
|
||||
if not isinstance(target, dict):
|
||||
continue
|
||||
for section_name in ("dependencies", "dev-dependencies", "build-dependencies"):
|
||||
dependencies = target.get(section_name)
|
||||
if isinstance(dependencies, dict):
|
||||
sections.append((f'target.{target_name}.{section_name}', dependencies))
|
||||
|
||||
return sections
|
||||
|
||||
|
||||
def source_failures() -> list[str]:
|
||||
failures = []
|
||||
for path in sorted(TUI_ROOT.glob("**/*.rs")):
|
||||
text = path.read_text()
|
||||
for line_number, line in enumerate(text.splitlines(), start=1):
|
||||
if any(pattern.search(line) for pattern in FORBIDDEN_SOURCE_PATTERNS):
|
||||
failures.append(f"{relative_path(path)}:{line_number} imports `codex_core`")
|
||||
return failures
|
||||
|
||||
|
||||
def relative_path(path: Path) -> str:
|
||||
return str(path.relative_to(ROOT))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
20
reference/openai-codex/.github/workflows/Dockerfile.bazel
vendored
Normal file
20
reference/openai-codex/.github/workflows/Dockerfile.bazel
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# TODO(mbolin): Published to docker.io/mbolin491/codex-bazel:latest for
|
||||
# initial debugging, but we should publish to a more proper location.
|
||||
#
|
||||
# docker buildx create --use
|
||||
# docker buildx build --platform linux/amd64,linux/arm64 -f .github/workflows/Dockerfile.bazel -t mbolin491/codex-bazel:latest --push .
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl git python3 ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install dotslash.
|
||||
RUN curl -LSfs "https://github.com/facebook/dotslash/releases/download/v0.5.8/dotslash-ubuntu-22.04.$(uname -m).tar.gz" | tar fxz - -C /usr/local/bin
|
||||
|
||||
# Ubuntu 24.04 ships with user 'ubuntu' already created with UID 1000.
|
||||
USER ubuntu
|
||||
|
||||
WORKDIR /workspace
|
||||
34
reference/openai-codex/.github/workflows/README.md
vendored
Normal file
34
reference/openai-codex/.github/workflows/README.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# Workflow Strategy
|
||||
|
||||
The workflows in this directory are split so that pull requests get fast, review-friendly signal while `main` still gets the full cross-platform verification pass.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- `bazel.yml` is the main pre-merge verification path for Rust code.
|
||||
It runs Bazel `test` and Bazel `clippy` on the supported Bazel targets,
|
||||
including the generated Rust test binaries needed to lint inline `#[cfg(test)]`
|
||||
code.
|
||||
- `rust-ci.yml` keeps the Cargo-native PR checks intentionally small:
|
||||
- `cargo fmt --check`
|
||||
- `cargo shear`
|
||||
- `argument-comment-lint` on Linux, macOS, and Windows
|
||||
- `tools/argument-comment-lint` package tests when the lint or its workflow wiring changes
|
||||
|
||||
## Post-Merge On `main`
|
||||
|
||||
- `bazel.yml` also runs on pushes to `main`.
|
||||
This re-verifies the merged Bazel path and helps keep the BuildBuddy caches warm.
|
||||
- `rust-ci-full.yml` is the full Cargo-native verification workflow.
|
||||
It keeps the heavier checks off the PR path while still validating them after merge:
|
||||
- the full Cargo `clippy` matrix
|
||||
- the full Cargo `nextest` matrix via per-platform archive-backed shards
|
||||
- Windows ARM64 nextest archives cross-compiled on Windows x64, then replayed on native Windows ARM64 shards
|
||||
- release-profile Cargo builds
|
||||
- cross-platform `argument-comment-lint`
|
||||
- Linux remote-env tests
|
||||
|
||||
## Rule Of Thumb
|
||||
|
||||
- If a build/test/clippy check can be expressed in Bazel, prefer putting the PR-time version in `bazel.yml`.
|
||||
- Keep `rust-ci.yml` fast enough that it usually does not dominate PR latency.
|
||||
- Reserve `rust-ci-full.yml` for heavyweight Cargo-native coverage that Bazel does not replace yet.
|
||||
518
reference/openai-codex/.github/workflows/bazel.yml
vendored
Normal file
518
reference/openai-codex/.github/workflows/bazel.yml
vendored
Normal file
@@ -0,0 +1,518 @@
|
||||
name: Bazel
|
||||
|
||||
# Note this workflow was originally derived from:
|
||||
# https://github.com/cerisier/toolchains_llvm_bootstrapped/blob/main/.github/workflows/ci.yaml
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# Cancel previous actions from the same PR or branch except 'main' branch.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency and https://docs.github.com/en/actions/learn-github-actions/contexts for more info.
|
||||
group: concurrency-group::${{ github.workflow }}::${{ github.event.pull_request.number > 0 && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}${{ github.ref_name == 'main' && format('::{0}', github.run_id) || ''}}
|
||||
cancel-in-progress: ${{ github.ref_name != 'main' }}
|
||||
jobs:
|
||||
test:
|
||||
# PRs use the sharded Windows cross-compiled test jobs below. Post-merge
|
||||
# pushes to main also run the native Windows test job for broader Windows
|
||||
# signal without putting PR latency back on the critical path. Cargo CI
|
||||
# owns V8/code-mode test coverage for now.
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# macOS
|
||||
- os: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
- os: macos-15-xlarge
|
||||
target: x86_64-apple-darwin
|
||||
|
||||
# Linux
|
||||
- os: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-musl
|
||||
# 2026-02-27 Bazel tests have been flaky on arm in CI.
|
||||
# Disable until we can investigate and stabilize them.
|
||||
# - os: ubuntu-24.04-arm
|
||||
# target: aarch64-unknown-linux-musl
|
||||
# - os: ubuntu-24.04-arm
|
||||
# target: aarch64-unknown-linux-gnu
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
# Configure a human readable name for each job
|
||||
name: Bazel test on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check rusty_v8 MODULE.bazel checksums
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: |
|
||||
python3 .github/scripts/rusty_v8_bazel.py check-module-bazel
|
||||
python3 -m unittest discover -s .github/scripts -p test_rusty_v8_bazel.py
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
cache-scope: bazel-${{ github.job }}
|
||||
install-test-prereqs: "true"
|
||||
- name: Check MODULE.bazel.lock is up to date
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: ./scripts/check-module-bazel-lock.sh
|
||||
|
||||
- name: bazel test //...
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
bazel_targets=(
|
||||
//...
|
||||
# Keep standalone V8 library targets out of the ordinary Bazel CI
|
||||
# path. V8 consumers under `//codex-rs/...` still participate
|
||||
# transitively through `//...`.
|
||||
-//third_party/v8:all
|
||||
# V8-backed code-mode tests are covered by Cargo CI. Bazel CI
|
||||
# cross-compiles in several legs, and those tests are not stable in
|
||||
# that setup yet.
|
||||
-//codex-rs/code-mode:code-mode-unit-tests
|
||||
-//codex-rs/v8-poc:v8-poc-unit-tests
|
||||
)
|
||||
|
||||
bazel_wrapper_args=(
|
||||
--print-failed-action-summary
|
||||
--print-failed-test-logs
|
||||
)
|
||||
bazel_test_args=(
|
||||
test
|
||||
--test_tag_filters=-argument-comment-lint
|
||||
--test_verbose_timeout_warnings
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
)
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
"${bazel_wrapper_args[@]}" \
|
||||
-- \
|
||||
"${bazel_test_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}"
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bazel-execution-logs-test-${{ matrix.target }}
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
||||
|
||||
test-windows-shard:
|
||||
# Split the Windows Bazel test leg across separate Windows
|
||||
# hosts. Each shard still uses Linux RBE for build actions, but the test
|
||||
# execution itself happens on its own Windows runner.
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
runs-on: windows-latest
|
||||
name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm shard ${{ matrix.shard }}/4
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: x86_64-pc-windows-gnullvm
|
||||
# Reuse the former monolithic Windows test cache for restores. Do
|
||||
# not save it from every shard below; duplicate uploads would sit on
|
||||
# the PR-blocking critical path after the useful test work is done.
|
||||
cache-scope: bazel-test
|
||||
install-test-prereqs: "true"
|
||||
|
||||
- name: bazel test shard
|
||||
env:
|
||||
BAZEL_TEST_SHARD: ${{ matrix.shard }}
|
||||
BAZEL_TEST_SHARD_COUNT: 4
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
bazel_test_query='tests(//...) except tests(//third_party/v8:all) except //codex-rs/code-mode:code-mode-unit-tests except //codex-rs/v8-poc:v8-poc-unit-tests except attr(tags, "manual", tests(//...))'
|
||||
mapfile -t bazel_targets < <(
|
||||
MSYS2_ARG_CONV_EXCL='*' bazel query --output=label "${bazel_test_query}" \
|
||||
| LC_ALL=C sort
|
||||
)
|
||||
|
||||
selected_targets=()
|
||||
for bazel_target in "${bazel_targets[@]}"; do
|
||||
target_bucket="$(
|
||||
printf '%s\n' "${bazel_target}" \
|
||||
| cksum \
|
||||
| awk -v shard_count="${BAZEL_TEST_SHARD_COUNT}" '{ print ($1 % shard_count) + 1 }'
|
||||
)"
|
||||
if [[ "${target_bucket}" == "${BAZEL_TEST_SHARD}" ]]; then
|
||||
selected_targets+=("${bazel_target}")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#selected_targets[@]} -eq 0 ]]; then
|
||||
echo "No Bazel test targets selected for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Selected ${#selected_targets[@]} of ${#bazel_targets[@]} Bazel test targets for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}."
|
||||
|
||||
bazel_test_args=(
|
||||
test
|
||||
--skip_incompatible_explicit_targets
|
||||
--test_tag_filters=-argument-comment-lint
|
||||
--test_verbose_timeout_warnings
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
--build_metadata=TAG_windows_test_shard=${BAZEL_TEST_SHARD}
|
||||
)
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
--print-failed-action-summary \
|
||||
--print-failed-test-logs \
|
||||
--windows-cross-compile \
|
||||
--remote-download-toplevel \
|
||||
-- \
|
||||
"${bazel_test_args[@]}" \
|
||||
-- \
|
||||
"${selected_targets[@]}"
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bazel-execution-logs-test-x86_64-pc-windows-gnullvm-shard-${{ matrix.shard }}
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
test-windows:
|
||||
# Preserve the existing required-check surface while the real work happens
|
||||
# in the sharded Windows jobs above.
|
||||
if: always()
|
||||
needs: test-windows-shard
|
||||
runs-on: ubuntu-24.04
|
||||
name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm
|
||||
|
||||
steps:
|
||||
- name: Confirm Windows Bazel test shards passed
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ needs.test-windows-shard.result }}" != "success" ]]; then
|
||||
echo "Windows Bazel test shards finished with result: ${{ needs.test-windows-shard.result }}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-windows-native-main:
|
||||
# Native Windows Bazel tests are slower and frequently approach the
|
||||
# 30-minute PR budget. Run this only for post-merge commits to main and give
|
||||
# it a larger timeout.
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
timeout-minutes: 40
|
||||
runs-on: windows-latest
|
||||
name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm (native main)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: x86_64-pc-windows-gnullvm
|
||||
cache-scope: bazel-${{ github.job }}
|
||||
install-test-prereqs: "true"
|
||||
|
||||
- name: bazel test //...
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
bazel_targets=(
|
||||
//...
|
||||
# Keep standalone V8 library targets out of the ordinary Bazel CI
|
||||
# path. V8 consumers under `//codex-rs/...` still participate
|
||||
# transitively through `//...`.
|
||||
-//third_party/v8:all
|
||||
# Keep this aligned with the main Bazel job. The native Windows
|
||||
# job preserves broad post-merge coverage, but code-mode/V8 tests
|
||||
# are covered by Cargo CI rather than Bazel for now.
|
||||
-//codex-rs/code-mode:code-mode-unit-tests
|
||||
-//codex-rs/v8-poc:v8-poc-unit-tests
|
||||
)
|
||||
|
||||
bazel_test_args=(
|
||||
test
|
||||
--test_tag_filters=-argument-comment-lint
|
||||
--test_verbose_timeout_warnings
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
--build_metadata=TAG_windows_native_main=true
|
||||
)
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
--print-failed-action-summary \
|
||||
--print-failed-test-logs \
|
||||
-- \
|
||||
"${bazel_test_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}"
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bazel-execution-logs-test-windows-native-x86_64-pc-windows-gnullvm
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
||||
|
||||
clippy:
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Keep Linux lint coverage on x64 and add the arm64 macOS path that
|
||||
# the Bazel test job already exercises. Add Windows gnullvm as well
|
||||
# so PRs get Bazel-native lint signal on the same Windows toolchain
|
||||
# that the Bazel test job uses.
|
||||
- os: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-gnullvm
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Bazel clippy on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
cache-scope: bazel-${{ github.job }}
|
||||
|
||||
- name: bazel build --config=clippy lint targets
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
bazel_clippy_args=(
|
||||
--config=clippy
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
--build_metadata=TAG_job=clippy
|
||||
)
|
||||
bazel_wrapper_args=()
|
||||
bazel_target_list_args=()
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
# Keep this aligned with the fast Windows Bazel test job: use
|
||||
# Linux RBE for clippy build actions while targeting Windows
|
||||
# gnullvm. Fork/community PRs without the BuildBuddy secret fall
|
||||
# back inside `run-bazel-ci.sh` to the previous local Windows MSVC
|
||||
# host-platform shape.
|
||||
bazel_wrapper_args+=(--windows-cross-compile)
|
||||
bazel_target_list_args+=(--windows-cross-compile)
|
||||
if [[ -z "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
# The fork fallback can see incompatible explicit Windows-cross
|
||||
# internal test binaries in the generated target list. Preserve
|
||||
# the old local-fallback behavior there.
|
||||
bazel_clippy_args+=(--skip_incompatible_explicit_targets)
|
||||
fi
|
||||
fi
|
||||
|
||||
bazel_target_lines="$(./scripts/list-bazel-clippy-targets.sh "${bazel_target_list_args[@]}")"
|
||||
bazel_targets=()
|
||||
while IFS= read -r target; do
|
||||
bazel_targets+=("${target}")
|
||||
done <<< "${bazel_target_lines}"
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
--print-failed-action-summary \
|
||||
"${bazel_wrapper_args[@]}" \
|
||||
-- \
|
||||
build \
|
||||
"${bazel_clippy_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}"
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bazel-execution-logs-clippy-${{ matrix.target }}
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
||||
|
||||
verify-release-build:
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-gnullvm
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Verify release build on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
cache-scope: bazel-${{ github.job }}
|
||||
|
||||
- name: bazel build verify-release-build targets
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
# This job exists to compile Rust code behind
|
||||
# `cfg(not(debug_assertions))` so PR CI catches failures that would
|
||||
# otherwise show up only in a release build. We do not need the full
|
||||
# optimizer and debug-info work that normally comes with a release
|
||||
# build to get that signal, so keep Bazel in `fastbuild` and disable
|
||||
# Rust debug assertions explicitly.
|
||||
bazel_wrapper_args=()
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
# This is build-only signal, so use the same Linux-RBE
|
||||
# cross-compile path as the fast Windows test and clippy jobs.
|
||||
# Fork/community PRs without the BuildBuddy secret fall back
|
||||
# inside `run-bazel-ci.sh` to the previous local Windows MSVC
|
||||
# host-platform shape.
|
||||
bazel_wrapper_args+=(--windows-cross-compile)
|
||||
fi
|
||||
|
||||
bazel_build_args=(
|
||||
--compilation_mode=fastbuild
|
||||
--@rules_rust//rust/settings:extra_rustc_flag=-Cdebug-assertions=no
|
||||
--@rules_rust//rust/settings:extra_exec_rustc_flag=-Cdebug-assertions=no
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
--build_metadata=TAG_job=verify-release-build
|
||||
--build_metadata=TAG_rust_debug_assertions=off
|
||||
)
|
||||
|
||||
bazel_target_lines="$(bash ./scripts/list-bazel-release-targets.sh)"
|
||||
bazel_targets=()
|
||||
while IFS= read -r target; do
|
||||
bazel_targets+=("${target}")
|
||||
done <<< "${bazel_target_lines}"
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
"${bazel_wrapper_args[@]}" \
|
||||
-- \
|
||||
build \
|
||||
"${bazel_build_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}"
|
||||
|
||||
- name: Verify Bazel builds bwrap
|
||||
if: runner.os == 'Linux'
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
--remote-download-toplevel \
|
||||
--print-failed-action-summary \
|
||||
-- \
|
||||
build \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \
|
||||
--build_metadata=TAG_job=verify-bwrap \
|
||||
-- \
|
||||
//codex-rs/bwrap:bwrap
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bazel-execution-logs-verify-release-build-${{ matrix.target }}
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
||||
34
reference/openai-codex/.github/workflows/blob-size-policy.yml
vendored
Normal file
34
reference/openai-codex/.github/workflows/blob-size-policy.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: blob-size-policy
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Blob size policy
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Determine PR comparison range
|
||||
id: range
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT"
|
||||
echo "head=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check changed blob sizes
|
||||
env:
|
||||
BASE_SHA: ${{ steps.range.outputs.base }}
|
||||
HEAD_SHA: ${{ steps.range.outputs.head }}
|
||||
run: |
|
||||
python3 scripts/check_blob_size.py \
|
||||
--base "$BASE_SHA" \
|
||||
--head "$HEAD_SHA" \
|
||||
--max-bytes 512000 \
|
||||
--allowlist .github/blob-size-allowlist.txt
|
||||
29
reference/openai-codex/.github/workflows/cargo-deny.yml
vendored
Normal file
29
reference/openai-codex/.github/workflows/cargo-deny.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: cargo-deny
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
cargo-deny:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./codex-rs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
|
||||
- name: Run cargo-deny
|
||||
uses: EmbarkStudios/cargo-deny-action@82eb9f621fbc699dd0918f3ea06864c14cc84246 # v2
|
||||
with:
|
||||
rust-version: 1.93.0
|
||||
manifest-path: ./codex-rs/Cargo.toml
|
||||
78
reference/openai-codex/.github/workflows/ci.yml
vendored
Normal file
78
reference/openai-codex/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
push: { branches: [main] }
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Verify codex-rs Cargo manifests inherit workspace settings
|
||||
run: python3 .github/scripts/verify_cargo_workspace_manifests.py
|
||||
|
||||
- name: Verify codex-tui does not import codex-core directly
|
||||
run: python3 .github/scripts/verify_tui_core_boundary.py
|
||||
|
||||
- name: Verify Bazel clippy flags match Cargo workspace lints
|
||||
run: python3 .github/scripts/verify_bazel_clippy_lints.py
|
||||
|
||||
- name: Test Codex package builder
|
||||
run: python3 -m unittest discover -s scripts/codex_package -p 'test_*.py'
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Stage npm package
|
||||
id: stage_npm_package
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Use a recent successful rust-release run that published the full
|
||||
# cross-platform native payload required by the npm package layout.
|
||||
# Passing the workflow URL directly avoids relying on old rust-v*
|
||||
# branches remaining discoverable via `gh run list --branch ...`.
|
||||
CODEX_VERSION=0.133.0-alpha.4
|
||||
WORKFLOW_URL="https://github.com/openai/codex/actions/runs/26201494185"
|
||||
OUTPUT_DIR="${RUNNER_TEMP}"
|
||||
python3 ./scripts/stage_npm_packages.py \
|
||||
--release-version "$CODEX_VERSION" \
|
||||
--workflow-url "$WORKFLOW_URL" \
|
||||
--package codex \
|
||||
--output-dir "$OUTPUT_DIR"
|
||||
PACK_OUTPUT="${OUTPUT_DIR}/codex-npm-${CODEX_VERSION}.tgz"
|
||||
echo "pack_output=$PACK_OUTPUT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload staged npm package artifact
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: codex-npm-staging
|
||||
path: ${{ steps.stage_npm_package.outputs.pack_output }}
|
||||
|
||||
- name: Ensure root README.md contains only ASCII and certain Unicode code points
|
||||
run: ./scripts/asciicheck.py README.md
|
||||
- name: Check root README ToC
|
||||
run: python3 scripts/readme_toc.py README.md
|
||||
|
||||
- name: Prettier (run `pnpm run format:fix` to fix)
|
||||
run: pnpm run format
|
||||
49
reference/openai-codex/.github/workflows/cla.yml
vendored
Normal file
49
reference/openai-codex/.github/workflows/cla.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: CLA Assistant
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types: [opened, closed, synchronize]
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
|
||||
jobs:
|
||||
cla:
|
||||
# Only run the CLA assistant for the canonical openai repo so forks are not blocked
|
||||
# and contributors who signed previously do not receive duplicate CLA notifications.
|
||||
if: ${{ github.repository_owner == 'openai' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
|
||||
# Run on close only if the PR was merged. This will lock the PR to preserve
|
||||
# the CLA agreement. We don't want to lock PRs that have been closed without
|
||||
# merging because the contributor may want to respond with additional comments.
|
||||
# This action has a "lock-pullrequest-aftermerge" option that can be set to false,
|
||||
# but that would unconditionally skip locking even in cases where the PR was merged.
|
||||
if: |
|
||||
(
|
||||
github.event_name == 'pull_request_target' &&
|
||||
(
|
||||
github.event.action == 'opened' ||
|
||||
github.event.action == 'synchronize' ||
|
||||
(github.event.action == 'closed' && github.event.pull_request.merged == true)
|
||||
)
|
||||
) ||
|
||||
(
|
||||
github.event_name == 'issue_comment' &&
|
||||
(
|
||||
github.event.comment.body == 'recheck' ||
|
||||
github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA'
|
||||
)
|
||||
)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
path-to-document: https://github.com/openai/codex/blob/main/docs/CLA.md
|
||||
path-to-signatures: signatures/cla.json
|
||||
branch: cla-signatures
|
||||
allowlist: codex,dependabot,dependabot[bot],github-actions[bot]
|
||||
107
reference/openai-codex/.github/workflows/close-stale-contributor-prs.yml
vendored
Normal file
107
reference/openai-codex/.github/workflows/close-stale-contributor-prs.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Close stale contributor PRs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 6 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
close-stale-contributor-prs:
|
||||
# Prevent scheduled runs on forks
|
||||
if: github.repository == 'openai/codex'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close inactive PRs from contributors
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const DAYS_INACTIVE = 14;
|
||||
const cutoff = new Date(Date.now() - DAYS_INACTIVE * 24 * 60 * 60 * 1000);
|
||||
const { owner, repo } = context.repo;
|
||||
const dryRun = false;
|
||||
const stalePrs = [];
|
||||
|
||||
core.info(`Dry run mode: ${dryRun}`);
|
||||
|
||||
const prs = await github.paginate(github.rest.pulls.list, {
|
||||
owner,
|
||||
repo,
|
||||
state: "open",
|
||||
per_page: 100,
|
||||
sort: "updated",
|
||||
direction: "asc",
|
||||
});
|
||||
|
||||
for (const pr of prs) {
|
||||
const lastUpdated = new Date(pr.updated_at);
|
||||
if (lastUpdated > cutoff) {
|
||||
core.info(`PR ${pr.number} is fresh`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pr.user || pr.user.type !== "User") {
|
||||
core.info(`PR ${pr.number} wasn't created by a user`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let permission;
|
||||
try {
|
||||
const permissionResponse = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner,
|
||||
repo,
|
||||
username: pr.user.login,
|
||||
});
|
||||
permission = permissionResponse.data.permission;
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
core.info(`Author ${pr.user.login} is not a collaborator; skipping #${pr.number}`);
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
const hasContributorAccess = ["admin", "maintain", "write"].includes(permission);
|
||||
if (!hasContributorAccess) {
|
||||
core.info(`Author ${pr.user.login} has ${permission} access; skipping #${pr.number}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
stalePrs.push(pr);
|
||||
}
|
||||
|
||||
if (!stalePrs.length) {
|
||||
core.info("No stale contributor pull requests found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const pr of stalePrs) {
|
||||
const issue_number = pr.number;
|
||||
const closeComment = `Closing this pull request because it has had no updates for more than ${DAYS_INACTIVE} days. If you plan to continue working on it, feel free to reopen or open a new PR.`;
|
||||
|
||||
if (dryRun) {
|
||||
core.info(`[dry-run] Would close contributor PR #${issue_number} from ${pr.user.login}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
body: closeComment,
|
||||
});
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: issue_number,
|
||||
state: "closed",
|
||||
});
|
||||
|
||||
core.info(`Closed contributor PR #${issue_number} from ${pr.user.login}`);
|
||||
}
|
||||
30
reference/openai-codex/.github/workflows/codespell.yml
vendored
Normal file
30
reference/openai-codex/.github/workflows/codespell.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Codespell configuration is within .codespellrc
|
||||
---
|
||||
name: Codespell
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
name: Check for spelling errors
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
- name: Annotate locations with typos
|
||||
uses: codespell-project/codespell-problem-matcher@b80729f885d32f78a716c2f107b4db1025001c42 # v1.1.0
|
||||
- name: Codespell
|
||||
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2
|
||||
with:
|
||||
ignore_words_file: .codespellignore
|
||||
420
reference/openai-codex/.github/workflows/issue-deduplicator.yml
vendored
Normal file
420
reference/openai-codex/.github/workflows/issue-deduplicator.yml
vendored
Normal file
@@ -0,0 +1,420 @@
|
||||
name: Issue Deduplicator
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
gather-duplicates-all:
|
||||
name: Identify potential duplicates (all issues)
|
||||
# Prevent runs on forks (requires OpenAI API key, wastes Actions minutes)
|
||||
if: github.repository == 'openai/codex' && (github.event.action == 'opened' || (github.event.action == 'labeled' && github.event.label.name == 'codex-deduplicate'))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
codex_output: ${{ steps.codex-all.outputs.final-message }}
|
||||
steps:
|
||||
- name: Prepare Codex inputs
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
|
||||
CURRENT_ISSUE_FILE=codex-current-issue.json
|
||||
EXISTING_ALL_FILE=codex-existing-issues-all.json
|
||||
|
||||
gh issue list --repo "$REPO" \
|
||||
--json number,title,body,createdAt,updatedAt,state,labels \
|
||||
--limit 1000 \
|
||||
--state all \
|
||||
--search "sort:created-desc" \
|
||||
| jq '[.[] | {
|
||||
number,
|
||||
title,
|
||||
body: ((.body // "")[0:4000]),
|
||||
createdAt,
|
||||
updatedAt,
|
||||
state,
|
||||
labels: ((.labels // []) | map(.name))
|
||||
}]' \
|
||||
> "$EXISTING_ALL_FILE"
|
||||
|
||||
gh issue view "$ISSUE_NUMBER" \
|
||||
--repo "$REPO" \
|
||||
--json number,title,body \
|
||||
| jq '{number, title, body: ((.body // "")[0:4000])}' \
|
||||
> "$CURRENT_ISSUE_FILE"
|
||||
|
||||
echo "Prepared duplicate detection input files."
|
||||
echo "all_issue_count=$(jq 'length' "$EXISTING_ALL_FILE")"
|
||||
|
||||
# Prompt instructions are intentionally inline in this workflow. The old
|
||||
# .github/prompts/issue-deduplicator.txt file is obsolete and removed.
|
||||
- id: codex-all
|
||||
name: Find duplicates (pass 1, all issues)
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
safety-strategy: drop-sudo
|
||||
sandbox: read-only
|
||||
prompt: |
|
||||
You are an assistant that triages new GitHub issues by identifying potential duplicates.
|
||||
|
||||
You will receive the following JSON files located in the current working directory:
|
||||
- `codex-current-issue.json`: JSON object describing the newly created issue (fields: number, title, body).
|
||||
- `codex-existing-issues-all.json`: JSON array of recent issues with states, timestamps, and labels.
|
||||
|
||||
Instructions:
|
||||
- Compare the current issue against the existing issues to find up to five that appear to describe the same underlying problem or request.
|
||||
- Prioritize concrete overlap in symptoms, reproduction details, error signatures, and user intent.
|
||||
- Prefer active unresolved issues when confidence is similar.
|
||||
- Closed issues can still be valid duplicates if they clearly match.
|
||||
- Return fewer matches rather than speculative ones.
|
||||
- If confidence is low, return an empty list.
|
||||
- Include at most five issue numbers.
|
||||
- After analysis, provide a short reason for your decision.
|
||||
|
||||
output-schema: |
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"reason": { "type": "string" }
|
||||
},
|
||||
"required": ["issues", "reason"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
normalize-duplicates-all:
|
||||
name: Normalize pass 1 output
|
||||
needs: gather-duplicates-all
|
||||
if: ${{ needs.gather-duplicates-all.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
outputs:
|
||||
issues_json: ${{ steps.normalize-all.outputs.issues_json }}
|
||||
reason: ${{ steps.normalize-all.outputs.reason }}
|
||||
has_matches: ${{ steps.normalize-all.outputs.has_matches }}
|
||||
steps:
|
||||
- id: normalize-all
|
||||
name: Normalize pass 1 output
|
||||
env:
|
||||
CODEX_OUTPUT: ${{ needs.gather-duplicates-all.outputs.codex_output }}
|
||||
CURRENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
|
||||
raw=${CODEX_OUTPUT//$'\r'/}
|
||||
parsed=false
|
||||
issues='[]'
|
||||
reason=''
|
||||
|
||||
if [ -n "$raw" ] && printf '%s' "$raw" | jq -e 'type == "object" and (.issues | type == "array")' >/dev/null 2>&1; then
|
||||
parsed=true
|
||||
issues=$(printf '%s' "$raw" | jq -c '[.issues[] | tostring]')
|
||||
reason=$(printf '%s' "$raw" | jq -r '.reason // ""')
|
||||
else
|
||||
reason='Pass 1 output was empty or invalid JSON.'
|
||||
fi
|
||||
|
||||
filtered=$(jq -cn --argjson issues "$issues" --arg current "$CURRENT_ISSUE_NUMBER" '[
|
||||
$issues[]
|
||||
| tostring
|
||||
| select(. != $current)
|
||||
] | reduce .[] as $issue ([]; if index($issue) then . else . + [$issue] end) | .[:5]')
|
||||
|
||||
has_matches=false
|
||||
if [ "$(jq 'length' <<< "$filtered")" -gt 0 ]; then
|
||||
has_matches=true
|
||||
fi
|
||||
|
||||
echo "Pass 1 parsed: $parsed"
|
||||
echo "Pass 1 matches after filtering: $(jq 'length' <<< "$filtered")"
|
||||
echo "Pass 1 reason: $reason"
|
||||
|
||||
{
|
||||
echo "issues_json=$filtered"
|
||||
echo "reason<<EOF"
|
||||
echo "$reason"
|
||||
echo "EOF"
|
||||
echo "has_matches=$has_matches"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
gather-duplicates-open:
|
||||
name: Identify potential duplicates (open issues fallback)
|
||||
# Pass 1 Codex execution drops sudo on its runner, so run the fallback in a fresh job.
|
||||
needs: normalize-duplicates-all
|
||||
if: ${{ needs.normalize-duplicates-all.result == 'success' && needs.normalize-duplicates-all.outputs.has_matches != 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
codex_output: ${{ steps.codex-open.outputs.final-message }}
|
||||
steps:
|
||||
- name: Prepare Codex inputs
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
|
||||
CURRENT_ISSUE_FILE=codex-current-issue.json
|
||||
EXISTING_OPEN_FILE=codex-existing-issues-open.json
|
||||
|
||||
gh issue list --repo "$REPO" \
|
||||
--json number,title,body,createdAt,updatedAt,state,labels \
|
||||
--limit 1000 \
|
||||
--state open \
|
||||
--search "sort:created-desc" \
|
||||
| jq '[.[] | {
|
||||
number,
|
||||
title,
|
||||
body: ((.body // "")[0:4000]),
|
||||
createdAt,
|
||||
updatedAt,
|
||||
state,
|
||||
labels: ((.labels // []) | map(.name))
|
||||
}]' \
|
||||
> "$EXISTING_OPEN_FILE"
|
||||
|
||||
gh issue view "$ISSUE_NUMBER" \
|
||||
--repo "$REPO" \
|
||||
--json number,title,body \
|
||||
| jq '{number, title, body: ((.body // "")[0:4000])}' \
|
||||
> "$CURRENT_ISSUE_FILE"
|
||||
|
||||
echo "Prepared fallback duplicate detection input files."
|
||||
echo "open_issue_count=$(jq 'length' "$EXISTING_OPEN_FILE")"
|
||||
|
||||
- id: codex-open
|
||||
name: Find duplicates (pass 2, open issues)
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
safety-strategy: drop-sudo
|
||||
sandbox: read-only
|
||||
prompt: |
|
||||
You are an assistant that triages new GitHub issues by identifying potential duplicates.
|
||||
|
||||
This is a fallback pass because a broad search did not find convincing matches.
|
||||
|
||||
You will receive the following JSON files located in the current working directory:
|
||||
- `codex-current-issue.json`: JSON object describing the newly created issue (fields: number, title, body).
|
||||
- `codex-existing-issues-open.json`: JSON array of open issues only.
|
||||
|
||||
Instructions:
|
||||
- Search only these active unresolved issues for duplicates of the current issue.
|
||||
- Prioritize concrete overlap in symptoms, reproduction details, error signatures, and user intent.
|
||||
- Prefer fewer, higher-confidence matches.
|
||||
- If confidence is low, return an empty list.
|
||||
- Include at most five issue numbers.
|
||||
- After analysis, provide a short reason for your decision.
|
||||
|
||||
output-schema: |
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"reason": { "type": "string" }
|
||||
},
|
||||
"required": ["issues", "reason"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
normalize-duplicates-open:
|
||||
name: Normalize pass 2 output
|
||||
needs: gather-duplicates-open
|
||||
if: ${{ needs.gather-duplicates-open.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
outputs:
|
||||
issues_json: ${{ steps.normalize-open.outputs.issues_json }}
|
||||
reason: ${{ steps.normalize-open.outputs.reason }}
|
||||
has_matches: ${{ steps.normalize-open.outputs.has_matches }}
|
||||
steps:
|
||||
- id: normalize-open
|
||||
name: Normalize pass 2 output
|
||||
env:
|
||||
CODEX_OUTPUT: ${{ needs.gather-duplicates-open.outputs.codex_output }}
|
||||
CURRENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
|
||||
raw=${CODEX_OUTPUT//$'\r'/}
|
||||
parsed=false
|
||||
issues='[]'
|
||||
reason=''
|
||||
|
||||
if [ -n "$raw" ] && printf '%s' "$raw" | jq -e 'type == "object" and (.issues | type == "array")' >/dev/null 2>&1; then
|
||||
parsed=true
|
||||
issues=$(printf '%s' "$raw" | jq -c '[.issues[] | tostring]')
|
||||
reason=$(printf '%s' "$raw" | jq -r '.reason // ""')
|
||||
else
|
||||
reason='Pass 2 output was empty or invalid JSON.'
|
||||
fi
|
||||
|
||||
filtered=$(jq -cn --argjson issues "$issues" --arg current "$CURRENT_ISSUE_NUMBER" '[
|
||||
$issues[]
|
||||
| tostring
|
||||
| select(. != $current)
|
||||
] | reduce .[] as $issue ([]; if index($issue) then . else . + [$issue] end) | .[:5]')
|
||||
|
||||
has_matches=false
|
||||
if [ "$(jq 'length' <<< "$filtered")" -gt 0 ]; then
|
||||
has_matches=true
|
||||
fi
|
||||
|
||||
echo "Pass 2 parsed: $parsed"
|
||||
echo "Pass 2 matches after filtering: $(jq 'length' <<< "$filtered")"
|
||||
echo "Pass 2 reason: $reason"
|
||||
|
||||
{
|
||||
echo "issues_json=$filtered"
|
||||
echo "reason<<EOF"
|
||||
echo "$reason"
|
||||
echo "EOF"
|
||||
echo "has_matches=$has_matches"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
select-final:
|
||||
name: Select final duplicate set
|
||||
needs:
|
||||
- normalize-duplicates-all
|
||||
- normalize-duplicates-open
|
||||
if: ${{ always() && needs.normalize-duplicates-all.result == 'success' && (needs.normalize-duplicates-open.result == 'success' || needs.normalize-duplicates-open.result == 'skipped') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
codex_output: ${{ steps.select-final.outputs.codex_output }}
|
||||
steps:
|
||||
- id: select-final
|
||||
name: Select final duplicate set
|
||||
env:
|
||||
PASS1_ISSUES: ${{ needs.normalize-duplicates-all.outputs.issues_json }}
|
||||
PASS1_REASON: ${{ needs.normalize-duplicates-all.outputs.reason }}
|
||||
PASS2_ISSUES: ${{ needs.normalize-duplicates-open.outputs.issues_json }}
|
||||
PASS2_REASON: ${{ needs.normalize-duplicates-open.outputs.reason }}
|
||||
PASS1_HAS_MATCHES: ${{ needs.normalize-duplicates-all.outputs.has_matches }}
|
||||
PASS2_HAS_MATCHES: ${{ needs.normalize-duplicates-open.outputs.has_matches }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
|
||||
selected_issues='[]'
|
||||
selected_reason='No plausible duplicates found.'
|
||||
selected_pass='none'
|
||||
|
||||
if [ "$PASS1_HAS_MATCHES" = "true" ]; then
|
||||
selected_issues=${PASS1_ISSUES:-'[]'}
|
||||
selected_reason=${PASS1_REASON:-'Pass 1 found duplicates.'}
|
||||
selected_pass='all'
|
||||
fi
|
||||
|
||||
if [ "$PASS2_HAS_MATCHES" = "true" ]; then
|
||||
selected_issues=${PASS2_ISSUES:-'[]'}
|
||||
selected_reason=${PASS2_REASON:-'Pass 2 found duplicates.'}
|
||||
selected_pass='open-fallback'
|
||||
fi
|
||||
|
||||
final_json=$(jq -cn \
|
||||
--argjson issues "$selected_issues" \
|
||||
--arg reason "$selected_reason" \
|
||||
--arg pass "$selected_pass" \
|
||||
'{issues: $issues, reason: $reason, pass: $pass}')
|
||||
|
||||
echo "Final pass used: $selected_pass"
|
||||
echo "Final duplicate count: $(jq '.issues | length' <<< "$final_json")"
|
||||
echo "Final reason: $(jq -r '.reason' <<< "$final_json")"
|
||||
|
||||
{
|
||||
echo "codex_output<<EOF"
|
||||
echo "$final_json"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
comment-on-issue:
|
||||
name: Comment with potential duplicates
|
||||
needs: select-final
|
||||
if: ${{ always() && needs.select-final.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- name: Comment on issue
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
CODEX_OUTPUT: ${{ needs.select-final.outputs.codex_output }}
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
const raw = process.env.CODEX_OUTPUT ?? '';
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(raw);
|
||||
} catch (error) {
|
||||
core.info(`Codex output was not valid JSON. Raw output: ${raw}`);
|
||||
core.info(`Parse error: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const issues = Array.isArray(parsed?.issues) ? parsed.issues : [];
|
||||
const currentIssueNumber = String(context.payload.issue.number);
|
||||
const passUsed = typeof parsed?.pass === 'string' ? parsed.pass : 'unknown';
|
||||
const reason = typeof parsed?.reason === 'string' ? parsed.reason : '';
|
||||
|
||||
console.log(`Current issue number: ${currentIssueNumber}`);
|
||||
console.log(`Pass used: ${passUsed}`);
|
||||
if (reason) {
|
||||
console.log(`Reason: ${reason}`);
|
||||
}
|
||||
console.log(issues);
|
||||
|
||||
const filteredIssues = [...new Set(issues.map((value) => String(value)))].filter((value) => value !== currentIssueNumber).slice(0, 5);
|
||||
|
||||
if (filteredIssues.length === 0) {
|
||||
core.info('Codex reported no potential duplicates.');
|
||||
return;
|
||||
}
|
||||
|
||||
const lines = [
|
||||
'Potential duplicates detected. Please review them and close your issue if it is a duplicate.',
|
||||
'',
|
||||
...filteredIssues.map((value) => `- #${String(value)}`),
|
||||
'',
|
||||
'*Powered by [Codex Action](https://github.com/openai/codex-action)*'];
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
body: lines.join("\n"),
|
||||
});
|
||||
|
||||
- name: Remove codex-deduplicate label
|
||||
if: ${{ always() && github.event.action == 'labeled' && github.event.label.name == 'codex-deduplicate' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
gh issue edit "$ISSUE_NUMBER" --remove-label codex-deduplicate || true
|
||||
echo "Attempted to remove label: codex-deduplicate"
|
||||
151
reference/openai-codex/.github/workflows/issue-labeler.yml
vendored
Normal file
151
reference/openai-codex/.github/workflows/issue-labeler.yml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
name: Issue Labeler
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
gather-labels:
|
||||
name: Generate label suggestions
|
||||
# Prevent runs on forks (requires OpenAI API key, wastes Actions minutes)
|
||||
if: github.repository == 'openai/codex' && (github.event.action == 'opened' || (github.event.action == 'labeled' && github.event.label.name == 'codex-label'))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
codex_output: ${{ steps.codex.outputs.final-message }}
|
||||
steps:
|
||||
- id: codex
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
safety-strategy: drop-sudo
|
||||
sandbox: read-only
|
||||
prompt: |
|
||||
You are an assistant that reviews GitHub issues for the repository.
|
||||
|
||||
Your job is to choose the most appropriate labels for the issue described later in this prompt.
|
||||
Follow these rules:
|
||||
|
||||
- Add one (and only one) of the following three labels to distinguish the type of issue. Default to "bug" if unsure.
|
||||
1. bug — Reproducible defects in Codex products (CLI, VS Code extension, web, auth).
|
||||
2. enhancement — Feature requests or usability improvements that ask for new capabilities, better ergonomics, or quality-of-life tweaks.
|
||||
3. documentation — Updates or corrections needed in docs/README/config references (broken links, missing examples, outdated keys, clarification requests).
|
||||
|
||||
- If applicable, add one of the following labels to specify which sub-product or product surface the issue relates to.
|
||||
1. CLI — the Codex command line interface.
|
||||
2. extension — VS Code (or other IDE) extension-specific issues.
|
||||
3. app - Issues related to the Codex desktop application.
|
||||
4. codex-web — Issues targeting the Codex web UI/Cloud experience.
|
||||
5. github-action — Issues with the Codex GitHub action.
|
||||
6. iOS — Issues with the Codex iOS app.
|
||||
|
||||
- Additionally add zero or more of the following labels that are relevant to the issue content. Prefer a small set of precise labels over many broad ones.
|
||||
- For agent-area issues, prefer the most specific applicable label. Use "agent" only as a fallback for agent-related issues that do not fit a more specific agent-area label. Prefer "app-server" over "session" or "config" when the issue is about app-server protocol, API, RPC, schema, launch, or bridge behavior. Use "memory" for agentic memory storage/retrieval and "performance" for high process memory utilization or memory leaks.
|
||||
1. windows-os — Bugs or friction specific to Windows environments (always when PowerShell is mentioned, path handling, copy/paste, OS-specific auth or tooling failures).
|
||||
2. mcp — Topics involving Model Context Protocol servers/clients.
|
||||
3. mcp-server — Problems related to the codex mcp-server command, where codex runs as an MCP server.
|
||||
4. azure — Problems or requests tied to Azure OpenAI deployments.
|
||||
5. model-behavior — Undesirable LLM behavior: forgetting goals, refusing work, hallucinating environment details, quota misreports, or other reasoning/performance anomalies.
|
||||
6. code-review — Issues related to the code review feature or functionality.
|
||||
7. safety-check - Issues related to cyber risk detection or trusted access verification.
|
||||
8. auth - Problems related to authentication, login, or access tokens.
|
||||
9. exec - Problems related to the "codex exec" command or functionality.
|
||||
10. hooks - Problems related to event hooks
|
||||
11. context - Problems related to compaction, context windows, or available context reporting.
|
||||
12. skills - Problems related to skills or plugins
|
||||
13. custom-model - Problems that involve using custom model providers, local models, or OSS models.
|
||||
14. rate-limits - Problems related to token limits, rate limits, or token usage reporting.
|
||||
15. sandbox - Issues related to local sandbox environments or tool call approvals to override sandbox restrictions.
|
||||
16. tool-calls - Problems related to specific tool call invocations including unexpected errors, failures, or hangs.
|
||||
17. TUI - Problems with the terminal user interface (TUI) including keyboard shortcuts, copy & pasting, menus, or screen update issues.
|
||||
18. app-server - Issues involving the app-server protocol or interfaces, including SDK/API payloads, thread/* and turn/* RPCs, app-server launch behavior, external app/controller bridges, and app-server protocol/schema behavior.
|
||||
19. connectivity - Network connectivity or endpoint issues, including reconnecting messages, stream dropped/disconnected errors, websocket/SSE/transport failures, timeout/network/VPN/proxy/API endpoint failures, and related retry behavior.
|
||||
20. subagent - Issues involving subagents, sub-agents, or multi-agent behavior, including spawn_agent, wait_agent, close_agent, worker/explorer roles, delegation, agent teams, lifecycle, model/config inheritance, quotas, and orchestration.
|
||||
21. session - Issues involving session or thread management, including resume, fork, archive, rename/title, thread history, rollout persistence, compaction, checkpoints, retention, and cross-session state.
|
||||
22. config - Issues involving config.toml, config keys, config key merging, config updates, profiles, hooks config, project config, agent role TOMLs, instruction/personality config, and config schema behavior.
|
||||
23. plan - Issues involving plan mode, planning workflows, or plan-specific tools/behavior.
|
||||
24. computer-use - Issues involving agentic computer use or SkyComputerUseService.
|
||||
25. browser - Issues involving agentic browser use, IAB, or the built-in browser within the Codex app.
|
||||
26. memory - Issues involving agentic memory storage and retrieval.
|
||||
27. imagen - Issues involving image generation.
|
||||
28. remote - Issues involving remote access, remote control, or SSH.
|
||||
29. performance - Issues involving slow, laggy performance, high memory utilization, or memory leaks.
|
||||
30. automations - Issues involving scheduled automation tasks or heartbeats.
|
||||
31. pets - Issues involving pets avatars and animations.
|
||||
32. agent - Fallback only for core agent loop or agent-related issues that do not fit app-server, connectivity, subagent, session, config, plan, computer-use, browser, memory, imagen, remote, performance, automations, or pets.
|
||||
|
||||
Issue number: ${{ github.event.issue.number }}
|
||||
|
||||
Issue title:
|
||||
${{ github.event.issue.title }}
|
||||
|
||||
Issue body:
|
||||
${{ github.event.issue.body }}
|
||||
|
||||
Repository full name:
|
||||
${{ github.repository }}
|
||||
|
||||
output-schema: |
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"labels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["labels"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
apply-labels:
|
||||
name: Apply labels from Codex output
|
||||
needs: gather-labels
|
||||
if: ${{ needs.gather-labels.result != 'skipped' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
CODEX_OUTPUT: ${{ needs.gather-labels.outputs.codex_output }}
|
||||
steps:
|
||||
- name: Apply labels
|
||||
run: |
|
||||
json=${CODEX_OUTPUT//$'\r'/}
|
||||
if [ -z "$json" ]; then
|
||||
echo "Codex produced no output. Skipping label application."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$json" | jq -e 'type == "object" and (.labels | type == "array")' >/dev/null 2>&1; then
|
||||
echo "Codex output did not include a labels array. Raw output: $json"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
labels=$(printf '%s' "$json" | jq -r '.labels[] | tostring')
|
||||
if [ -z "$labels" ]; then
|
||||
echo "Codex returned an empty array. Nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cmd=(gh issue edit "$ISSUE_NUMBER")
|
||||
while IFS= read -r label; do
|
||||
cmd+=(--add-label "$label")
|
||||
done <<< "$labels"
|
||||
|
||||
"${cmd[@]}" || true
|
||||
|
||||
- name: Remove codex-label trigger
|
||||
if: ${{ always() && github.event.action == 'labeled' && github.event.label.name == 'codex-label' }}
|
||||
run: |
|
||||
gh issue edit "$ISSUE_NUMBER" --remove-label codex-label || true
|
||||
echo "Attempted to remove label: codex-label"
|
||||
464
reference/openai-codex/.github/workflows/rust-ci-full-nextest-platform.yml
vendored
Normal file
464
reference/openai-codex/.github/workflows/rust-ci-full-nextest-platform.yml
vendored
Normal file
@@ -0,0 +1,464 @@
|
||||
name: rust-ci-full nextest platform
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
required: true
|
||||
type: string
|
||||
runner_group:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
runner_labels:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
archive_runner:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
archive_runner_group:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
archive_runner_labels:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
target:
|
||||
required: true
|
||||
type: string
|
||||
profile:
|
||||
required: true
|
||||
type: string
|
||||
artifact_id:
|
||||
required: true
|
||||
type: string
|
||||
remote_env:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
test_threads:
|
||||
required: false
|
||||
default: 0
|
||||
type: number
|
||||
use_sccache:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
# Caller workflow-level env does not flow through workflow_call, so keep the
|
||||
# Cargo git transport hardening on the archive and shard jobs directly here.
|
||||
env:
|
||||
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
|
||||
|
||||
jobs:
|
||||
archive:
|
||||
name: Build nextest archive
|
||||
runs-on: ${{ inputs.archive_runner_group != '' && fromJSON(format('{{"group":"{0}","labels":"{1}"}}', inputs.archive_runner_group, inputs.archive_runner_labels)) || inputs.archive_runner != '' && inputs.archive_runner || inputs.runner_group != '' && fromJSON(format('{{"group":"{0}","labels":"{1}"}}', inputs.runner_group, inputs.runner_labels)) || inputs.runner }}
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
# Windows ARM64 archives are built on Windows x64, while their shards run
|
||||
# on native Windows ARM64. Key producer-side caches by the archive runner
|
||||
# so the cross-compile build reuses the Windows x64 cache lineage.
|
||||
ARCHIVE_CACHE_RUNNER: ${{ inputs.archive_runner != '' && inputs.archive_runner || inputs.runner }}
|
||||
USE_SCCACHE: ${{ inputs.use_sccache && 'true' || 'false' }}
|
||||
CARGO_INCREMENTAL: "0"
|
||||
SCCACHE_CACHE_SIZE: 10G
|
||||
NEXTEST_ARCHIVE_FILE: nextest-${{ inputs.artifact_id }}.tar.zst
|
||||
TEST_HELPERS_ARTIFACT: nextest-test-helpers-${{ inputs.artifact_id }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure Dev Drive (Windows)
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
shell: pwsh
|
||||
run: ../.github/scripts/setup-dev-drive.ps1
|
||||
|
||||
- name: Install Linux build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
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 --no-install-recommends pkg-config libcap-dev bubblewrap
|
||||
fi
|
||||
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ inputs.target }}
|
||||
|
||||
- name: Expose MSVC SDK environment (Windows)
|
||||
if: ${{ runner.os == 'Windows' && inputs.target == 'aarch64-pc-windows-msvc' }}
|
||||
uses: ./.github/actions/setup-msvc-env
|
||||
with:
|
||||
target: ${{ inputs.target }}
|
||||
|
||||
- name: Compute lockfile hash
|
||||
id: lockhash
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "hash=$(sha256sum Cargo.lock | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
echo "toolchain_hash=$(sha256sum rust-toolchain.toml | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Restore cargo home cache
|
||||
id: cache_cargo_home_restore
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
key: cargo-home-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
||||
restore-keys: |
|
||||
cargo-home-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-
|
||||
|
||||
- name: Install sccache
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: sccache
|
||||
version: 0.7.5
|
||||
|
||||
- name: Configure sccache backend
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
|
||||
echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
|
||||
echo "Using sccache GitHub backend"
|
||||
else
|
||||
echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
|
||||
if [[ -n "${DEV_DRIVE:-}" ]]; then
|
||||
echo "SCCACHE_DIR=${DEV_DRIVE}\\.sccache" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
|
||||
fi
|
||||
echo "Using sccache local disk + actions/cache fallback"
|
||||
fi
|
||||
|
||||
- name: Enable sccache wrapper
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
wrapper="$(command -v sccache)"
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]] && command -v cygpath >/dev/null 2>&1; then
|
||||
wrapper="$(cygpath -w "${wrapper}")"
|
||||
fi
|
||||
echo "RUSTC_WRAPPER=${wrapper}" >> "$GITHUB_ENV"
|
||||
echo "CARGO_BUILD_RUSTC_WRAPPER=${wrapper}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Restore sccache cache (fallback)
|
||||
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
||||
id: cache_sccache_restore
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ env.SCCACHE_DIR }}
|
||||
key: sccache-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
sccache-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-${{ steps.lockhash.outputs.hash }}-
|
||||
sccache-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-
|
||||
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: nextest
|
||||
version: 0.9.103
|
||||
|
||||
- name: Enable unprivileged user namespaces (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo sysctl -w kernel.unprivileged_userns_clone=1
|
||||
if sudo sysctl -a 2>/dev/null | grep -q '^kernel.apparmor_restrict_unprivileged_userns'; then
|
||||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
fi
|
||||
|
||||
- name: Build nextest archive
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
archive_dir="${RUNNER_TEMP}/nextest-archive"
|
||||
mkdir -p "${archive_dir}"
|
||||
cargo nextest archive \
|
||||
--target ${{ inputs.target }} \
|
||||
--cargo-profile ${{ inputs.profile }} \
|
||||
--timings \
|
||||
--archive-file "${archive_dir}/${NEXTEST_ARCHIVE_FILE}"
|
||||
|
||||
- name: Build runtime test helpers
|
||||
if: ${{ runner.os == 'Linux' || runner.os == 'Windows' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
helper_dir="${RUNNER_TEMP}/${TEST_HELPERS_ARTIFACT}"
|
||||
mkdir -p "${helper_dir}"
|
||||
|
||||
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||
cargo build \
|
||||
--target ${{ inputs.target }} \
|
||||
--profile ${{ inputs.profile }} \
|
||||
-p codex-linux-sandbox \
|
||||
--bin codex-linux-sandbox
|
||||
cp "target/${{ inputs.target }}/${{ inputs.profile }}/codex-linux-sandbox" "${helper_dir}/"
|
||||
else
|
||||
cargo build \
|
||||
--target ${{ inputs.target }} \
|
||||
--profile ${{ inputs.profile }} \
|
||||
-p codex-windows-sandbox \
|
||||
--bin codex-windows-sandbox-setup \
|
||||
--bin codex-command-runner
|
||||
cp "target/${{ inputs.target }}/${{ inputs.profile }}/codex-windows-sandbox-setup.exe" "${helper_dir}/"
|
||||
cp "target/${{ inputs.target }}/${{ inputs.profile }}/codex-command-runner.exe" "${helper_dir}/"
|
||||
fi
|
||||
|
||||
- name: Upload Cargo timings (nextest)
|
||||
if: always()
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: cargo-timings-rust-ci-nextest-${{ inputs.target }}-${{ inputs.profile }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload nextest archive
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: nextest-archive-${{ inputs.artifact_id }}
|
||||
path: ${{ runner.temp }}/nextest-archive/${{ env.NEXTEST_ARCHIVE_FILE }}
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload runtime test helpers
|
||||
if: ${{ runner.os == 'Linux' || runner.os == 'Windows' }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: ${{ env.TEST_HELPERS_ARTIFACT }}
|
||||
path: ${{ runner.temp }}/${{ env.TEST_HELPERS_ARTIFACT }}/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Save cargo home cache
|
||||
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
key: cargo-home-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
||||
|
||||
- name: Save sccache cache (fallback)
|
||||
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ env.SCCACHE_DIR }}
|
||||
key: sccache-${{ env.ARCHIVE_CACHE_RUNNER }}-${{ inputs.target }}-${{ inputs.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
|
||||
- name: sccache stats
|
||||
if: always() && env.USE_SCCACHE == 'true'
|
||||
continue-on-error: true
|
||||
run: sccache --show-stats || true
|
||||
|
||||
- name: sccache summary
|
||||
if: always() && env.USE_SCCACHE == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
{
|
||||
echo "### sccache stats — ${{ inputs.target }} (tests)";
|
||||
echo;
|
||||
echo '```';
|
||||
sccache --show-stats || true;
|
||||
echo '```';
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
shard:
|
||||
name: Tests shard ${{ matrix.shard }}/4
|
||||
needs: archive
|
||||
runs-on: ${{ inputs.runner_group != '' && fromJSON(format('{{"group":"{0}","labels":"{1}"}}', inputs.runner_group, inputs.runner_labels)) || inputs.runner }}
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
NEXTEST_ARCHIVE_FILE: nextest-${{ inputs.artifact_id }}.tar.zst
|
||||
TEST_HELPERS_ARTIFACT: nextest-test-helpers-${{ inputs.artifact_id }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Linux build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
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 --no-install-recommends pkg-config libcap-dev bubblewrap
|
||||
fi
|
||||
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ inputs.target }}
|
||||
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: nextest
|
||||
version: 0.9.103
|
||||
|
||||
- name: Enable unprivileged user namespaces (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo sysctl -w kernel.unprivileged_userns_clone=1
|
||||
if sudo sysctl -a 2>/dev/null | grep -q '^kernel.apparmor_restrict_unprivileged_userns'; then
|
||||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
fi
|
||||
|
||||
- name: Set up remote test env (Docker)
|
||||
if: ${{ runner.os == 'Linux' && inputs.remote_env }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export CODEX_TEST_REMOTE_ENV_CONTAINER_NAME="codex-remote-test-env-${{ github.run_id }}-${{ matrix.shard }}"
|
||||
source "${GITHUB_WORKSPACE}/scripts/test-remote-env.sh"
|
||||
echo "CODEX_TEST_REMOTE_ENV=${CODEX_TEST_REMOTE_ENV}" >> "$GITHUB_ENV"
|
||||
echo "CODEX_TEST_REMOTE_EXEC_SERVER_URL=${CODEX_TEST_REMOTE_EXEC_SERVER_URL}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Download nextest archive
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: nextest-archive-${{ inputs.artifact_id }}
|
||||
path: ${{ runner.temp }}/nextest-archive
|
||||
|
||||
- name: Download runtime test helpers
|
||||
if: ${{ runner.os == 'Linux' || runner.os == 'Windows' }}
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: ${{ env.TEST_HELPERS_ARTIFACT }}
|
||||
path: ${{ runner.temp }}/${{ env.TEST_HELPERS_ARTIFACT }}
|
||||
|
||||
- name: tests
|
||||
id: test
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
archive_file="${RUNNER_TEMP}/nextest-archive/${NEXTEST_ARCHIVE_FILE}"
|
||||
workspace_root="$(pwd)"
|
||||
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
archive_file="$(cygpath -w "${archive_file}")"
|
||||
workspace_root="$(cygpath -w "${workspace_root}")"
|
||||
fi
|
||||
|
||||
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||
helper_dir="${RUNNER_TEMP}/${TEST_HELPERS_ARTIFACT}"
|
||||
helper_target_dir="$(pwd)/target/${{ inputs.target }}/${{ inputs.profile }}"
|
||||
mkdir -p "${helper_target_dir}"
|
||||
cp "${helper_dir}/codex-linux-sandbox" "${helper_target_dir}/"
|
||||
chmod +x "${helper_target_dir}/codex-linux-sandbox"
|
||||
elif [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
helper_dir="${RUNNER_TEMP}/${TEST_HELPERS_ARTIFACT}"
|
||||
helper_target_dir="$(pwd)/target/${{ inputs.target }}/${{ inputs.profile }}"
|
||||
mkdir -p "${helper_target_dir}"
|
||||
cp "${helper_dir}/codex-windows-sandbox-setup.exe" "${helper_target_dir}/"
|
||||
cp "${helper_dir}/codex-command-runner.exe" "${helper_target_dir}/"
|
||||
fi
|
||||
|
||||
nextest_args=(
|
||||
run
|
||||
--no-fail-fast
|
||||
--archive-file "${archive_file}"
|
||||
--workspace-remap "${workspace_root}"
|
||||
--partition "hash:${{ matrix.shard }}/4"
|
||||
)
|
||||
if [[ "${{ inputs.test_threads }}" != "0" ]]; then
|
||||
nextest_args+=(--test-threads "${{ inputs.test_threads }}")
|
||||
fi
|
||||
|
||||
test_command=(cargo nextest "${nextest_args[@]}")
|
||||
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||
sandbox_helper="${helper_target_dir}/codex-linux-sandbox"
|
||||
test_command=(
|
||||
env
|
||||
"CARGO_BIN_EXE_codex-linux-sandbox=${sandbox_helper}"
|
||||
"CARGO_BIN_EXE_codex_linux_sandbox=${sandbox_helper}"
|
||||
cargo nextest "${nextest_args[@]}"
|
||||
)
|
||||
elif [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
setup_helper="$(cygpath -w "${helper_target_dir}/codex-windows-sandbox-setup.exe")"
|
||||
command_runner="$(cygpath -w "${helper_target_dir}/codex-command-runner.exe")"
|
||||
test_command=(
|
||||
env
|
||||
"CARGO_BIN_EXE_codex_windows_sandbox_setup=${setup_helper}"
|
||||
"CARGO_BIN_EXE_codex_command_runner=${command_runner}"
|
||||
cargo nextest "${nextest_args[@]}"
|
||||
)
|
||||
fi
|
||||
|
||||
"${test_command[@]}"
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
RUST_MIN_STACK: "8388608" # 8 MiB
|
||||
NEXTEST_STATUS_LEVEL: leak
|
||||
|
||||
- name: Upload nextest JUnit report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: nextest-junit-rust-ci-${{ inputs.artifact_id }}-shard-${{ matrix.shard }}
|
||||
path: codex-rs/target/nextest/default/junit.xml
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Tear down remote test env
|
||||
if: ${{ always() && runner.os == 'Linux' && inputs.remote_env }}
|
||||
shell: bash
|
||||
run: |
|
||||
set +e
|
||||
if [[ "${STEPS_TEST_OUTCOME}" != "success" ]]; then
|
||||
docker logs "${CODEX_TEST_REMOTE_ENV}" || true
|
||||
fi
|
||||
docker rm -f "${CODEX_TEST_REMOTE_ENV}" >/dev/null 2>&1 || true
|
||||
env:
|
||||
STEPS_TEST_OUTCOME: ${{ steps.test.outcome }}
|
||||
|
||||
- name: verify tests passed
|
||||
if: steps.test.outcome == 'failure'
|
||||
run: |
|
||||
echo "Tests failed. See logs for details."
|
||||
exit 1
|
||||
|
||||
result:
|
||||
name: Platform result
|
||||
needs: shard
|
||||
if: always()
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Confirm test shards passed
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ needs.shard.result }}" != "success" ]]; then
|
||||
echo "Nextest shards finished with result: ${{ needs.shard.result }}" >&2
|
||||
exit 1
|
||||
fi
|
||||
643
reference/openai-codex/.github/workflows/rust-ci-full.yml
vendored
Normal file
643
reference/openai-codex/.github/workflows/rust-ci-full.yml
vendored
Normal file
@@ -0,0 +1,643 @@
|
||||
name: rust-ci-full
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "**full-ci**"
|
||||
workflow_dispatch:
|
||||
|
||||
# CI builds in debug (dev) for faster signal.
|
||||
env:
|
||||
# Cargo's libgit2 transport has been flaky on macOS when fetching git
|
||||
# dependencies with nested submodules. Use the system git CLI, which has
|
||||
# better network/proxy behavior and matches Cargo's own suggested fallback.
|
||||
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
|
||||
|
||||
jobs:
|
||||
# --- CI that doesn't need specific targets ---------------------------------
|
||||
general:
|
||||
name: Format / etc
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
components: rustfmt
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: just
|
||||
- name: cargo fmt
|
||||
run: cargo fmt -- --config imports_granularity=Item --check
|
||||
- name: Rust benchmark smoke test
|
||||
run: just bench-smoke
|
||||
|
||||
cargo_shear:
|
||||
name: cargo shear
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: cargo-shear@1.11.2
|
||||
- name: cargo shear
|
||||
run: cargo shear --deny-warnings
|
||||
|
||||
argument_comment_lint_package:
|
||||
name: Argument comment lint package
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: nightly-2025-09-18
|
||||
components: llvm-tools-preview, rustc-dev, rust-src
|
||||
- name: Cache cargo-dylint tooling
|
||||
id: cargo_dylint_cache
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/cargo-dylint
|
||||
~/.cargo/bin/dylint-link
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ env.CARGO_DYLINT_VERSION }}-${{ env.DYLINT_LINK_VERSION }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
- name: Install cargo-dylint tooling
|
||||
if: ${{ steps.cargo_dylint_cache.outputs.cache-hit != 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
- name: Check Python wrapper syntax
|
||||
run: python3 -m py_compile tools/argument-comment-lint/wrapper_common.py tools/argument-comment-lint/run.py tools/argument-comment-lint/run-prebuilt-linter.py tools/argument-comment-lint/test_wrapper_common.py
|
||||
- name: Test Python wrapper helpers
|
||||
run: python3 -m unittest discover -s tools/argument-comment-lint -p 'test_*.py'
|
||||
- name: Test argument comment lint package
|
||||
working-directory: tools/argument-comment-lint
|
||||
run: cargo test
|
||||
env:
|
||||
RUST_MIN_STACK: "8388608" # 8 MiB
|
||||
|
||||
argument_comment_lint_prebuilt:
|
||||
name: Argument comment lint - ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Linux
|
||||
runner: ubuntu-24.04
|
||||
- name: macOS
|
||||
runner: macos-15-xlarge
|
||||
- name: Windows
|
||||
runner: windows-x64
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ runner.os }}
|
||||
install-test-prereqs: true
|
||||
- name: Install Linux sandbox build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
||||
- name: Run argument comment lint on codex-rs via Bazel
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
bazel_targets="$(./tools/argument-comment-lint/list-bazel-targets.sh)"
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
-- \
|
||||
build \
|
||||
--config=argument-comment-lint \
|
||||
--keep_going \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \
|
||||
-- \
|
||||
${bazel_targets}
|
||||
- name: Run argument comment lint on codex-rs via Bazel
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/run-argument-comment-lint-bazel.sh \
|
||||
--config=argument-comment-lint \
|
||||
--platforms=//:local_windows \
|
||||
--keep_going \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
|
||||
# --- CI to validate on different os/targets --------------------------------
|
||||
lint_build:
|
||||
name: Lint/Build — ${{ matrix.runner }} - ${{ matrix.target }}${{ matrix.profile == 'release' && ' (release)' || '' }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: 30
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
# Speed up repeated builds across CI runs by caching compiled objects, except on
|
||||
# arm64 macOS runners cross-targeting x86_64 where ring/cc-rs can produce
|
||||
# mixed-architecture archives under sccache.
|
||||
USE_SCCACHE: ${{ (startsWith(matrix.runner, 'windows') || (matrix.runner == 'macos-15-xlarge' && matrix.target == 'x86_64-apple-darwin')) && 'false' || 'true' }}
|
||||
CARGO_INCREMENTAL: "0"
|
||||
SCCACHE_CACHE_SIZE: 10G
|
||||
# In rust-ci, representative release-profile checks use thin LTO for faster feedback.
|
||||
CARGO_PROFILE_RELEASE_LTO: ${{ matrix.profile == 'release' && 'thin' || 'fat' }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
profile: dev
|
||||
- runner: macos-15-xlarge
|
||||
target: x86_64-apple-darwin
|
||||
profile: dev
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-musl
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-musl
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-arm64
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-gnu
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
profile: dev
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
|
||||
# Also run representative release builds on Mac and Linux because
|
||||
# there could be release-only build errors we want to catch.
|
||||
# Hopefully this also pre-populates the build cache to speed up
|
||||
# releases.
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
profile: release
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-musl
|
||||
profile: release
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-musl
|
||||
profile: release
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
profile: release
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
profile: release
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Linux build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
sudo apt-get update -y
|
||||
packages=(pkg-config libcap-dev)
|
||||
if [[ "${{ matrix.target }}" == 'x86_64-unknown-linux-musl' || "${{ matrix.target }}" == 'aarch64-unknown-linux-musl' ]]; then
|
||||
packages+=(libubsan1)
|
||||
fi
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${packages[@]}"
|
||||
fi
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
components: clippy
|
||||
|
||||
- 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"
|
||||
|
||||
- name: Compute lockfile hash
|
||||
id: lockhash
|
||||
working-directory: codex-rs
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "hash=$(sha256sum Cargo.lock | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
echo "toolchain_hash=$(sha256sum rust-toolchain.toml | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Explicit cache restore: split cargo home vs target, so we can
|
||||
# avoid caching the large target dir on the gnu-dev job.
|
||||
- name: Restore cargo home cache
|
||||
id: cache_cargo_home_restore
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
${{ github.workspace }}/.cargo-home/bin/
|
||||
${{ github.workspace }}/.cargo-home/registry/index/
|
||||
${{ github.workspace }}/.cargo-home/registry/cache/
|
||||
${{ github.workspace }}/.cargo-home/git/db/
|
||||
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
||||
restore-keys: |
|
||||
cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
||||
|
||||
# Install and restore sccache cache
|
||||
- name: Install sccache
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: sccache
|
||||
version: 0.7.5
|
||||
|
||||
- name: Configure sccache backend
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
|
||||
echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
|
||||
echo "Using sccache GitHub backend"
|
||||
else
|
||||
echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
|
||||
echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
|
||||
echo "Using sccache local disk + actions/cache fallback"
|
||||
fi
|
||||
|
||||
- name: Enable sccache wrapper
|
||||
if: ${{ env.USE_SCCACHE == 'true' }}
|
||||
shell: bash
|
||||
run: echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Restore sccache cache (fallback)
|
||||
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
||||
id: cache_sccache_restore
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-
|
||||
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
||||
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
||||
name: Disable sccache wrapper (musl)
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "RUSTC_WRAPPER=" >> "$GITHUB_ENV"
|
||||
echo "RUSTC_WORKSPACE_WRAPPER=" >> "$GITHUB_ENV"
|
||||
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
||||
name: Prepare APT cache directories (musl)
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo mkdir -p /var/cache/apt/archives /var/lib/apt/lists
|
||||
sudo chown -R "$USER:$USER" /var/cache/apt /var/lib/apt/lists
|
||||
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
||||
name: Restore APT cache (musl)
|
||||
id: cache_apt_restore
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
/var/cache/apt
|
||||
key: apt-${{ matrix.runner }}-${{ matrix.target }}-v1
|
||||
|
||||
- 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:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
TARGET: ${{ matrix.target }}
|
||||
APT_UPDATE_ARGS: -o Acquire::Retries=3
|
||||
APT_INSTALL_ARGS: --no-install-recommends
|
||||
shell: bash
|
||||
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
|
||||
# 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"
|
||||
|
||||
- if: ${{ !contains(matrix.target, 'windows') }}
|
||||
name: Configure rusty_v8 artifact overrides and verify checksums
|
||||
uses: ./.github/actions/setup-rusty-v8
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Install cargo-chef
|
||||
if: ${{ matrix.profile == 'release' }}
|
||||
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: cargo-chef
|
||||
version: 0.1.71
|
||||
|
||||
- name: Pre-warm dependency cache (cargo-chef)
|
||||
if: ${{ matrix.profile == 'release' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RECIPE="${RUNNER_TEMP}/chef-recipe.json"
|
||||
cargo chef prepare --recipe-path "$RECIPE"
|
||||
cargo chef cook --recipe-path "$RECIPE" --target ${{ matrix.target }} --release
|
||||
|
||||
- name: cargo clippy
|
||||
run: cargo clippy --target ${{ matrix.target }} --tests --profile ${{ matrix.profile }} --timings -- -D warnings
|
||||
|
||||
- name: Upload Cargo timings (clippy)
|
||||
if: always()
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: cargo-timings-rust-ci-clippy-${{ matrix.target }}-${{ matrix.profile }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
if-no-files-found: warn
|
||||
|
||||
# Save caches explicitly; make non-fatal so cache packaging
|
||||
# never fails the overall job. Only save when key wasn't hit.
|
||||
- name: Save cargo home cache
|
||||
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
${{ github.workspace }}/.cargo-home/bin/
|
||||
${{ github.workspace }}/.cargo-home/registry/index/
|
||||
${{ github.workspace }}/.cargo-home/registry/cache/
|
||||
${{ github.workspace }}/.cargo-home/git/db/
|
||||
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
||||
|
||||
- name: Save sccache cache (fallback)
|
||||
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
|
||||
- name: sccache stats
|
||||
if: always() && env.USE_SCCACHE == 'true'
|
||||
continue-on-error: true
|
||||
run: sccache --show-stats || true
|
||||
|
||||
- name: sccache summary
|
||||
if: always() && env.USE_SCCACHE == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
{
|
||||
echo "### sccache stats — ${{ matrix.target }} (${{ matrix.profile }})";
|
||||
echo;
|
||||
echo '```';
|
||||
sccache --show-stats || true;
|
||||
echo '```';
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Save APT cache (musl)
|
||||
if: always() && !cancelled() && (matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl') && steps.cache_apt_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
/var/cache/apt
|
||||
key: apt-${{ matrix.runner }}-${{ matrix.target }}-v1
|
||||
|
||||
tests_macos_aarch64:
|
||||
name: Tests — macos-15-xlarge - aarch64-apple-darwin
|
||||
uses: ./.github/workflows/rust-ci-full-nextest-platform.yml
|
||||
with:
|
||||
runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
profile: ci-test
|
||||
artifact_id: macos-aarch64
|
||||
use_sccache: true
|
||||
secrets: inherit
|
||||
|
||||
tests_linux_x64_remote:
|
||||
name: Tests — ubuntu-24.04 - x86_64-unknown-linux-gnu (remote)
|
||||
uses: ./.github/workflows/rust-ci-full-nextest-platform.yml
|
||||
with:
|
||||
runner: ubuntu-24.04
|
||||
runner_group: codex-runners
|
||||
runner_labels: codex-linux-x64
|
||||
target: x86_64-unknown-linux-gnu
|
||||
profile: ci-test
|
||||
artifact_id: linux-x64-remote
|
||||
remote_env: true
|
||||
use_sccache: true
|
||||
secrets: inherit
|
||||
|
||||
tests_linux_arm64:
|
||||
name: Tests — ubuntu-24.04-arm - aarch64-unknown-linux-gnu
|
||||
uses: ./.github/workflows/rust-ci-full-nextest-platform.yml
|
||||
with:
|
||||
runner: ubuntu-24.04-arm
|
||||
runner_group: codex-runners
|
||||
runner_labels: codex-linux-arm64
|
||||
target: aarch64-unknown-linux-gnu
|
||||
profile: ci-test
|
||||
artifact_id: linux-arm64
|
||||
use_sccache: true
|
||||
secrets: inherit
|
||||
|
||||
tests_windows_x64:
|
||||
name: Tests — windows-x64 - x86_64-pc-windows-msvc
|
||||
uses: ./.github/workflows/rust-ci-full-nextest-platform.yml
|
||||
with:
|
||||
runner: windows-x64
|
||||
runner_group: codex-runners
|
||||
runner_labels: codex-windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
profile: ci-test
|
||||
artifact_id: windows-x64
|
||||
test_threads: 8
|
||||
secrets: inherit
|
||||
|
||||
tests_windows_arm64:
|
||||
name: Tests — windows-arm64 - aarch64-pc-windows-msvc
|
||||
uses: ./.github/workflows/rust-ci-full-nextest-platform.yml
|
||||
with:
|
||||
runner: windows-arm64
|
||||
runner_group: codex-runners
|
||||
runner_labels: codex-windows-arm64
|
||||
archive_runner: windows-x64
|
||||
archive_runner_group: codex-runners
|
||||
archive_runner_labels: codex-windows-x64
|
||||
target: aarch64-pc-windows-msvc
|
||||
profile: ci-test
|
||||
artifact_id: windows-arm64
|
||||
test_threads: 8
|
||||
use_sccache: true
|
||||
secrets: inherit
|
||||
|
||||
# --- Gatherer job for the full post-merge workflow --------------------------
|
||||
results:
|
||||
name: Full CI results
|
||||
needs:
|
||||
[
|
||||
general,
|
||||
cargo_shear,
|
||||
argument_comment_lint_package,
|
||||
argument_comment_lint_prebuilt,
|
||||
lint_build,
|
||||
tests_macos_aarch64,
|
||||
tests_linux_x64_remote,
|
||||
tests_linux_arm64,
|
||||
tests_windows_x64,
|
||||
tests_windows_arm64,
|
||||
]
|
||||
if: always()
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Summarize
|
||||
shell: bash
|
||||
run: |
|
||||
echo "argpkg : ${{ needs.argument_comment_lint_package.result }}"
|
||||
echo "arglint: ${{ needs.argument_comment_lint_prebuilt.result }}"
|
||||
echo "general: ${{ needs.general.result }}"
|
||||
echo "shear : ${{ needs.cargo_shear.result }}"
|
||||
echo "lint : ${{ needs.lint_build.result }}"
|
||||
echo "test macos : ${{ needs.tests_macos_aarch64.result }}"
|
||||
echo "test linux : ${{ needs.tests_linux_x64_remote.result }}"
|
||||
echo "test arm64 : ${{ needs.tests_linux_arm64.result }}"
|
||||
echo "test winx64: ${{ needs.tests_windows_x64.result }}"
|
||||
echo "test winarm: ${{ needs.tests_windows_arm64.result }}"
|
||||
[[ '${{ needs.argument_comment_lint_package.result }}' == 'success' ]] || { echo 'argument_comment_lint_package failed'; exit 1; }
|
||||
[[ '${{ needs.argument_comment_lint_prebuilt.result }}' == 'success' ]] || { echo 'argument_comment_lint_prebuilt failed'; exit 1; }
|
||||
[[ '${{ needs.general.result }}' == 'success' ]] || { echo 'general failed'; exit 1; }
|
||||
[[ '${{ needs.cargo_shear.result }}' == 'success' ]] || { echo 'cargo_shear failed'; exit 1; }
|
||||
[[ '${{ needs.lint_build.result }}' == 'success' ]] || { echo 'lint_build failed'; exit 1; }
|
||||
[[ '${{ needs.tests_macos_aarch64.result }}' == 'success' ]] || { echo 'tests_macos_aarch64 failed'; exit 1; }
|
||||
[[ '${{ needs.tests_linux_x64_remote.result }}' == 'success' ]] || { echo 'tests_linux_x64_remote failed'; exit 1; }
|
||||
[[ '${{ needs.tests_linux_arm64.result }}' == 'success' ]] || { echo 'tests_linux_arm64 failed'; exit 1; }
|
||||
[[ '${{ needs.tests_windows_x64.result }}' == 'success' ]] || { echo 'tests_windows_x64 failed'; exit 1; }
|
||||
[[ '${{ needs.tests_windows_arm64.result }}' == 'success' ]] || { echo 'tests_windows_arm64 failed'; exit 1; }
|
||||
|
||||
- name: sccache summary note
|
||||
if: always()
|
||||
run: |
|
||||
echo "Per-job sccache stats are attached to each matrix job's Step Summary."
|
||||
245
reference/openai-codex/.github/workflows/rust-ci.yml
vendored
Normal file
245
reference/openai-codex/.github/workflows/rust-ci.yml
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
name: rust-ci
|
||||
on:
|
||||
pull_request: {}
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# --- Detect what changed so the fast PR workflow only runs relevant jobs ----
|
||||
changed:
|
||||
name: Detect changed areas
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
argument_comment_lint: ${{ steps.detect.outputs.argument_comment_lint }}
|
||||
argument_comment_lint_package: ${{ steps.detect.outputs.argument_comment_lint_package }}
|
||||
codex: ${{ steps.detect.outputs.codex }}
|
||||
workflows: ${{ steps.detect.outputs.workflows }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Detect changed paths (no external action)
|
||||
id: detect
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
BASE_SHA='${{ github.event.pull_request.base.sha }}'
|
||||
HEAD_SHA='${{ github.event.pull_request.head.sha }}'
|
||||
echo "Base SHA: $BASE_SHA"
|
||||
echo "Head SHA: $HEAD_SHA"
|
||||
mapfile -t files < <(git diff --name-only --no-renames "$BASE_SHA" "$HEAD_SHA")
|
||||
else
|
||||
# On manual runs, default to the full fast-PR bundle.
|
||||
files=("codex-rs/force" "tools/argument-comment-lint/force" ".github/force")
|
||||
fi
|
||||
|
||||
codex=false
|
||||
argument_comment_lint=false
|
||||
argument_comment_lint_package=false
|
||||
workflows=false
|
||||
for f in "${files[@]}"; do
|
||||
[[ $f == codex-rs/* ]] && codex=true
|
||||
[[ $f == codex-rs/* || $f == tools/argument-comment-lint/* || $f == justfile ]] && argument_comment_lint=true
|
||||
[[ $f == defs.bzl || $f == workspace_root_test_launcher.sh.tpl || $f == workspace_root_test_launcher.bat.tpl ]] && argument_comment_lint=true
|
||||
[[ $f == tools/argument-comment-lint/* || $f == .github/workflows/rust-ci.yml || $f == .github/workflows/rust-ci-full.yml ]] && argument_comment_lint_package=true
|
||||
[[ $f == .github/* ]] && workflows=true
|
||||
done
|
||||
|
||||
echo "argument_comment_lint=$argument_comment_lint" >> "$GITHUB_OUTPUT"
|
||||
echo "argument_comment_lint_package=$argument_comment_lint_package" >> "$GITHUB_OUTPUT"
|
||||
echo "codex=$codex" >> "$GITHUB_OUTPUT"
|
||||
echo "workflows=$workflows" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# --- Fast Cargo-native PR checks -------------------------------------------
|
||||
general:
|
||||
name: Format / etc
|
||||
runs-on: ubuntu-24.04
|
||||
needs: changed
|
||||
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
components: rustfmt
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: just
|
||||
- name: cargo fmt
|
||||
run: cargo fmt -- --config imports_granularity=Item --check
|
||||
- name: Rust benchmark smoke test
|
||||
run: just bench-smoke
|
||||
|
||||
cargo_shear:
|
||||
name: cargo shear
|
||||
runs-on: ubuntu-24.04
|
||||
needs: changed
|
||||
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49
|
||||
with:
|
||||
tool: cargo-shear@1.11.2
|
||||
- name: cargo shear
|
||||
run: cargo shear --deny-warnings
|
||||
|
||||
argument_comment_lint_package:
|
||||
name: Argument comment lint package
|
||||
runs-on: ubuntu-24.04
|
||||
needs: changed
|
||||
if: ${{ needs.changed.outputs.argument_comment_lint_package == 'true' }}
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
- name: Install nightly argument-comment-lint toolchain
|
||||
shell: bash
|
||||
run: |
|
||||
rustup toolchain install nightly-2025-09-18 \
|
||||
--profile minimal \
|
||||
--component llvm-tools-preview \
|
||||
--component rustc-dev \
|
||||
--component rust-src \
|
||||
--no-self-update
|
||||
rustup default nightly-2025-09-18
|
||||
- name: Cache cargo-dylint tooling
|
||||
id: cargo_dylint_cache
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/cargo-dylint
|
||||
~/.cargo/bin/dylint-link
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ env.CARGO_DYLINT_VERSION }}-${{ env.DYLINT_LINK_VERSION }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
- name: Install cargo-dylint tooling
|
||||
if: ${{ steps.cargo_dylint_cache.outputs.cache-hit != 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
- name: Check Python wrapper syntax
|
||||
run: python3 -m py_compile tools/argument-comment-lint/wrapper_common.py tools/argument-comment-lint/run.py tools/argument-comment-lint/run-prebuilt-linter.py tools/argument-comment-lint/test_wrapper_common.py
|
||||
- name: Test Python wrapper helpers
|
||||
run: python3 -m unittest discover -s tools/argument-comment-lint -p 'test_*.py'
|
||||
- name: Test argument comment lint package
|
||||
working-directory: tools/argument-comment-lint
|
||||
run: cargo test
|
||||
env:
|
||||
RUST_MIN_STACK: "8388608" # 8 MiB
|
||||
|
||||
argument_comment_lint_prebuilt:
|
||||
name: Argument comment lint - ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: ${{ matrix.timeout_minutes }}
|
||||
needs: changed
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Linux
|
||||
runner: ubuntu-24.04
|
||||
timeout_minutes: 30
|
||||
- name: macOS
|
||||
runner: macos-15-xlarge
|
||||
timeout_minutes: 30
|
||||
- name: Windows
|
||||
runner: windows-x64
|
||||
timeout_minutes: 30
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
steps:
|
||||
- name: Check whether argument comment lint should run
|
||||
id: argument_comment_lint_gate
|
||||
shell: bash
|
||||
env:
|
||||
ARGUMENT_COMMENT_LINT: ${{ needs.changed.outputs.argument_comment_lint }}
|
||||
WORKFLOWS: ${{ needs.changed.outputs.workflows }}
|
||||
run: |
|
||||
if [[ "$ARGUMENT_COMMENT_LINT" == "true" || "$WORKFLOWS" == "true" ]]; then
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "No argument-comment-lint relevant changes."
|
||||
echo "run=false" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
if: ${{ steps.argument_comment_lint_gate.outputs.run == 'true' }}
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
- name: Run argument comment lint on codex-rs via Bazel
|
||||
if: ${{ steps.argument_comment_lint_gate.outputs.run == 'true' }}
|
||||
uses: ./.github/actions/run-argument-comment-lint
|
||||
with:
|
||||
target: ${{ runner.os }}
|
||||
buildbuddy-api-key: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
|
||||
# --- Gatherer job that you mark as the ONLY required status -----------------
|
||||
results:
|
||||
name: CI results (required)
|
||||
needs:
|
||||
[
|
||||
changed,
|
||||
general,
|
||||
cargo_shear,
|
||||
argument_comment_lint_package,
|
||||
argument_comment_lint_prebuilt,
|
||||
]
|
||||
if: always()
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Summarize
|
||||
shell: bash
|
||||
run: |
|
||||
echo "argpkg : ${{ needs.argument_comment_lint_package.result }}"
|
||||
echo "arglint: ${{ needs.argument_comment_lint_prebuilt.result }}"
|
||||
echo "general: ${{ needs.general.result }}"
|
||||
echo "shear : ${{ needs.cargo_shear.result }}"
|
||||
|
||||
# If nothing relevant changed (PR touching only root README, etc.),
|
||||
# declare success regardless of other jobs.
|
||||
if [[ "${NEEDS_CHANGED_OUTPUTS_ARGUMENT_COMMENT_LINT}" != 'true' && "${NEEDS_CHANGED_OUTPUTS_CODEX}" != 'true' && "${NEEDS_CHANGED_OUTPUTS_WORKFLOWS}" != 'true' ]]; then
|
||||
echo 'No relevant changes -> CI not required.'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${NEEDS_CHANGED_OUTPUTS_ARGUMENT_COMMENT_LINT_PACKAGE}" == 'true' ]]; then
|
||||
[[ '${{ needs.argument_comment_lint_package.result }}' == 'success' ]] || { echo 'argument_comment_lint_package failed'; exit 1; }
|
||||
fi
|
||||
|
||||
if [[ "${NEEDS_CHANGED_OUTPUTS_ARGUMENT_COMMENT_LINT}" == 'true' || "${NEEDS_CHANGED_OUTPUTS_WORKFLOWS}" == 'true' ]]; then
|
||||
[[ '${{ needs.argument_comment_lint_prebuilt.result }}' == 'success' ]] || { echo 'argument_comment_lint_prebuilt failed'; exit 1; }
|
||||
fi
|
||||
|
||||
if [[ "${NEEDS_CHANGED_OUTPUTS_CODEX}" == 'true' || "${NEEDS_CHANGED_OUTPUTS_WORKFLOWS}" == 'true' ]]; then
|
||||
[[ '${{ needs.general.result }}' == 'success' ]] || { echo 'general failed'; exit 1; }
|
||||
[[ '${{ needs.cargo_shear.result }}' == 'success' ]] || { echo 'cargo_shear failed'; exit 1; }
|
||||
fi
|
||||
env:
|
||||
NEEDS_CHANGED_OUTPUTS_ARGUMENT_COMMENT_LINT: ${{ needs.changed.outputs.argument_comment_lint }}
|
||||
NEEDS_CHANGED_OUTPUTS_CODEX: ${{ needs.changed.outputs.codex }}
|
||||
NEEDS_CHANGED_OUTPUTS_WORKFLOWS: ${{ needs.changed.outputs.workflows }}
|
||||
NEEDS_CHANGED_OUTPUTS_ARGUMENT_COMMENT_LINT_PACKAGE: ${{ needs.changed.outputs.argument_comment_lint_package }}
|
||||
108
reference/openai-codex/.github/workflows/rust-release-argument-comment-lint.yml
vendored
Normal file
108
reference/openai-codex/.github/workflows/rust-release-argument-comment-lint.yml
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
name: rust-release-argument-comment-lint
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
publish:
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
skip:
|
||||
if: ${{ !inputs.publish }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "Skipping argument-comment-lint release assets for prerelease tag"
|
||||
|
||||
build:
|
||||
if: ${{ inputs.publish }}
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
archive_name: argument-comment-lint-aarch64-apple-darwin.tar.gz
|
||||
lib_name: libargument_comment_lint@nightly-2025-09-18-aarch64-apple-darwin.dylib
|
||||
runner_binary: argument-comment-lint
|
||||
cargo_dylint_binary: cargo-dylint
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
archive_name: argument-comment-lint-x86_64-unknown-linux-gnu.tar.gz
|
||||
lib_name: libargument_comment_lint@nightly-2025-09-18-x86_64-unknown-linux-gnu.so
|
||||
runner_binary: argument-comment-lint
|
||||
cargo_dylint_binary: cargo-dylint
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-gnu
|
||||
archive_name: argument-comment-lint-aarch64-unknown-linux-gnu.tar.gz
|
||||
lib_name: libargument_comment_lint@nightly-2025-09-18-aarch64-unknown-linux-gnu.so
|
||||
runner_binary: argument-comment-lint
|
||||
cargo_dylint_binary: cargo-dylint
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
archive_name: argument-comment-lint-x86_64-pc-windows-msvc.zip
|
||||
lib_name: argument_comment_lint@nightly-2025-09-18-x86_64-pc-windows-msvc.dll
|
||||
runner_binary: argument-comment-lint.exe
|
||||
cargo_dylint_binary: cargo-dylint.exe
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: nightly-2025-09-18
|
||||
targets: ${{ matrix.target }}
|
||||
components: llvm-tools-preview, rustc-dev, rust-src
|
||||
|
||||
- name: Install tooling
|
||||
shell: bash
|
||||
run: |
|
||||
install_root="${RUNNER_TEMP}/argument-comment-lint-tools"
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION" --root "$install_root"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
echo "INSTALL_ROOT=$install_root" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Cargo build
|
||||
working-directory: tools/argument-comment-lint
|
||||
shell: bash
|
||||
run: cargo build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Stage artifact
|
||||
shell: bash
|
||||
run: |
|
||||
dest="dist/argument-comment-lint/${{ matrix.target }}"
|
||||
mkdir -p "$dest"
|
||||
package_root="${RUNNER_TEMP}/argument-comment-lint"
|
||||
rm -rf "$package_root"
|
||||
mkdir -p "$package_root/bin" "$package_root/lib"
|
||||
|
||||
cp "tools/argument-comment-lint/target/${{ matrix.target }}/release/${{ matrix.runner_binary }}" \
|
||||
"$package_root/bin/${{ matrix.runner_binary }}"
|
||||
cp "${INSTALL_ROOT}/bin/${{ matrix.cargo_dylint_binary }}" \
|
||||
"$package_root/bin/${{ matrix.cargo_dylint_binary }}"
|
||||
cp "tools/argument-comment-lint/target/${{ matrix.target }}/release/${{ matrix.lib_name }}" \
|
||||
"$package_root/lib/${{ matrix.lib_name }}"
|
||||
|
||||
archive_path="$dest/${{ matrix.archive_name }}"
|
||||
if [[ "${{ runner.os }}" == "Windows" ]]; then
|
||||
(cd "${RUNNER_TEMP}" && 7z a "$GITHUB_WORKSPACE/$archive_path" argument-comment-lint >/dev/null)
|
||||
else
|
||||
(cd "${RUNNER_TEMP}" && tar -czf "$GITHUB_WORKSPACE/$archive_path" argument-comment-lint)
|
||||
fi
|
||||
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: argument-comment-lint-${{ matrix.target }}
|
||||
path: dist/argument-comment-lint/${{ matrix.target }}/*
|
||||
57
reference/openai-codex/.github/workflows/rust-release-prepare.yml
vendored
Normal file
57
reference/openai-codex/.github/workflows/rust-release-prepare.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: rust-release-prepare
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 */4 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
# Prevent scheduled runs on forks (no secrets, wastes Actions minutes)
|
||||
if: github.repository == 'openai/codex'
|
||||
environment:
|
||||
name: rust-release-prepare
|
||||
deployment: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Update models.json
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
client_version="99.99.99"
|
||||
terminal_info="github-actions"
|
||||
user_agent="codex_cli_rs/99.99.99 (Linux $(uname -r); $(uname -m)) ${terminal_info}"
|
||||
base_url="${OPENAI_BASE_URL:-https://chatgpt.com/backend-api/codex}"
|
||||
|
||||
headers=(
|
||||
-H "Authorization: Bearer ${OPENAI_API_KEY}"
|
||||
-H "User-Agent: ${user_agent}"
|
||||
)
|
||||
|
||||
url="${base_url%/}/models?client_version=${client_version}"
|
||||
curl --http1.1 --fail --show-error --location "${headers[@]}" "${url}" | jq '.' > codex-rs/models-manager/models.json
|
||||
|
||||
- name: Open pull request (if changed)
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
commit-message: "Update models.json"
|
||||
title: "Update models.json"
|
||||
body: "Automated update of models.json."
|
||||
branch: "bot/update-models-json"
|
||||
reviewers: "pakrym-oai,aibrahim-oai"
|
||||
delete-branch: true
|
||||
342
reference/openai-codex/.github/workflows/rust-release-windows.yml
vendored
Normal file
342
reference/openai-codex/.github/workflows/rust-release-windows.yml
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
name: rust-release-windows
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
release-lto:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AZURE_TRUSTED_SIGNING_CLIENT_ID:
|
||||
required: true
|
||||
AZURE_TRUSTED_SIGNING_TENANT_ID:
|
||||
required: true
|
||||
AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID:
|
||||
required: true
|
||||
AZURE_TRUSTED_SIGNING_ENDPOINT:
|
||||
required: true
|
||||
AZURE_TRUSTED_SIGNING_ACCOUNT_NAME:
|
||||
required: true
|
||||
AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build-windows-binaries:
|
||||
name: Build Windows binaries - ${{ matrix.runner }} - ${{ matrix.target }} - ${{ matrix.bundle }}
|
||||
runs-on: ${{ matrix.runs_on }}
|
||||
# Windows release builds can exceed an hour on fat-LTO mainline releases,
|
||||
# so keep the timeout aligned with the top-level release build headroom.
|
||||
timeout-minutes: 90
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
CARGO_PROFILE_RELEASE_LTO: ${{ inputs.release-lto }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: primary
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: primary
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: helpers
|
||||
binaries: "codex-windows-sandbox-setup codex-command-runner"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: helpers
|
||||
binaries: "codex-windows-sandbox-setup codex-command-runner"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: app-server
|
||||
binaries: "codex-app-server"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: app-server
|
||||
binaries: "codex-app-server"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Print runner specs (Windows)
|
||||
shell: powershell
|
||||
run: |
|
||||
$computer = Get-CimInstance Win32_ComputerSystem
|
||||
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
|
||||
$ramGiB = [math]::Round($computer.TotalPhysicalMemory / 1GB, 1)
|
||||
Write-Host "Runner: $env:RUNNER_NAME"
|
||||
Write-Host "OS: $([System.Environment]::OSVersion.VersionString)"
|
||||
Write-Host "CPU: $($cpu.Name)"
|
||||
Write-Host "Logical CPUs: $($computer.NumberOfLogicalProcessors)"
|
||||
Write-Host "Physical CPUs: $($computer.NumberOfProcessors)"
|
||||
Write-Host "Total RAM: $ramGiB GiB"
|
||||
Write-Host "Disk usage:"
|
||||
Get-PSDrive -PSProvider FileSystem | Format-Table -AutoSize Name, @{Name='Size(GB)';Expression={[math]::Round(($_.Used + $_.Free) / 1GB, 1)}}, @{Name='Free(GB)';Expression={[math]::Round($_.Free / 1GB, 1)}}
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Cargo build (Windows binaries)
|
||||
shell: bash
|
||||
run: |
|
||||
build_args=()
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
build_args+=(--bin "$binary")
|
||||
done
|
||||
cargo build --target ${{ matrix.target }} --release --timings "${build_args[@]}"
|
||||
|
||||
- name: Upload Cargo timings
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: cargo-timings-rust-release-windows-${{ matrix.target }}-${{ matrix.bundle }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Stage Windows binaries
|
||||
shell: bash
|
||||
run: |
|
||||
output_dir="target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}"
|
||||
mkdir -p "$output_dir"
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
cp "target/${{ matrix.target }}/release/${binary}.exe" "$output_dir/${binary}.exe"
|
||||
done
|
||||
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-${{ matrix.bundle }}
|
||||
path: |
|
||||
codex-rs/target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}/*
|
||||
|
||||
build-windows:
|
||||
needs:
|
||||
- build-windows-binaries
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runs_on }}
|
||||
timeout-minutes: 90
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
WINDOWS_BINARIES: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner codex-app-server"
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Download prebuilt Windows primary binaries
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-primary
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Download prebuilt Windows helper binaries
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-helpers
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Download prebuilt Windows app-server binary
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-app-server
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Verify binaries
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for binary in ${WINDOWS_BINARIES}; do
|
||||
ls -lh "target/${{ matrix.target }}/release/${binary}.exe"
|
||||
done
|
||||
|
||||
- name: Sign Windows binaries with Azure Trusted Signing
|
||||
uses: ./.github/actions/windows-code-sign
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
binaries: ${{ env.WINDOWS_BINARIES }}
|
||||
client-id: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID }}
|
||||
endpoint: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
|
||||
account-name: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }}
|
||||
certificate-profile-name: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME }}
|
||||
|
||||
- name: Stage artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
dest="dist/${{ matrix.target }}"
|
||||
mkdir -p "$dest"
|
||||
|
||||
for binary in ${WINDOWS_BINARIES}; do
|
||||
cp "target/${{ matrix.target }}/release/${binary}.exe" \
|
||||
"$dest/${binary}-${{ matrix.target }}.exe"
|
||||
done
|
||||
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- name: Build Codex package archives
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for bundle in primary app-server; do
|
||||
bash "${GITHUB_WORKSPACE}/.github/scripts/build-codex-package-archive.sh" \
|
||||
--target "${{ matrix.target }}" \
|
||||
--bundle "$bundle" \
|
||||
--entrypoint-dir "target/${{ matrix.target }}/release" \
|
||||
--archive-dir "dist/${{ matrix.target }}"
|
||||
done
|
||||
|
||||
- name: Build Python runtime wheel
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
case "${{ matrix.target }}" in
|
||||
aarch64-pc-windows-msvc)
|
||||
platform_tag="win_arm64"
|
||||
;;
|
||||
x86_64-pc-windows-msvc)
|
||||
platform_tag="win_amd64"
|
||||
;;
|
||||
*)
|
||||
echo "No Python runtime wheel platform tag for ${{ matrix.target }}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
python -m venv "${RUNNER_TEMP}/python-runtime-build-venv"
|
||||
"${RUNNER_TEMP}/python-runtime-build-venv/Scripts/python.exe" -m pip install build
|
||||
|
||||
stage_dir="${RUNNER_TEMP}/openai-codex-cli-bin-${{ matrix.target }}"
|
||||
wheel_dir="${GITHUB_WORKSPACE}/python-runtime-dist/${{ matrix.target }}"
|
||||
python "${GITHUB_WORKSPACE}/sdk/python/scripts/update_sdk_artifacts.py" \
|
||||
stage-runtime \
|
||||
"$stage_dir" \
|
||||
"dist/${{ matrix.target }}/codex-package-${{ matrix.target }}.tar.gz" \
|
||||
--codex-version "${GITHUB_REF_NAME}" \
|
||||
--platform-tag "$platform_tag"
|
||||
"${RUNNER_TEMP}/python-runtime-build-venv/Scripts/python.exe" -m build --wheel --outdir "$wheel_dir" "$stage_dir"
|
||||
|
||||
- name: Upload Python runtime wheel
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: python-runtime-wheel-${{ matrix.target }}
|
||||
path: python-runtime-dist/${{ matrix.target }}/*.whl
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Compress artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
# Path that contains the uncompressed binaries for the current
|
||||
# ${{ matrix.target }}
|
||||
dest="dist/${{ matrix.target }}"
|
||||
repo_root=$PWD
|
||||
|
||||
# For compatibility with environments that lack the `zstd` tool we
|
||||
# additionally create a `.tar.gz` and `.zip` for every Windows binary.
|
||||
# The end result is:
|
||||
# codex-<target>.zst
|
||||
# codex-<target>.tar.gz
|
||||
# codex-<target>.zip
|
||||
for f in "$dest"/*; do
|
||||
base="$(basename "$f")"
|
||||
# Skip files that are already archives (shouldn't happen, but be
|
||||
# safe).
|
||||
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.
|
||||
# Must run from inside the dest dir so 7z won't embed the
|
||||
# directory path inside the zip.
|
||||
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.
|
||||
# Fall back to the single-binary zip if the helpers are missing
|
||||
# to avoid breaking releases.
|
||||
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"
|
||||
# Use an absolute path so bundle zips land in the real dist
|
||||
# dir even when 7z runs from a temp directory.
|
||||
(cd "$bundle_dir" && 7z a "$repo_root/$dest/${base}.zip" .)
|
||||
else
|
||||
echo "warning: missing sandbox binaries; falling back to single-binary zip"
|
||||
echo "warning: expected $runner_src and $setup_src"
|
||||
(cd "$dest" && 7z a "${base}.zip" "$base")
|
||||
fi
|
||||
rm -rf "$bundle_dir"
|
||||
else
|
||||
(cd "$dest" && 7z a "${base}.zip" "$base")
|
||||
fi
|
||||
|
||||
# Keep raw executables and produce .zst alongside them.
|
||||
"${GITHUB_WORKSPACE}/.github/workflows/zstd" -T0 -19 "$dest/$base"
|
||||
done
|
||||
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: |
|
||||
codex-rs/dist/${{ matrix.target }}/*
|
||||
103
reference/openai-codex/.github/workflows/rust-release-zsh.yml
vendored
Normal file
103
reference/openai-codex/.github/workflows/rust-release-zsh.yml
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
name: rust-release-zsh
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
ZSH_COMMIT: 77045ef899e53b9598bebc5a41db93a548a40ca6
|
||||
ZSH_PATCH: codex-rs/shell-escalation/patches/zsh-exec-wrapper.patch
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
name: Build zsh (Linux) - ${{ matrix.variant }} - ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-musl
|
||||
variant: ubuntu-24.04
|
||||
image: ubuntu:24.04
|
||||
archive_name: codex-zsh-x86_64-unknown-linux-musl.tar.gz
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-musl
|
||||
variant: ubuntu-24.04
|
||||
image: arm64v8/ubuntu:24.04
|
||||
archive_name: codex-zsh-aarch64-unknown-linux-musl.tar.gz
|
||||
|
||||
steps:
|
||||
- name: Install build prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
autoconf \
|
||||
bison \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
gettext \
|
||||
git \
|
||||
libncursesw5-dev
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build, smoke-test, and stage zsh artifact
|
||||
shell: bash
|
||||
run: |
|
||||
"${GITHUB_WORKSPACE}/.github/scripts/build-zsh-release-artifact.sh" \
|
||||
"dist/zsh/${{ matrix.target }}/${{ matrix.archive_name }}"
|
||||
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: codex-zsh-${{ matrix.target }}
|
||||
path: dist/zsh/${{ matrix.target }}/*
|
||||
|
||||
darwin:
|
||||
name: Build zsh (macOS) - ${{ matrix.variant }} - ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: macos-15-large
|
||||
target: x86_64-apple-darwin
|
||||
variant: macos-15
|
||||
archive_name: codex-zsh-x86_64-apple-darwin.tar.gz
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
variant: macos-15
|
||||
archive_name: codex-zsh-aarch64-apple-darwin.tar.gz
|
||||
|
||||
steps:
|
||||
- name: Install build prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if ! command -v autoconf >/dev/null 2>&1; then
|
||||
brew install autoconf
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build, smoke-test, and stage zsh artifact
|
||||
shell: bash
|
||||
run: |
|
||||
"${GITHUB_WORKSPACE}/.github/scripts/build-zsh-release-artifact.sh" \
|
||||
"dist/zsh/${{ matrix.target }}/${{ matrix.archive_name }}"
|
||||
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: codex-zsh-${{ matrix.target }}
|
||||
path: dist/zsh/${{ matrix.target }}/*
|
||||
1562
reference/openai-codex/.github/workflows/rust-release.yml
vendored
Normal file
1562
reference/openai-codex/.github/workflows/rust-release.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
313
reference/openai-codex/.github/workflows/rusty-v8-release.yml
vendored
Normal file
313
reference/openai-codex/.github/workflows/rusty-v8-release.yml
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
name: rusty-v8-release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "rusty-v8-v*.*.*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}::${{ github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
metadata:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_tag: ${{ steps.release_tag.outputs.release_tag }}
|
||||
v8_version: ${{ steps.v8_version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Resolve exact v8 crate version
|
||||
id: v8_version
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="$(python3 .github/scripts/rusty_v8_bazel.py resolved-v8-crate-version)"
|
||||
echo "version=${version}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve release tag
|
||||
id: release_tag
|
||||
env:
|
||||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||||
V8_VERSION: ${{ steps.v8_version.outputs.version }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
expected_release_tag="rusty-v8-v${V8_VERSION}"
|
||||
release_tag="${GITHUB_REF_NAME}"
|
||||
if [[ "${release_tag}" != "${expected_release_tag}" ]]; then
|
||||
echo "Tag ${release_tag} does not match expected release tag ${expected_release_tag}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "release_tag=${release_tag}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.variant }} ${{ matrix.target }}
|
||||
needs: metadata
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64
|
||||
sandbox: false
|
||||
target: x86_64-unknown-linux-gnu
|
||||
variant: release
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64
|
||||
sandbox: true
|
||||
target: x86_64-unknown-linux-gnu
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64
|
||||
sandbox: false
|
||||
target: aarch64-unknown-linux-gnu
|
||||
variant: release
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64
|
||||
sandbox: true
|
||||
target: aarch64-unknown-linux-gnu
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_amd64
|
||||
sandbox: false
|
||||
target: x86_64-apple-darwin
|
||||
variant: release
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_amd64
|
||||
sandbox: true
|
||||
target: x86_64-apple-darwin
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_arm64
|
||||
sandbox: false
|
||||
target: aarch64-apple-darwin
|
||||
variant: release
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_arm64
|
||||
sandbox: true
|
||||
target: aarch64-apple-darwin
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64_musl
|
||||
sandbox: false
|
||||
target: x86_64-unknown-linux-musl
|
||||
variant: release
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64_musl
|
||||
sandbox: false
|
||||
target: aarch64-unknown-linux-musl
|
||||
variant: release
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64_musl
|
||||
sandbox: true
|
||||
target: x86_64-unknown-linux-musl
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64_musl
|
||||
sandbox: true
|
||||
target: aarch64-unknown-linux-musl
|
||||
variant: ptrcomp-sandbox
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Set up Rust toolchain for Cargo smoke
|
||||
uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Build Bazel V8 release pair
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
target_suffix="${TARGET//-/_}"
|
||||
pair_kind="release_pair"
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
pair_kind="sandbox_release_pair"
|
||||
fi
|
||||
pair_target="//third_party/v8:rusty_v8_${pair_kind}_${target_suffix}"
|
||||
|
||||
bazel_args=(
|
||||
build
|
||||
-c
|
||||
opt
|
||||
"--platforms=@llvm//platforms:${PLATFORM}"
|
||||
--config=rusty-v8-upstream-libcxx
|
||||
"${pair_target}"
|
||||
--build_metadata=COMMIT_SHA=$(git rev-parse HEAD)
|
||||
)
|
||||
if [[ "${SANDBOX}" != "true" ]]; then
|
||||
bazel_args+=(--config=v8-release-compat)
|
||||
fi
|
||||
|
||||
bazel \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
"${bazel_args[@]}" \
|
||||
"--config=${{ matrix.bazel_config }}" \
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
|
||||
- name: Stage release pair
|
||||
env:
|
||||
BAZEL_CONFIG: ${{ matrix.bazel_config }}
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
stage_args=(
|
||||
--platform "${PLATFORM}"
|
||||
--target "${TARGET}"
|
||||
--compilation-mode opt
|
||||
--output-dir "dist/${TARGET}"
|
||||
--bazel-config "${BAZEL_CONFIG}"
|
||||
)
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
stage_args+=(--sandbox)
|
||||
else
|
||||
stage_args+=(--bazel-config v8-release-compat)
|
||||
fi
|
||||
|
||||
python3 .github/scripts/rusty_v8_bazel.py stage-release-pair "${stage_args[@]}"
|
||||
|
||||
- name: Smoke test staged artifact with Cargo
|
||||
env:
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
host_arch="$(uname -m)"
|
||||
case "${TARGET}:${host_arch}" in
|
||||
x86_64-apple-darwin:x86_64|aarch64-apple-darwin:arm64|x86_64-unknown-linux-gnu:x86_64|aarch64-unknown-linux-gnu:aarch64)
|
||||
;;
|
||||
*)
|
||||
echo "Skipping non-native Cargo smoke for ${TARGET} on ${host_arch}."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
archive="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'librusty_v8_*.a.gz' -print -quit)"
|
||||
binding="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'src_binding_*.rs' -print -quit)"
|
||||
if [[ -z "${archive}" || -z "${binding}" ]]; then
|
||||
echo "Missing staged archive or binding for ${TARGET}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cargo_args=(test -p codex-v8-poc)
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
cargo_args+=(--features sandbox)
|
||||
fi
|
||||
|
||||
(
|
||||
cd codex-rs
|
||||
CARGO_TARGET_DIR="${RUNNER_TEMP}/rusty-v8-cargo-smoke-${TARGET}-${SANDBOX}" \
|
||||
RUSTY_V8_ARCHIVE="${GITHUB_WORKSPACE}/${archive}" \
|
||||
RUSTY_V8_SRC_BINDING_PATH="${GITHUB_WORKSPACE}/${binding}" \
|
||||
cargo "${cargo_args[@]}"
|
||||
)
|
||||
|
||||
- name: Upload staged artifacts
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: rusty-v8-${{ needs.metadata.outputs.v8_version }}-${{ matrix.variant }}-${{ matrix.target }}
|
||||
path: dist/${{ matrix.target }}/*
|
||||
|
||||
publish-release:
|
||||
needs:
|
||||
- metadata
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: Check whether release already exists
|
||||
id: release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" > /dev/null 2>&1; then
|
||||
echo "exists=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "exists=false" >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
|
||||
- name: Create GitHub Release
|
||||
if: ${{ steps.release.outputs.exists != 'true' }}
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
tag_name: ${{ needs.metadata.outputs.release_tag }}
|
||||
name: ${{ needs.metadata.outputs.release_tag }}
|
||||
files: dist/**
|
||||
# Keep V8 artifact releases out of Codex's normal "latest release" channel.
|
||||
prerelease: true
|
||||
|
||||
- name: Amend existing GitHub Release
|
||||
if: ${{ steps.release.outputs.exists == 'true' }}
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
tag_name: ${{ needs.metadata.outputs.release_tag }}
|
||||
name: ${{ needs.metadata.outputs.release_tag }}
|
||||
files: dist/**
|
||||
overwrite_files: true
|
||||
# Keep V8 artifact releases out of Codex's normal "latest release" channel.
|
||||
prerelease: true
|
||||
160
reference/openai-codex/.github/workflows/sdk.yml
vendored
Normal file
160
reference/openai-codex/.github/workflows/sdk.yml
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
name: sdk
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request: {}
|
||||
|
||||
jobs:
|
||||
python-sdk:
|
||||
runs-on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Test Python SDK
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Run inside Alpine so dependency resolution exercises the pinned
|
||||
# runtime wheel on the same Linux wheel family that CI installs.
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-e HOME=/tmp/codex-python-sdk-home \
|
||||
-e UV_LINK_MODE=copy \
|
||||
-v "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \
|
||||
-w "${GITHUB_WORKSPACE}/sdk/python" \
|
||||
python:3.12-alpine \
|
||||
sh -euxc '
|
||||
python -m venv /tmp/uv
|
||||
/tmp/uv/bin/python -m pip install uv==0.11.3
|
||||
/tmp/uv/bin/uv sync --extra dev --frozen
|
||||
/tmp/uv/bin/uv run --extra dev ruff check --output-format=github .
|
||||
/tmp/uv/bin/uv run --extra dev ruff format --check .
|
||||
/tmp/uv/bin/uv run --extra dev pytest
|
||||
'
|
||||
|
||||
sdks:
|
||||
runs-on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Linux bwrap build dependencies
|
||||
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: Setup pnpm
|
||||
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: x86_64-unknown-linux-gnu
|
||||
|
||||
- name: Build codex with Bazel
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Use the shared CI wrapper so fork PRs fall back cleanly when
|
||||
# BuildBuddy credentials are unavailable. This workflow needs the
|
||||
# built `codex` binary on disk afterwards, so ask the wrapper to
|
||||
# override CI's default remote_download_minimal behavior.
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
--remote-download-toplevel \
|
||||
-- \
|
||||
build \
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \
|
||||
--build_metadata=TAG_job=sdk \
|
||||
-- \
|
||||
//codex-rs/cli:codex
|
||||
|
||||
# Resolve the exact output file using the same wrapper/config path as
|
||||
# the build instead of guessing which Bazel convenience symlink is
|
||||
# available on the runner.
|
||||
cquery_output="$(
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
-- \
|
||||
cquery \
|
||||
--output=files \
|
||||
-- \
|
||||
//codex-rs/cli:codex \
|
||||
| grep -E '^(/|bazel-out/)' \
|
||||
| tail -n 1
|
||||
)"
|
||||
if [[ "${cquery_output}" = /* ]]; then
|
||||
codex_bazel_output_path="${cquery_output}"
|
||||
else
|
||||
codex_bazel_output_path="${GITHUB_WORKSPACE}/${cquery_output}"
|
||||
fi
|
||||
if [[ -z "${codex_bazel_output_path}" ]]; then
|
||||
echo "Bazel did not report an output path for //codex-rs/cli:codex." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -e "${codex_bazel_output_path}" ]]; then
|
||||
echo "Unable to locate the Bazel-built codex binary at ${codex_bazel_output_path}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stage the binary into the workspace and point the SDK tests at that
|
||||
# stable path. The tests spawn `codex` directly many times, so using a
|
||||
# normal executable path is more reliable than invoking Bazel for each
|
||||
# test process.
|
||||
install_dir="${GITHUB_WORKSPACE}/.tmp/sdk-ci"
|
||||
mkdir -p "${install_dir}"
|
||||
install -m 755 "${codex_bazel_output_path}" "${install_dir}/codex"
|
||||
echo "CODEX_EXEC_PATH=${install_dir}/codex" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Warm up Bazel-built codex
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
"${CODEX_EXEC_PATH}" --version
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build SDK packages
|
||||
run: pnpm -r --filter ./sdk/typescript run build
|
||||
|
||||
- name: Lint SDK packages
|
||||
run: pnpm -r --filter ./sdk/typescript run lint
|
||||
|
||||
- name: Test SDK packages
|
||||
run: pnpm -r --filter ./sdk/typescript run test
|
||||
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/bazel-repo-cache
|
||||
key: bazel-cache-x86_64-unknown-linux-gnu-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
411
reference/openai-codex/.github/workflows/v8-canary.yml
vendored
Normal file
411
reference/openai-codex/.github/workflows/v8-canary.yml
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
name: v8-canary
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".bazelrc"
|
||||
- ".github/actions/setup-bazel-ci/**"
|
||||
- ".github/scripts/rusty_v8_bazel.py"
|
||||
- ".github/scripts/rusty_v8_module_bazel.py"
|
||||
- ".github/workflows/rusty-v8-release.yml"
|
||||
- ".github/workflows/v8-canary.yml"
|
||||
- "MODULE.bazel"
|
||||
- "MODULE.bazel.lock"
|
||||
- "codex-rs/Cargo.toml"
|
||||
- "patches/BUILD.bazel"
|
||||
- "patches/llvm_*.patch"
|
||||
- "patches/rules_cc_*.patch"
|
||||
- "patches/v8_*.patch"
|
||||
- "third_party/v8/**"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".bazelrc"
|
||||
- ".github/actions/setup-bazel-ci/**"
|
||||
- ".github/scripts/rusty_v8_bazel.py"
|
||||
- ".github/scripts/rusty_v8_module_bazel.py"
|
||||
- ".github/workflows/rusty-v8-release.yml"
|
||||
- ".github/workflows/v8-canary.yml"
|
||||
- "MODULE.bazel"
|
||||
- "MODULE.bazel.lock"
|
||||
- "codex-rs/Cargo.toml"
|
||||
- "patches/BUILD.bazel"
|
||||
- "patches/llvm_*.patch"
|
||||
- "patches/rules_cc_*.patch"
|
||||
- "patches/v8_*.patch"
|
||||
- "third_party/v8/**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}::${{ github.event.pull_request.number > 0 && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}
|
||||
cancel-in-progress: ${{ github.ref_name != 'main' }}
|
||||
|
||||
jobs:
|
||||
metadata:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
v8_version: ${{ steps.v8_version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Resolve exact v8 crate version
|
||||
id: v8_version
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="$(python3 .github/scripts/rusty_v8_bazel.py resolved-v8-crate-version)"
|
||||
echo "version=${version}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.variant }} ${{ matrix.target }}
|
||||
needs: metadata
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64
|
||||
sandbox: false
|
||||
target: x86_64-unknown-linux-gnu
|
||||
variant: release
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64
|
||||
sandbox: true
|
||||
target: x86_64-unknown-linux-gnu
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64
|
||||
sandbox: false
|
||||
target: aarch64-unknown-linux-gnu
|
||||
variant: release
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64
|
||||
sandbox: true
|
||||
target: aarch64-unknown-linux-gnu
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_amd64
|
||||
sandbox: false
|
||||
target: x86_64-apple-darwin
|
||||
variant: release
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_amd64
|
||||
sandbox: true
|
||||
target: x86_64-apple-darwin
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_arm64
|
||||
sandbox: false
|
||||
target: aarch64-apple-darwin
|
||||
variant: release
|
||||
- runner: macos-15-xlarge
|
||||
bazel_config: ci-macos
|
||||
platform: macos_arm64
|
||||
sandbox: true
|
||||
target: aarch64-apple-darwin
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64_musl
|
||||
sandbox: false
|
||||
target: x86_64-unknown-linux-musl
|
||||
variant: release
|
||||
- runner: ubuntu-24.04
|
||||
bazel_config: ci-v8
|
||||
platform: linux_amd64_musl
|
||||
sandbox: true
|
||||
target: x86_64-unknown-linux-musl
|
||||
variant: ptrcomp-sandbox
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64_musl
|
||||
sandbox: false
|
||||
target: aarch64-unknown-linux-musl
|
||||
variant: release
|
||||
- runner: ubuntu-24.04-arm
|
||||
bazel_config: ci-v8
|
||||
platform: linux_arm64_musl
|
||||
sandbox: true
|
||||
target: aarch64-unknown-linux-musl
|
||||
variant: ptrcomp-sandbox
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Set up Rust toolchain for Cargo smoke
|
||||
uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Build Bazel V8 release pair
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
target_suffix="${TARGET//-/_}"
|
||||
pair_kind="release_pair"
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
pair_kind="sandbox_release_pair"
|
||||
fi
|
||||
pair_target="//third_party/v8:rusty_v8_${pair_kind}_${target_suffix}"
|
||||
|
||||
bazel_args=(
|
||||
build
|
||||
"--platforms=@llvm//platforms:${PLATFORM}"
|
||||
--config=rusty-v8-upstream-libcxx
|
||||
"${pair_target}"
|
||||
--build_metadata=COMMIT_SHA=$(git rev-parse HEAD)
|
||||
)
|
||||
if [[ "${SANDBOX}" != "true" ]]; then
|
||||
bazel_args+=(--config=v8-release-compat)
|
||||
fi
|
||||
|
||||
bazel \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
"${bazel_args[@]}" \
|
||||
"--config=${{ matrix.bazel_config }}" \
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
|
||||
- name: Stage release pair
|
||||
env:
|
||||
BAZEL_CONFIG: ${{ matrix.bazel_config }}
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
stage_args=(
|
||||
--platform "${PLATFORM}"
|
||||
--target "${TARGET}"
|
||||
--output-dir "dist/${TARGET}"
|
||||
--bazel-config "${BAZEL_CONFIG}"
|
||||
)
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
stage_args+=(--sandbox)
|
||||
else
|
||||
stage_args+=(--bazel-config v8-release-compat)
|
||||
fi
|
||||
|
||||
python3 .github/scripts/rusty_v8_bazel.py stage-release-pair "${stage_args[@]}"
|
||||
|
||||
- name: Smoke test staged artifact with Cargo
|
||||
env:
|
||||
SANDBOX: ${{ matrix.sandbox }}
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
host_arch="$(uname -m)"
|
||||
case "${TARGET}:${host_arch}" in
|
||||
x86_64-apple-darwin:x86_64|aarch64-apple-darwin:arm64|x86_64-unknown-linux-gnu:x86_64|aarch64-unknown-linux-gnu:aarch64)
|
||||
;;
|
||||
*)
|
||||
echo "Skipping non-native Cargo smoke for ${TARGET} on ${host_arch}."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
archive="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'librusty_v8_*.a.gz' -print -quit)"
|
||||
binding="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'src_binding_*.rs' -print -quit)"
|
||||
if [[ -z "${archive}" || -z "${binding}" ]]; then
|
||||
echo "Missing staged archive or binding for ${TARGET}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cargo_args=(test -p codex-v8-poc)
|
||||
if [[ "${SANDBOX}" == "true" ]]; then
|
||||
cargo_args+=(--features sandbox)
|
||||
fi
|
||||
|
||||
(
|
||||
cd codex-rs
|
||||
CARGO_TARGET_DIR="${RUNNER_TEMP}/rusty-v8-cargo-smoke-${TARGET}-${SANDBOX}" \
|
||||
RUSTY_V8_ARCHIVE="${GITHUB_WORKSPACE}/${archive}" \
|
||||
RUSTY_V8_SRC_BINDING_PATH="${GITHUB_WORKSPACE}/${binding}" \
|
||||
cargo "${cargo_args[@]}"
|
||||
)
|
||||
|
||||
- name: Upload staged artifacts
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: v8-canary-${{ needs.metadata.outputs.v8_version }}-${{ matrix.variant }}-${{ matrix.target }}
|
||||
path: dist/${{ matrix.target }}/*
|
||||
|
||||
build-windows-source:
|
||||
name: Build ptrcomp-sandbox ${{ matrix.target }} from source
|
||||
needs: metadata
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: windows-2022
|
||||
target: x86_64-pc-windows-msvc
|
||||
- runner: windows-2022
|
||||
target: aarch64-pc-windows-msvc
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Configure git for upstream checkout
|
||||
shell: bash
|
||||
run: git config --global core.symlinks true
|
||||
|
||||
- name: Check out upstream rusty_v8
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
repository: denoland/rusty_v8
|
||||
ref: v${{ needs.metadata.outputs.v8_version }}
|
||||
path: upstream-rusty-v8
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
architecture: x64
|
||||
|
||||
- name: Set up Codex Rust toolchain for Cargo smoke
|
||||
uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Install rusty_v8 Rust toolchain
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rustup toolchain install 1.91.0 --profile minimal --no-self-update
|
||||
rustup target add --toolchain 1.91.0 "${TARGET}"
|
||||
|
||||
- name: Write upstream submodule status
|
||||
shell: bash
|
||||
working-directory: upstream-rusty-v8
|
||||
run: git submodule status --recursive > git_submodule_status.txt
|
||||
|
||||
- name: Restore upstream source-build cache
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
upstream-rusty-v8/target/sccache
|
||||
upstream-rusty-v8/target/${{ matrix.target }}/release/gn_out
|
||||
key: rusty-v8-source-${{ matrix.target }}-sandbox-${{ hashFiles('upstream-rusty-v8/Cargo.lock', 'upstream-rusty-v8/build.rs', 'upstream-rusty-v8/git_submodule_status.txt') }}
|
||||
restore-keys: |
|
||||
rusty-v8-source-${{ matrix.target }}-sandbox-
|
||||
|
||||
- name: Install and start sccache
|
||||
shell: pwsh
|
||||
env:
|
||||
SCCACHE_CACHE_SIZE: 256M
|
||||
SCCACHE_DIR: ${{ github.workspace }}/upstream-rusty-v8/target/sccache
|
||||
SCCACHE_IDLE_TIMEOUT: 0
|
||||
run: |
|
||||
$version = "v0.8.2"
|
||||
$platform = "x86_64-pc-windows-msvc"
|
||||
$basename = "sccache-$version-$platform"
|
||||
$url = "https://github.com/mozilla/sccache/releases/download/$version/$basename.tar.gz"
|
||||
cd ~
|
||||
curl -LO $url
|
||||
tar -xzvf "$basename.tar.gz"
|
||||
. $basename/sccache --start-server
|
||||
echo "$(pwd)/$basename" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Install Chromium clang for ARM64 MSVC cross build
|
||||
if: matrix.target == 'aarch64-pc-windows-msvc'
|
||||
shell: bash
|
||||
working-directory: upstream-rusty-v8
|
||||
run: python3 tools/clang/scripts/update.py
|
||||
|
||||
- name: Build upstream rusty_v8 sandbox release pair
|
||||
env:
|
||||
SCCACHE_IDLE_TIMEOUT: 0
|
||||
TARGET: ${{ matrix.target }}
|
||||
V8_FROM_SOURCE: "1"
|
||||
shell: bash
|
||||
working-directory: upstream-rusty-v8
|
||||
run: cargo +1.91.0 build --locked --release --target "${TARGET}" --features v8_enable_sandbox
|
||||
|
||||
- name: Stage upstream sandbox release pair
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 .github/scripts/rusty_v8_bazel.py stage-upstream-release-pair \
|
||||
--source-root upstream-rusty-v8 \
|
||||
--target "${TARGET}" \
|
||||
--output-dir "dist/${TARGET}" \
|
||||
--sandbox
|
||||
|
||||
- name: Smoke link staged artifact with Cargo
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
archive="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'rusty_v8_*.lib.gz' -print -quit)"
|
||||
binding="$(find "dist/${TARGET}" -maxdepth 1 -type f -name 'src_binding_*.rs' -print -quit)"
|
||||
if [[ -z "${archive}" || -z "${binding}" ]]; then
|
||||
echo "Missing staged archive or binding for ${TARGET}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
(
|
||||
cd codex-rs
|
||||
RUSTY_V8_ARCHIVE="${GITHUB_WORKSPACE}/${archive}" \
|
||||
RUSTY_V8_SRC_BINDING_PATH="${GITHUB_WORKSPACE}/${binding}" \
|
||||
cargo +1.93.0 test -p codex-v8-poc --target "${TARGET}" --features sandbox --no-run
|
||||
)
|
||||
|
||||
- name: Upload staged artifacts
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: v8-canary-${{ needs.metadata.outputs.v8_version }}-ptrcomp-sandbox-${{ matrix.target }}
|
||||
path: dist/${{ matrix.target }}/*
|
||||
46
reference/openai-codex/.github/workflows/zstd
vendored
Executable file
46
reference/openai-codex/.github/workflows/zstd
vendored
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env dotslash
|
||||
|
||||
// This DotSlash file wraps zstd for Windows runners.
|
||||
// The upstream release provides win32/win64 binaries; for windows-aarch64 we
|
||||
// use the win64 artifact via Windows x64 emulation.
|
||||
{
|
||||
"name": "zstd",
|
||||
"platforms": {
|
||||
"windows-x86_64": {
|
||||
"size": 1747181,
|
||||
"hash": "sha256",
|
||||
"digest": "acb4e8111511749dc7a3ebedca9b04190e37a17afeb73f55d4425dbf0b90fad9",
|
||||
"format": "zip",
|
||||
"path": "zstd-v1.5.7-win64/zstd.exe",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-v1.5.7-win64.zip"
|
||||
},
|
||||
{
|
||||
"type": "github-release",
|
||||
"repo": "facebook/zstd",
|
||||
"tag": "v1.5.7",
|
||||
"name": "zstd-v1.5.7-win64.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"size": 1747181,
|
||||
"hash": "sha256",
|
||||
"digest": "acb4e8111511749dc7a3ebedca9b04190e37a17afeb73f55d4425dbf0b90fad9",
|
||||
"format": "zip",
|
||||
"path": "zstd-v1.5.7-win64/zstd.exe",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-v1.5.7-win64.zip"
|
||||
},
|
||||
{
|
||||
"type": "github-release",
|
||||
"repo": "facebook/zstd",
|
||||
"tag": "v1.5.7",
|
||||
"name": "zstd-v1.5.7-win64.zip"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user