Repository navigation
ci(tui): run only python_agent_e2e for agent-only changes; keep the rust-cache key across image updates - #48
Merged
Conversation
A change that touches only `packages/pi-agent-cli/pi_agent_cli/**` or `packages/pi-agent-cli/tests/_tool_agent.py` started the whole TUI CI, because the end-to-end tests of the pager (`python_agent_e2e`) talk to the Python agent. The TUI CI builds and runs ten suites and takes 18 to 35 minutes. A change of the Python agent can change only that one test target. The runs of PR #46 (`--setup`, Python only) took 25 to 35 minutes, and the first two failed on a Rust test that the PR did not touch (#47). Change. - New workflow `tui-e2e.yml` (job `python_agent_e2e`): the two paths above and its own file start it. It runs `cargo nextest run --locked --no-fail-fast -p pi-pager --test python_agent_e2e`: the command that `scripts/tui_baseline.py` builds for that target of the `pi-pager` suite, with the terminal variables of `[test.env]`. The Python agent is installed as in `tui-ci.yml`, and `PI_E2E_REQUIRED=1` stays, so a missing Python is a failure. - `tui-ci.yml` no longer lists the two paths. It starts for `tui/**`, the baseline script, the manifest and its own file, and it still runs these tests. A change of both runs both workflows. - Cache: the new job restores the cache of the `test` job (same key) and never saves. A cache with the same key but fewer artifacts would stop the `test` job from saving the whole one, because a key is saved once. - Six tests in `scripts/tests/test_tui_baseline.py` keep the two workflows in line: the paths, the command, the environment, the install lines (agent, nextest) and the cache key. - AGENTS.md (root and `pi-agent-cli`), `docs/baselines/tui.md`, the comment in `scripts/tui_baseline.toml` and CHANGELOG [Unreleased] say it. Checked: - actionlint 1.7.12: no finding for the two workflows (none for the old `tui-ci.yml` either). - `scripts/tests/test_tui_baseline.py`: 56 passed, 3 skipped on Windows; 59 passed on Linux (WSL). `scripts/tests`: 230 passed, 11 skipped on Windows. Ruff check and format check pass. - 13 changes of the two workflow files (the agent path back in `tui-ci.yml`, a renamed path, a file that does not watch itself, a flag removed, another target, another TERM, `PI_HOME` set, `PI_E2E_REQUIRED=0`, another nextest version, another pip line, a cache that saves, another key, a changed event header): each one fails the test that is meant to catch it. - Not checked here: a run on GitHub. The CI of this PR runs both workflows (it changes both files). The first PR that changes only `pi_agent_cli/**` shows that the TUI CI stays away.
rust-cache puts the version of every Rust toolchain on the runner into its cache key. The image has its own `stable`, and an image update changes it (1.99.0 to 1.99.1 on 2026-10-25). The key changed, no cache matched, and the `test` job built everything again (35 minutes, 31 of them for the build). Add the step "Keep only the pinned Rust toolchain" after the toolchain install in every job of tui-ci.yml and in tui-e2e.yml. It makes the toolchain of tui/rust-toolchain.toml the default and uninstalls the others, so the key does not depend on the image. `add-rust-environment-hash-key: false` is not a fix: it also removes the hash of Cargo.lock, so the key never changes and the cache is never saved again. Tests (scripts/tests/test_tui_baseline.py) keep the step equal in every job and before the cache step, and keep the variables that the key hashes equal in both workflows (the end-to-end job restores the key of the `test` job). Docs: CHANGELOG.md, docs/baselines/tui.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two changes, one commit each:
2727c68).8125744, see "The cache key" below).# .github/workflows/tui-ci.yml: on.push.paths and on.pull_request.paths - "tui/**" - "scripts/tui_baseline.py" - "scripts/tui_baseline.toml" - ".github/workflows/tui-ci.yml" - - "packages/pi-agent-cli/pi_agent_cli/**" - - "packages/pi-agent-cli/tests/_tool_agent.py"Evidence
Before: a PR that changed only
pi_agent_cli/**ran the wholecargo nextestjob: feat(cli): add --setup and offer it to ACP clients as a terminal login #46 took 25m38s, 32m1s (those two red, on a Rust test that feat(cli): add --setup and offer it to ACP clients as a terminal login #46 does not touch; fixed in fix(tui): read every age of the queue janitor before it deletes a file #47) and 35m17s.After: the new job
python_agent_e2eof this PR took 12m25s, with no cache found (the new image, see below): the build 11m16s, then14 tests run: 14 passed, 0 skippedin 10.9 s (soPI_E2E_REQUIRED=1and the Python agent worked). This PR changes both workflow files, so both workflows run on it.Probe: #49 (a draft on top of this branch, closed after the check) changed one comment line in
pi_agent_cli/__init__.pyand nothing else. It startedCIandTUI E2E. It did not startTUI CI: its five checks were Ruff, pytest (three Python versions) andpython_agent_e2e.All checks pass on both commits, with no cache each time (the key is new on the first commit, and on the second).
2727c68:Gates + cargo check3m54s,cargo nextest35m30s,python_agent_e2e12m25s.8125744:Gates + cargo check5m39s,cargo nextest24m10s,python_agent_e2e7m35s. Ruff and pytest (three Python versions) pass on both. The release job runs only on a manual start (workflow_dispatch), so it is skipped. The same cold job took 35m30s and 24m10s: the runners are not equal.actionlint1.7.12: no finding in the two workflows (none in the oldtui-ci.ymleither).Ten new tests in
scripts/tests/test_tui_baseline.pykeep the two workflows in line. Six are for the end-to-end workflow (the paths, the command thatsuite_commandbuilds, the[test.env]variables, the install lines, the cache key). Four are for the toolchain step (the jobs are read, the step is the same in every job and comes before the cache step, and both workflows set the same variables that the cache key hashes). Windows: 60 passed, 3 skipped (this file). Linux: the four new tests passed in thepytestjobs of CI (3052 passed, 39 skipped on Python 3.12). Ruff check and format check pass.shellcheckfinds nothing in the step, and a run of the step with stub tools (Git Bash) did what it should, also when an uninstall fails.13 changes of the workflow files, each one fails the test that is meant to catch it:
8 more changes for the toolchain step, each one fails the test that is meant to catch it: the step renamed, the step after
rust-cache,rustup defaultchanged in one job, noworking-directoryin one job, no uninstall in one job,RUST_BACKTRACEchanged in one workflow,RUSTFLAGSset in one workflow, and thejobs:header changed (a helper must not pass by finding nothing).The branch rules of
main(ruleset) have no required status check, so a PR without the TUI CI check is not blocked.The cache key
The cache of the
testjob missed whenever GitHub changed the Rust toolchain that is pre-installed on the image.rust-cacheputs the versions of all Rust toolchains on the runner into the key:Only
mainsaves the cache (save-if), so a miss stays until a run onmainsaves the new key.The fix is one step,
Keep only the pinned Rust toolchain, in every job that installs the pinned toolchain (the three jobs oftui-ci.ymland the job oftui-e2e.yml). It runs beforerust-cache:rustc --print sysrootruns intui/, so it gives the toolchain thattui/rust-toolchain.tomlselects. After the step, the hash holds one rustc version, and an image update does not change the key. The job does not fail when an uninstall fails (a warning only): the build does not need the uninstall.Do not use
add-rust-environment-hash-key: falsefor this. Inrust-cachev2 (src/config.ts,src/restore.ts,src/save.ts) it also removes the hash ofCargo.lockfrom the key. The key would never change, every run would find an exact hit and skip the save (Cache up-to-date.), and the cache would go stale.The first run on
mainafter the merge builds everything once and saves the cache. The end-to-end job restores that cache from then on.Check of the step in CI (run 40653787608, image 20261025.353.1). The logs of the jobs
Gates + cargo checkandpython_agent_e2eshow:The environment hash (
52c92e90) is the same in both jobs. It depends on the pinned rustc version and on five variables that the workflow sets, and on nothing from the image. Both jobs found no cache, because the key is new.python_agent_e2epassed (14 tests run, 14 passed). Its two runs with no cache took 12m25s (build 11m16s) and 7m35s (build 6m38s): the runners differ, so a cold time is a range, not one number.The full run passed too:
cargo nextesttook 24m10s with no cache (ten suites, 8,491 tests run and passed, 22 skipped). Its key is the same as the key of the e2e job:v0-rust-tui-linux-x86_64-test-Linux-x64-52c92e90-5a0e89f6. So the first run onmainsaves one cache for both jobs.Merge Danger
Door: two-way. Revert the two commits and the old workflows are back.
Blast Radius: CI only. No product code and no test of the Rust workspace change. A PR that changes only
pi_agent_cli/**no longer runs the other nine suites and theGates + cargo checkjob of the TUI CI. None of them reads the Python agent. Any other change of the Python tree (pi_agent_core,pi_agent_harness, other packages) did not start the TUI CI before and does not now.The new step uninstalls the other Rust toolchains of the image on the runner of the job (a GitHub-hosted VM that is deleted after the job). No step of these two files uses another toolchain than the pinned one: there is no
cargo +...and norustup run.release-baselinestarts only by hand.