REG-1909 Contract Preview 2b - #3620
Conversation
✅ Docs preview has no changesThe preview was not built because there were no changes. Build ID: bac257d328a73239f436545a ✅ AI Style Review — No Changes DetectedNo MDX files were changed in this pull request. Review Log: View detailed log
|
a0c34bf to
957c3e9
Compare
ff37b2e to
918952a
Compare
3e24da0 to
c9be9f4
Compare
798e645 to
17bf380
Compare
|
Code review Two findings, both against the retry/timeout composition guidance in CLAUDE.md. No correctness bugs found — GraphQL variables, union/enum mapping, and poll polarity all check out against the checked-in schema. 1. rover/crates/rover-client/src/operations/contract/preview/mod.rs Lines 130 to 147 in 6702205
CLAUDE.md is explicit about this shape:
Suggested fix: add a For fairness: the pre-existing 2. The new operation services expose no default timeout/retry configuration rover/crates/rover-client/src/operations/contract/preview/service.rs Lines 18 to 29 in 6702205 None of the three new wrappers — CLAUDE.md states this without hedging:
This matters more than usual here because the three operations have genuinely different latency profiles: the Flagging transparently: no existing operation |
6702205 to
cb48419
Compare
cb48419 to
38f953d
Compare
Adds the `operations::contract::preview` module: the contractPreviewAsync/contractPreviewStatus/contractPreviewResult GraphQL operations wrapped as Tower Services (per AGENTS.md's rover-client Service pattern), plus `start`/`result`/`poll`/`run` orchestration functions built on the shared `preview_poll` helper from the foundation PR. No CLI command calls this yet -- `rover contract preview" wiring lands in the next PR in this stack.
ContractPreviewStatus's Response changes from Option<PollState> to bool (preview builds never had a target_url to accumulate, so the richer PollState wrapper added nothing). poll() now builds ServiceBuilder::new().retry(PollRetryPolicy::new(...)).service(status) instead of calling the removed poll_preview_build, and maps the one-shot result fetch's error to PreviewResultUnavailable inline instead of via a separate remapping helper.
Mirrors WHOAMI_ATTEMPT_TIMEOUT: an inner per-attempt timeout layered under PollRetryPolicy's overall poll budget, so one hung status check can't consume checks_timeout_seconds in a single attempt. A timed-out attempt maps to `false` (not finished) rather than an error, so PollRetryPolicy just polls again on the normal schedule.
Follows the foundation change removing AttemptTimeoutLayer: per-call resilience is deferred to each operation's own retry/timeout composition rather than a bespoke layer bolted onto the poll retry policy.
Follows the rover-tower change replacing impl PollOutcome for bool with a dedicated enum.
… with a Tower mock Mirrors the same fix applied to the sibling subgraph-preview implementation: - Module shape: fold types.rs and the GraphQLQuery derives into mod.rs, leaving service.rs with only the tower::Service wrappers, per CLAUDE.md's target shape for new rover-client operations. - The four result_* tests exercising ContractPreviewResult's pure field mapping now use a Tower mock (rover_tower::mock_service!) instead of spinning up a real MockServer, since they were never testing wire-level HTTP behavior.
Mirrors the equivalent change on subgraph::preview per PR review feedback: instead of building the service internally from &StudioClient, start()/result() now take an already-composed Service, with default-service constructors (contract_preview_start_service / contract_preview_result_service) for the common case. This lets tests inject a rover_tower::mock_service! mock directly instead of spinning up an HTTP mock server. run()/poll() keep their existing &StudioClient-based signatures and build the default services internally.
The service.rs Tower-mock tests and mod.rs tests were checking only 2-3 of PreviewJobResponse's 6 fields via individual assert_eq! calls, and run_fails_fast_when_the_started_build_is_not_pollable only checked the RoverClientError::AdhocError variant, not its message -- all would pass even if an unrelated field silently regressed. Switched to full-struct equality and a full-value destructure for the error case, per CLAUDE.md's testing conventions.
340d5df to
2671aab
Compare
REG-1909 Contract Preview 2b
Crate-implementation PR (stacked on REG-1909 Foundation 1) for
rover contract preview.Adds
operations::contract::preview: thecontractPreviewAsync/contractPreviewStatus/contractPreviewResultGraphQL operations, each wrapped as atower::Serviceper AGENTS.md's rover-client Service pattern (seecontract/preview/service.rs), plusstart/result/poll/runorchestration functions built on the sharedpreview_pollhelper added in the foundation PR.No CLI command calls this yet —
rover contract previewwiring lands in the next PR in this stack (REG-1909 Contract Preview 3b).[x] A CHANGELOG.md entry is not needed for this PR