Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1b178be
chore(codex): upgrade openai-codex to 0.159.2
tiantt Sep 30, 2026
64a9782
fix(codex): keep replayed tool history in the order it happened
tiantt Sep 30, 2026
4fe91d4
test(runtime): add a runtime conformance suite
tiantt Sep 30, 2026
b127b4a
test(codex): add an opt-in real-model probe
tiantt Sep 30, 2026
482491a
feat(codex): add model routing for direct Responses and shim transports
tiantt Sep 30, 2026
dc4ec44
feat(codex): add a per-turn MCP bridge for ADK tools
tiantt Sep 30, 2026
247e9e0
test(codex): add a fake Codex for the direct provider + MCP bridge mode
tiantt Sep 30, 2026
8a3ba08
feat(codex): call Responses backends directly and serve ADK tools ove…
tiantt Sep 30, 2026
08b722b
feat(codex): persist Codex thread rollouts in a versioned thread store
tiantt Sep 30, 2026
031c3e6
feat(codex): add turn-control primitives for persistent threads
tiantt Sep 30, 2026
693e401
feat(codex): resume one Codex thread per session across invocations
tiantt Sep 30, 2026
b4164e4
feat(codex): bound, steer and compact Codex turns
tiantt Sep 30, 2026
97c8368
feat(codex): end-to-end session example; treat a closed turn as cance…
tiantt Sep 30, 2026
81a44ba
fix(codex): address review findings on the direct transport
tiantt Sep 30, 2026
f5333b6
test(codex): cover corrupt threads, bridge rejections, steer routing,…
tiantt Sep 30, 2026
94419f0
fix(codex): hand lost turns back to a resumed thread; one source of pins
tiantt Sep 30, 2026
99b9c42
fix(codex): keep header secrets off disk, retry resumes, meter the ru…
tiantt Sep 30, 2026
55354bc
feat(codex): version the thread store schema; test it on MySQL/Postgr…
tiantt Sep 30, 2026
221fed5
fix(codex): enforce tool admission and preserve resumed execution con…
tiantt Oct 1, 2026
2b1e1e0
fix(ci): restore runtime smoke test coverage
evanlowe Oct 9, 2026
89ead3f
docs(tests): explain local database Docker context
evanlowe Oct 9, 2026
495ba48
fix(tests): isolate turn smoke tests from plugin downloads
evanlowe Oct 9, 2026
f909377
fix(tests): isolate parallel Studio startup state
evanlowe Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 48 additions & 25 deletions .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ on:
- '**.py'
- 'pyproject.toml'
- 'requirements*.txt'
- 'uv.lock'
- '.github/workflows/unit-tests.yaml'
pull_request:
paths:
- '**.py'
- 'pyproject.toml'
- 'requirements*.txt'
- 'uv.lock'
- '.github/workflows/unit-tests.yaml'

jobs:
test:
Expand Down Expand Up @@ -67,28 +71,51 @@ jobs:
# model backend (no credentials, no network egress). Kept out of the matrix
# job above because it is serial and process-spawning.
#
# The job tolerates the test FAILING but not the test being ABSENT, and those
# are two separate steps below:
#
# * `continue-on-error` sits on the pytest step only. Whether the OS sandbox
# (landlock+seccomp on a GitHub runner) establishes at all is precisely the
# unknown this test exists to discover, and the CLI is pinned to an alpha
# (openai-codex-cli-bin==0.137.0a4), so a red assertion is signal to read,
# not a broken build. Drop that flag once the Linux sandbox verdict is in
# and the test has been green for a few runs -- at which point this job
# becomes an ordinary required check.
# * The step after it has NO such flag: a skipped or uncollected smoke test
# means the job proved nothing (lost binary, SDK install failure, platform
# check tripping), and an exit-0 green tick for that would defeat the whole
# point of running it. That must stay a hard failure even before the flag
# above comes off.
# Every selected case must run and pass, including database-backed resume.
codex-smoke:
runs-on: ubuntu-latest
timeout-minutes: 15

services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: veadk_test
MYSQL_DATABASE: veadk_test
MYSQL_USER: veadk_test
MYSQL_PASSWORD: veadk_test
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=10
postgres:
image: postgres:16
env:
POSTGRES_USER: veadk_test
POSTGRES_PASSWORD: veadk_test
POSTGRES_DB: veadk_test
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U veadk_test -d veadk_test"
--health-interval=10s
--health-timeout=5s
--health-retries=10

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Allow sandbox user namespaces on the runner
# Ubuntu's AppArmor restriction removes capabilities inside unprivileged
# user namespaces, preventing bubblewrap from configuring its loopback.
# Relax that host restriction only on this disposable runner; the tests
# still use the real read-only OS sandbox with network access disabled.
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
Expand All @@ -105,23 +132,22 @@ jobs:
uv pip install -e .

- name: Run the Codex end-to-end smoke test
# Tolerates a failing assertion (the sandbox verdict this job exists to
# collect); does NOT tolerate the test not running -- see the next step.
continue-on-error: true
env:
CODEX_RUN_SMOKE: "1"
VEADK_TEST_MYSQL_URL: mysql+aiomysql://veadk_test:veadk_test@127.0.0.1:3306/veadk_test
VEADK_TEST_POSTGRES_URL: postgresql+asyncpg://veadk_test:veadk_test@127.0.0.1:5432/veadk_test
run: |
source .venv/bin/activate
# -p no:xdist: this test must not be distributed across workers.
# -rs: print skip reasons, so a silently skipped smoke test (missing
# SDK, missing binary, unsupported platform) is visible in the log.
# --junitxml: machine-readable outcome for the assertion step below;
# pytest's own exit code cannot distinguish "passed" from "skipped".
pytest -m codex_smoke -p no:xdist -rs --junitxml=codex-smoke.xml
pytest tests/runtime/codex -m codex_smoke -p no:xdist -rs --junitxml=codex-smoke.xml

- name: Assert the smoke test actually ran
# No continue-on-error: this is the guard that stops the job going green
# while proving nothing.
if: ${{ !cancelled() }}
# Pytest exits successfully for skipped tests, so check its report too.
run: |
python3 - <<'PY'
import sys
Expand Down Expand Up @@ -179,10 +205,7 @@ jobs:

failed = [d for d in (_detail(c, "failure") for c in cases) if d]
if failed:
# Deliberately not fatal: the pytest step above already reported it,
# and its `continue-on-error` is what keeps this job advisory while
# the Linux sandbox verdict is unknown. Both come off together.
print(
sys.exit(
f"codex smoke: {len(cases)} test(s) ran, {len(failed)} FAILED "
"-- this is the signal this job exists to collect; read the "
"pytest output above:\n" + "\n".join(failed)
Expand Down
Loading
Loading