name: tests on: push: branches: [main] pull_request: permissions: contents: read jobs: tests: strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] python: ["3.10", "3.13"] runs-on: ${{ matrix.os }} defaults: run: # Git Bash on Windows: the launchers are `sh` scripts, run there as Claude Code runs them. shell: bash steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: ${{ matrix.python }} - run: python -m pip install pytest # On failure, the summary lines also go out as an annotation, which the check run shows # without signing in. - run: | set -o pipefail python -m pytest tests -rfEs --tb=line 2>&1 | tee pytest.log || { status=$? msg=$(grep -E '^(FAILED|ERROR) |\.py:[0-9]+: ' pytest.log | head -60 \ | sed 's/%/%25/g' | awk '{printf "%s%%0A", $0}') echo "::error title=pytest::${msg}" exit $status } env: COLUMNS: "200" codex: # The plugin installed and run by a real Codex CLI (tests/test_codex_cli.py): its install # copy finds the package through the `source` Codex writes, which Codex writes differently on # Windows, and a `codex exec` session runs its hooks. The model is a local stand-in, so the # job needs no key and makes no model call. strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} defaults: run: shell: bash steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: "3.13" - uses: actions/setup-node@v5 with: node-version: "22" # Pinned: a new Codex can change how it installs a plugin; move it on purpose. - run: npm install -g @openai/codex@0.164.0 - run: python -m pip install pytest # What Codex wrote for the marketplace goes out as a notice, and on failure the summary # lines and what Codex said about the hooks as annotations, all shown on the check run # without signing in. - run: | set -o pipefail status=0 python -m pytest tests/test_codex_cli.py -rfEsP --tb=short 2>&1 | tee pytest.log \ || status=$? grep -h " wrote: " pytest.log | sort -u | sed 's/^/::notice title=codex config.toml::/' \ || true if [ "$status" -ne 0 ]; then grep -h '^codex: ' pytest.log | sort -u | head -20 | sed 's/%/%25/g' \ | sed 's/^/::warning title=codex output::/' || true msg=$(grep -E '^(FAILED|ERROR) |\.py:[0-9]+: ' pytest.log | head -60 \ | sed 's/%/%25/g' | awk '{printf "%s%%0A", $0}') echo "::error title=pytest::${msg}" fi exit $status env: TE_CODEX_E2E: "1" COLUMNS: "200"