Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion docs/build-loop-in-30-minutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,20 @@ Run these smoke checks as the macOS user that owns the runner process:
```bash
gh auth status
codex --version
codex exec --skip-git-repo-check --sandbox read-only --ask-for-approval never --ephemeral "Reply with exactly: ok"
codex exec --skip-git-repo-check --sandbox read-only "Reply with exactly: ok"
claude auth status
claude -p "Reply with exactly: ok" --output-format json
```

For non-interactive runner or hosted-agent setup, load the Codex API key from a
secret store and pipe it into the CLI without printing it:

```bash
printf '%s\n' "$OPENAI_API_KEY" | codex login --with-api-key
codex login status
codex exec --skip-git-repo-check --sandbox read-only "Reply with exactly: ok"
```

In service mode, set `USER`, `LOGNAME`, `SHELL`, `LANG`, and a PATH that can
find `gh`, `git`, `codex`, `claude`, and `python3` in the runner `.env`, then
fully restart the listener.
Expand Down
11 changes: 10 additions & 1 deletion docs/self-hosted-mac-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,20 @@ Verify auth from a runner job or from the same service user environment:
```bash
gh auth status
codex login status
codex exec --skip-git-repo-check --sandbox read-only --ask-for-approval never --ephemeral "Reply with exactly: ok"
codex exec --skip-git-repo-check --sandbox read-only "Reply with exactly: ok"
claude auth status
claude -p "Reply with exactly: ok" --output-format json
```

For API-key runner auth, store `OPENAI_API_KEY` in the runner's secret manager
or private `.env`, then load it into the setup shell and run:

```bash
printf '%s\n' "$OPENAI_API_KEY" | codex login --with-api-key
codex login status
codex exec --skip-git-repo-check --sandbox read-only "Reply with exactly: ok"
```

`claude auth status` is not enough by itself. The prompt smoke is the useful
signal because login-keychain or inherited-env failures often appear only when
Claude makes a real non-interactive request.
Expand Down
3 changes: 0 additions & 3 deletions src/code_mower/doctor_checks/self_hosted_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,6 @@ def _check_codex_auth_probe(
"--skip-git-repo-check",
"--sandbox",
"read-only",
"--ask-for-approval",
"never",
"--ephemeral",
"--output-last-message",
str(output_path),
"Reply with exactly: ok",
Expand Down
31 changes: 31 additions & 0 deletions tests/test_doctor_self_hosted_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,37 @@ def fake_run(command: list[str], **_: object) -> subprocess.CompletedProcess[str
self.assertEqual(codex_check.status, "fail")
self.assertIn("codex auth prompt probe", codex_check.message)

def test_runner_cli_auth_codex_probe_omits_stale_smoke_flags(self) -> None:
config = _runner_config()
codex_lane = config["lanes"]["codex"]
calls: list[list[str]] = []

with tempfile.TemporaryDirectory() as tmp:
bin_dir = Path(tmp) / "bin"
bin_dir.mkdir()
codex = bin_dir / "codex"
codex.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
codex.chmod(0o755)

def fake_run(command: list[str], **_: object) -> subprocess.CompletedProcess[str]:
calls.append(command)
return subprocess.CompletedProcess(command, 0, "ok", "")

with mock.patch.dict(os.environ, {"PATH": str(bin_dir)}, clear=False):
checks = check_runner_cli_auth(
[("codex", codex_lane)],
run=fake_run,
http_timeout=5,
)

codex_check = next(check for check in checks if check.lane == "codex")
self.assertEqual(codex_check.status, "pass")
self.assertEqual(len(calls), 1)
self.assertNotIn("--ephemeral", calls[0])
self.assertNotIn("--ask-for-approval", calls[0])
self.assertNotIn("--ephemeral", codex_check.detail["args"])
self.assertNotIn("--ask-for-approval", codex_check.detail["args"])

def test_runner_workflow_labels_fail_when_custom_label_is_missing(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo_root = Path(tmp)
Expand Down
12 changes: 12 additions & 0 deletions tests/test_release_hygiene.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ def test_ci_workflow_tests_supported_python_minors(self) -> None:
self.assertIn(" - name: Unit tests\n", workflow)
self.assertIn(" - name: Compile sources\n", workflow)

def test_codex_smoke_docs_use_supported_flags(self) -> None:
doc_paths = (
ROOT / "docs/build-loop-in-30-minutes.md",
ROOT / "docs/self-hosted-mac-runner.md",
)

for path in doc_paths:
text = path.read_text(encoding="utf-8")
self.assertNotIn("--ephemeral", text, msg=str(path))
self.assertNotIn("--ask-for-approval", text, msg=str(path))
self.assertIn("codex login --with-api-key", text, msg=str(path))

def test_ruff_static_rule_stage_is_intentional(self) -> None:
pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))

Expand Down
Loading