Skip to content

ci(ios): prepare the runner before the fixture E2E so open does not pay its start - #3251

Merged
thymikee merged 4 commits into
mainfrom
ci/ios-e2e-prepare-runner
Oct 6, 2026
Merged

thymikee merged 4 commits into
mainfrom
ci/ios-e2e-prepare-runner

Conversation

@thymikee

@thymikee thymikee commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Summary

The fixture-backed iOS E2E smoke started with a cold runner. The gesture step ended with pnpm clean:daemon, which stops the daemon and kills its runner by lease. So the first runner-backed command in the E2E paid the full runner start inside its own 90 s request timeout.

This failed PR #3243's iOS smoke (job 112216909377). The restarted runner did not connect within 45 s, recovery rebuilt it (49 s), and the deep-link open needed the runner for its alert read, so the daemon timed it out at 90 s.

Changes:

  • Remove the clean:daemon calls that discard the prepared runner: after the gesture step in ios.yml, and around the drag step in replays-manual.yml. They are left over from before perf(ios): reuse prepared runner in Settings smoke #2949/perf(ci): reuse iOS runner and narrow native cache key #2952 made later steps reuse the prepared runner. The built-CLI E2E still gets its own daemon, because its code signature differs from the source daemon. A graceful replacement detaches the runner, and the new daemon adopts it.
  • The E2E harness runs prepare ios-runner as its first step, under the 420 s prepare budget. It runs inside node-test-tmpdir.ts, so the daemon keeps the run's TMPDIR and claims directory. If adoption is refused, the runner starts again in this step, not inside the first open. The harness stops its daemon at the end, before the wrapper deletes those directories.

2 workflow files and the E2E harness.

Validation

At 1edd8b4: pnpm check:affected --run and pnpm typecheck pass. At 8bc651c (prepare as a workflow step), iOS smoke passed and prepare adopted the preflight runner: 2.0 s, no build, runner uptime about 29 min. The iOS workflow on the new head rechecks it from inside the harness.

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.10 MB 5.10 MB 0 B
Package (unpacked) 5.10 MB 5.10 MB 0 B
Package (download) 1.53 MB 1.53 MB +7 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 29.5 ms 28.0 ms -1.5 ms
CLI --help 88.7 ms 84.7 ms -4.0 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/ios.yml Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .github/workflows/ios.yml Outdated
@thymikee

thymikee commented Oct 6, 2026

Copy link
Copy Markdown
Member Author

This PR is ready. I reviewed 1edd8b4 and found nothing that needs to change before merge.

All 19 checks pass. The iOS Smoke Tests job ran the changed harness path: the E2E passed with 15 tests, and the uploaded step-history.json shows prepare at 3.4 s and daemon stop at 218 ms. The CI log does not print the takeover notice or adoption diagnostics, so I infer adoption from the 3.4 s prepare time. replays-manual.yml is workflow_dispatch only and did not run on this head, so I checked the removed drag-step clean:daemon calls by reading the code, not by a live run. I did not rerun tests or live devices locally.

Not blocking, and you can take or leave these: in live-runner.ts the line Number(process.env.AGENT_DEVICE_IOS_PREPARE_TIMEOUT_MS ?? 420000) gives NaN or 0 when the variable is set but empty or malformed, so --timeout NaN would reach prepare (only a CI misconfiguration can cause this, and a finite and positive check would cover it); stopDaemon always runs daemon stop against context.stateDir, which is the developer's default daemon when AGENT_DEVICE_STATE_DIR is unset in a local run, so it could stop a daemon the harness did not start (stop it only when the harness owns the state dir, or note the behavior in the doc comment); and no unit test covers the finalize ordering for a stopDaemon failure combined with a cleanup failure, or for stopDaemon running after session cleanup (extending the finalizeSessionCleanup-style injection would cover it).

No conflicts are known, and nothing else needs to happen before merge.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 6, 2026
@thymikee
thymikee merged commit 32b756a into main Oct 6, 2026
19 checks passed
@thymikee
thymikee deleted the ci/ios-e2e-prepare-runner branch October 6, 2026 12:49
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-06 12:50 UTC

thymikee added a commit to AdzeB/agent-device that referenced this pull request Oct 6, 2026
* origin/main: (36 commits)
  fix(android): rebind the test IME when its commit went to a stale input session (callstack#3061)
  feat: release public workspace packages through npm publish (callstack#3252)
  fix(snapshot): stop a SwiftUI toolbar host from covering the sheet it encloses (callstack#3162)
  ci(ios): prepare the runner before the fixture E2E so open does not pay its start (callstack#3251)
  fix(apple-runner): fence prep spawns behind a start-owned admission (callstack#3239)
  0.21.22
  test(apple): own the simctl settings plan tests in simctl-settings.test.ts (callstack#3244)
  fix(limrun): report the session device id in iOS settings refusals (callstack#3243)
  0.21.21
  feat(remote): add a host-allocated macos-app lease backend (callstack#3236)
  test(android): bound the screenshot write wait by wall time, not event-loop turns (callstack#3250)
  feat(recording): cap the touch overlay frame rate at the caller's --fps (callstack#3241)
  fix(ad-script): let .ad scripts carry scroll --until and wait capture flags (callstack#3197) (callstack#3234)
  feat(provider-webdriver): keyboard enter, dismiss, and status over WebDriver (callstack#3233)
  feat(selectors): match role= against snapshot kind with a node-scoped alias window (callstack#3232)
  fix(provider-webdriver): read field values, placeholders, secure fields, and checked state from page source (callstack#3231)
  feat(replay): accept --test-ime on test and replay so flow-owned Android opens opt into the test IME (callstack#3235)
  refactor(daemon): route daemon-level diagnostics through one scope helper (callstack#3242)
  docs(adr): correct ADR 0031 pointer event delivery evidence (callstack#3245)
  fix(ios): stop a tap's post-gesture lookup from recording an XCTest failure (callstack#3060) (callstack#3237)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant