From bd1f3439079fb29c004a65d61453f666884b842c Mon Sep 17 00:00:00 2001 From: Jeffrie Budde <39542105+JSBtechnologies@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:58:07 -0500 Subject: [PATCH 1/2] ci: make the fork's PR checks meaningful Upstream's CI assumes OpenAI infrastructure (self-hosted runner groups, paid macOS runners, a BuildBuddy cache, signing and publishing secrets, an OpenAI API key for the issue bots). In the fork those jobs fail in seconds or queue forever, so every PR is red for reasons unrelated to the change. - blocking-ci.yml: drop the `bazel` and `sdk` calls and their `required` entries, with a comment explaining why. - rust-ci.yml: the Bazel-backed "Argument comment lint" matrix is upstream-only (`if: github.repository == 'openai/codex'`); `results` accepts it being skipped outside upstream. - scripts/fork-ci-disable.sh: disables, as a repository setting, the workflows that only make sense upstream (post-merge full CI, V8 canary, release and publishing workflows, issue bots, stale-PR sweeper, CLA). - docs/fork-ci.md: what runs, what is off, and how to resolve conflicts on these lines when merging upstream. Also fix the three real findings those checks had surfaced: - verify_cargo_workspace_manifests.py: code-mode no longer declares the `sandbox` feature, so its exception was stale. - core tests: `scenarios_read_only_mcp.rs` is a one-line stub that no module declares (upstream main is in the same state, with the snapshot left behind). Delete the stub and its orphaned snapshot so cargo shear stops flagging an unlinked file. - .codespellignore: `WRONLY` (O_WRONLY) and `oint` (LaTeX \oint). --- .codespellignore | 2 + .../verify_cargo_workspace_manifests.py | 1 - .github/workflows/blocking-ci.yml | 19 +++----- .github/workflows/rust-ci.yml | 13 ++++- .../tests/suite/scenarios_read_only_mcp.rs | 1 - ...read_only_mcp__read_only_mcp_requests.snap | 48 ------------------- docs/fork-ci.md | 47 ++++++++++++++++++ scripts/fork-ci-disable.sh | 47 ++++++++++++++++++ 8 files changed, 115 insertions(+), 63 deletions(-) delete mode 100644 codex-rs/core/tests/suite/scenarios_read_only_mcp.rs delete mode 100644 codex-rs/core/tests/suite/snapshots/all__suite__scenarios__read_only_mcp__read_only_mcp_requests.snap create mode 100644 docs/fork-ci.md create mode 100644 scripts/fork-ci-disable.sh diff --git a/.codespellignore b/.codespellignore index 4f3c8c3513b5..4d667d914122 100644 --- a/.codespellignore +++ b/.codespellignore @@ -5,3 +5,5 @@ psuedo SOM te TE +WRONLY +oint diff --git a/.github/scripts/verify_cargo_workspace_manifests.py b/.github/scripts/verify_cargo_workspace_manifests.py index 645c6c59e5c9..a8c6c28602f2 100644 --- a/.github/scripts/verify_cargo_workspace_manifests.py +++ b/.github/scripts/verify_cargo_workspace_manifests.py @@ -26,7 +26,6 @@ "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() diff --git a/.github/workflows/blocking-ci.yml b/.github/workflows/blocking-ci.yml index c6f00555a355..e62039b693c6 100644 --- a/.github/workflows/blocking-ci.yml +++ b/.github/workflows/blocking-ci.yml @@ -10,11 +10,13 @@ on: jobs: # Keep reusable workflow calls alphabetized. The `required` job below is the # version-controlled list that the main-branch ruleset should require. - bazel: - name: Bazel - uses: ./.github/workflows/bazel.yml - secrets: inherit - + # + # Fork (JSBtechnologies/codex): the `bazel` and `sdk` calls are left out. + # Upstream runs them on OpenAI's self-hosted runner groups (-runners, + # -windows-x64, macos-15-xlarge) with a BuildBuddy remote cache. None of + # that exists here, so they fail in seconds or queue forever and only produce + # false positives. Re-add them (and their `required.needs` entries) if that + # infrastructure is ever set up. See docs/fork-ci.md. blob-size-policy: name: Blob size policy uses: ./.github/workflows/blob-size-policy.yml @@ -40,24 +42,17 @@ jobs: uses: ./.github/workflows/rust-ci.yml secrets: inherit - sdk: - name: sdk - uses: ./.github/workflows/sdk.yml - secrets: inherit - required: name: CI required # Without `always()`, GitHub skips this job after a failed dependency and a # required check can appear successful instead of reporting the failure. if: ${{ always() }} needs: - - bazel - blob-size-policy - cargo-deny - codespell - repo-checks - rust-ci - - sdk runs-on: ubuntu-24.04 steps: # Keep the helper on the same combined revision as the child workflows so diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index ae24051e9c64..268f596724ca 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -166,6 +166,11 @@ jobs: runs-on: ${{ matrix.runs_on || matrix.runner }} timeout-minutes: ${{ matrix.timeout_minutes }} needs: changed + # Fork: this job runs Bazel through OpenAI's BuildBuddy cache on a + # self-hosted Windows runner and a paid macOS runner. In the fork it fails + # instantly or queues forever, so it is upstream-only; `results` below + # accepts it being skipped outside openai/codex. See docs/fork-ci.md. + if: ${{ github.repository == 'openai/codex' }} environment: name: bazel deployment: false @@ -249,7 +254,13 @@ jobs: 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; } + # Fork: the prebuilt lint is upstream-only (see its `if`), so a + # skipped result is acceptable outside openai/codex. + if [[ '${{ github.repository }}' == 'openai/codex' ]]; then + [[ '${{ needs.argument_comment_lint_prebuilt.result }}' == 'success' ]] || { echo 'argument_comment_lint_prebuilt failed'; exit 1; } + else + [[ '${{ needs.argument_comment_lint_prebuilt.result }}' == 'success' || '${{ needs.argument_comment_lint_prebuilt.result }}' == 'skipped' ]] || { echo 'argument_comment_lint_prebuilt failed'; exit 1; } + fi fi if [[ "${NEEDS_CHANGED_OUTPUTS_CODEX}" == 'true' || "${NEEDS_CHANGED_OUTPUTS_WORKFLOWS}" == 'true' ]]; then diff --git a/codex-rs/core/tests/suite/scenarios_read_only_mcp.rs b/codex-rs/core/tests/suite/scenarios_read_only_mcp.rs deleted file mode 100644 index 2cad1c9307f1..000000000000 --- a/codex-rs/core/tests/suite/scenarios_read_only_mcp.rs +++ /dev/null @@ -1 +0,0 @@ -//! Thread policy reaches MCP discovery and execution without relying on model arguments. diff --git a/codex-rs/core/tests/suite/snapshots/all__suite__scenarios__read_only_mcp__read_only_mcp_requests.snap b/codex-rs/core/tests/suite/snapshots/all__suite__scenarios__read_only_mcp__read_only_mcp_requests.snap deleted file mode 100644 index 4bd889eed630..000000000000 --- a/codex-rs/core/tests/suite/snapshots/all__suite__scenarios__read_only_mcp__read_only_mcp_requests.snap +++ /dev/null @@ -1,48 +0,0 @@ ---- -source: core/tests/suite/scenarios_read_only_mcp.rs -expression: "context_snapshot::format_request_history_snapshot(\"A read-only thread receives only read tools from the MCP server and executes a read.\",\n&mock.requests(),\n&ContextSnapshotOptions::default().rewrite_known_segments().include_request_settings(),)" ---- -Scenario: A read-only thread receives only read tools from the MCP server and executes a read. - -## Window 1 -Settings: - include: ["reasoning.encrypted_content"] - model: "gpt-5.5" - parallel_tool_calls: true - prompt_cache_key: "" - reasoning: {"effort":"medium"} - store: false - stream: true - text: {"verbosity":"low"} - tool_choice: "auto" - tools (11; hash=14a76ba72d609d9e): - - function/exec_command: Runs a command in a PTY, returning output or a session ID for ongoing interaction.; args=[cmd, justification, login, max_output_tokens, prefix_rule, sandbox_permissions, shell, tty, workdir, yield_time_ms]; hash=c04108e51a8548c5 - - function/write_stdin: Writes characters to an existing unified exec session and returns recent output.; args=[chars, max_output_tokens, session_id, yield_time_ms]; hash=7fb62d8a3e2df4e2 - - function/list_mcp_resources: Lists resources provided by MCP servers. Resources allow servers to share data that provides cont...; args=[cursor, server]; hash=6792edaff13561bd - - function/list_mcp_resource_templates: Lists resource templates provided by MCP servers. Parameterized resource templates allow servers ...; args=[cursor, server]; hash=60f17c90ef7a4ebb - - function/read_mcp_resource: Read a specific resource from an MCP server given the server name and resource URI.; args=[server, uri]; hash=24246896b39008ae - - function/request_user_input: Request user input for one to three short questions and wait for the response. This tool is only ...; args=[questions]; hash=64a729b25c424fc6 - - custom/apply_patch: The `apply_patch` tool can be used to edit files. This is a FREEFORM tool, so do not wrap the pat...; hash=dea9f12b0111a4ba - - function/view_image: View a local image file from the filesystem when visual inspection is needed. Use this for images...; args=[detail, path]; hash=3b766d5bdec5d50e - - namespace/multi_agent_v1: Tools for spawning and managing sub-agents.; hash=2327142bda177c50 - - function/close_agent - - function/resume_agent - - function/send_input - - function/spawn_agent - - function/wait_agent - - namespace/mcp__policy: Tools in the mcp__policy namespace.; hash=4868c429e15f1bec - - function/read - - web_search; hash=e214d4db1bc49e89 --- request 1 (turn) -- -00:message/developer: - -01:message/developer: - -02:message/user: - -03:message/user: - Read the report. --- request 2 (turn) -- -04:function_call/mcp__policy.read:{} -05:function_call_output:Wall time: seconds - Output: | Report ready. diff --git a/docs/fork-ci.md b/docs/fork-ci.md new file mode 100644 index 000000000000..cd7df63d72a3 --- /dev/null +++ b/docs/fork-ci.md @@ -0,0 +1,47 @@ +# CI in the fork (JSBtechnologies/codex) + +Upstream's CI assumes OpenAI infrastructure: self-hosted runner groups +(`-runners`, `-windows-x64`, `-linux-x64-xl`), paid +`macos-15-xlarge` runners, a BuildBuddy remote cache, code-signing and +publishing secrets, and an OpenAI API key for the issue bots. None of that +exists in the fork, so those jobs either fail in seconds or queue forever, and +every PR shows red checks that mean nothing. This document records exactly what +the fork turns off, so a red check here is a real finding. + +## What runs on a PR + +`blocking-ci.yml` is the PR gate. In the fork it calls: + +| reusable workflow | what it checks | +|---|---| +| `blob-size-policy.yml` | no oversized blobs committed | +| `cargo-deny.yml` | licenses and advisories | +| `codespell.yml` | spelling | +| `repo-checks.yml` | Cargo manifests inherit workspace settings, TUI/core boundary, Bazel clippy lints | +| `rust-ci.yml` | format, clippy, tests for changed crates, `cargo shear`, the argument-comment lint for packages | + +Removed from the gate in the fork, in the workflow file with a comment: the +`bazel` and `sdk` calls. Inside `rust-ci.yml`, the "Argument comment lint - +Linux/macOS/Windows" job is guarded with `if: github.repository == +'openai/codex'` and the `results` job accepts it being skipped outside upstream. + +## What is disabled as a repository setting + +`scripts/fork-ci-disable.sh` disables, via `gh workflow disable`, the workflows +that only make sense upstream: post-merge full CI on self-hosted runners, the +V8 canary, all upstream release and publishing workflows, the issue bots, the +stale-PR sweeper and the CLA assistant. Run it again after merging upstream if +new infra-bound workflows appear. `gh workflow enable ` reverts any of +them. + +## What the fork adds + +`fork-release.yml` builds and publishes fork releases on `fork-v*` tags using +GitHub-hosted runners only. See the header of that file. + +## Merging upstream + +The fork's edits to upstream workflow files are deliberately small and marked +with `Fork:` comments: `blocking-ci.yml` (two calls and two `needs` entries +removed) and `rust-ci.yml` (one `if:` and one branch in `results`). When an +upstream merge conflicts there, keep the fork's version of those lines. diff --git a/scripts/fork-ci-disable.sh b/scripts/fork-ci-disable.sh new file mode 100644 index 000000000000..17bfdd9f59a9 --- /dev/null +++ b/scripts/fork-ci-disable.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Fork (JSBtechnologies/codex): disable the upstream workflows that cannot run +# here, so they stop producing false-positive failures in the Actions tab. +# +# Everything listed needs OpenAI-only infrastructure: self-hosted runner groups +# (-runners, -windows-x64, -linux-x64-xl), paid macOS runners, +# a BuildBuddy remote cache, code-signing / notarization secrets, an OpenAI API +# key for the issue bots, or publishing credentials (R2, PyPI, winget). +# +# This is a repository setting, not a code change, so it survives upstream +# merges but must be re-run if upstream adds new infra-bound workflows. It is +# reversible with `gh workflow enable `. The PR gate itself +# (blocking-ci.yml) is trimmed in the workflow file instead; see docs/fork-ci.md. +# +# Usage: scripts/fork-ci-disable.sh [owner/repo] (needs a logged-in `gh`) +set -eu +repo="${1:-JSBtechnologies/codex}" + +disable=( + postmerge-ci.yml # push to main -> rust-ci-full on self-hosted runners + v8-canary + rust-ci-full.yml # also has its own push trigger; 32 self-hosted runner references + v8-canary.yml # pull_request -> Bazel via BuildBuddy + rust-release.yml # upstream release: self-hosted runners, signing, R2, winget + rust-release-windows.yml # upstream Windows release: self-hosted + Azure signing + rust-release-provisioned-macos.yml # upstream macOS release: notarization secrets + rusty-v8-release.yml # upstream V8 prebuilt publishing (BuildBuddy) + python-sdk-release.yml # PyPI publishing + python-sdk-cli-release.yml # PyPI publishing + python-runtime-release.yml # upstream runtime publishing + issue-deduplicator.yml # needs CODEX_OPENAI_API_KEY + issue-labeler.yml # needs CODEX_OPENAI_API_KEY + issue-translator.yml # needs CODEX_OPENAI_API_KEY + close-stale-contributor-prs.yml # upstream contributor-PR policy + cla.yml # upstream CLA assistant +) + +for wf in "${disable[@]}"; do + if gh workflow disable "$wf" --repo "$repo" 2>/dev/null; then + echo "disabled $wf" + else + echo "skipped $wf (not found or already disabled)" + fi +done + +echo +echo "Still enabled (expected: blocking-ci and the reusable workflows it calls, plus fork-release):" +gh workflow list --repo "$repo" --json name,path,state --jq '.[] | select(.state == "active") | " " + .path' From b27cfdf6daa4308a3f9ef25051fc11184505f97f Mon Sep 17 00:00:00 2001 From: Jeffrie Budde <39542105+JSBtechnologies@users.noreply.github.com> Date: Wed, 21 Oct 2026 14:21:54 -0500 Subject: [PATCH 2/2] docs: prettier formatting for docs/fork-ci.md --- docs/fork-ci.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/fork-ci.md b/docs/fork-ci.md index cd7df63d72a3..e1d477734f92 100644 --- a/docs/fork-ci.md +++ b/docs/fork-ci.md @@ -12,13 +12,13 @@ the fork turns off, so a red check here is a real finding. `blocking-ci.yml` is the PR gate. In the fork it calls: -| reusable workflow | what it checks | -|---|---| -| `blob-size-policy.yml` | no oversized blobs committed | -| `cargo-deny.yml` | licenses and advisories | -| `codespell.yml` | spelling | -| `repo-checks.yml` | Cargo manifests inherit workspace settings, TUI/core boundary, Bazel clippy lints | -| `rust-ci.yml` | format, clippy, tests for changed crates, `cargo shear`, the argument-comment lint for packages | +| reusable workflow | what it checks | +| ---------------------- | ----------------------------------------------------------------------------------------------- | +| `blob-size-policy.yml` | no oversized blobs committed | +| `cargo-deny.yml` | licenses and advisories | +| `codespell.yml` | spelling | +| `repo-checks.yml` | Cargo manifests inherit workspace settings, TUI/core boundary, Bazel clippy lints | +| `rust-ci.yml` | format, clippy, tests for changed crates, `cargo shear`, the argument-comment lint for packages | Removed from the gate in the fork, in the workflow file with a comment: the `bazel` and `sdk` calls. Inside `rust-ci.yml`, the "Argument comment lint -