Skip to content

feat(quarantine): send test collection id and record resolution mode - #1147

Merged
trunk-io[bot] merged 5 commits into
mainfrom
max/add-tc-id-to-get-quarantine-config
Jul 27, 2026
Merged

feat(quarantine): send test collection id and record resolution mode#1147
trunk-io[bot] merged 5 commits into
mainfrom
max/add-tc-id-to-get-quarantine-config

Conversation

@max-trunk

@max-trunk max-trunk commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What

Wires the CLI to the test-collection additions in the public API's POST /metrics/getQuarantineConfig endpoint (server side: trunk-io/trunk#33132), across both the traditional and rspec invocation paths:

  1. Sends --test-collection-id as testCollectionShortId on the request.
  2. Records the response's new quarantineResolutionMode (repo | test_collection) in telemetry and logs the resolved source.

The --no-repo flag / noRepo request param are intentionally out of scope for this PR.

Changes

  • api/src/message.rs
    • Add test_collection_short_id to GetQuarantineConfigRequest (testCollectionShortId, omitted when None).
    • Add a typed QuarantineResolutionMode enum (Repo | TestCollection | Unspecified) as the quarantine_resolution_mode field on GetQuarantineConfigResponse (#[serde(default)]). Its Deserialize is tolerant: any unknown, absent, or non-string value degrades to Unspecified rather than failing the whole response parse, so a future server value never breaks older clients. A single From<QuarantineResolutionMode> for the proto enum centralizes the mapping.
  • Request sourcing (both paths) — the id comes from the --test-collection-id flag / TRUNK_TEST_COLLECTION_ID env var, threaded into the request on the traditional path (cli/src/upload_command.rscli/src/context.rs) and read directly on the rspec path (test_report/src/report.rs). Empty values are filtered so an empty env var doesn't send "".
  • Telemetry — new proto QuarantineResolutionMode enum + UploadMetrics.quarantine_resolution_mode = 9 in proto/proto/upload_metrics.proto; carried through QuarantineContext (traditional) and a new RunUploadOptions.quarantine_resolution_mode_override (rspec).
  • Logging — on a successful lookup a human-readable info log names the resolved source (Resolved quarantine status for test collection <id> / ... for repo <name>), emitted at most once per report (not per test); disk-cache hits are tagged (cached).
  • rspec disk cache — the resolution mode is stored in the cache entry and restored on a cache hit (so telemetry is correct without a re-fetch), and the collection id is part of the cache key so runs with different ids in the same repo can't collide.

Compatibility

  • Response field is safe with older CLIsGetQuarantineConfigResponse has no deny_unknown_fields, so the extra key is ignored; the server PR can land first.
  • Unknown / non-string modes are safe — the tolerant deserializer degrades anything unrecognized to Unspecified.
  • Telemetry field is safe with an un-updated server — telemetry is protobuf-encoded, and a new field tag (= 9) is skipped by servers that don't know it.

Testing

  • cargo check and the full test suite pass across api, trunk-analytics-cli, and test_report.
  • cli/tests/upload.rs asserts that --test-collection-id reaches the getQuarantineConfig request (guards the traditional-path wiring).

Follow-up

  • Confirm the rspec Ruby gem forwards --test-collection-id / sets TRUNK_TEST_COLLECTION_ID (no Rust-side change needed).

🤖 Generated with Claude Code

Pipe the existing --test-collection-id value into the getQuarantineConfig
request (testCollectionShortId) and record the response's new
quarantineResolutionMode field in telemetry, across both the traditional
and rspec invocation paths.

- api: add test_collection_short_id to GetQuarantineConfigRequest and
  quarantine_resolution_mode (Option, serde default) to the response so
  older servers that omit it still deserialize.
- populate test_collection_short_id from meta (traditional) and from
  TRUNK_TEST_COLLECTION_ID (rspec).
- proto: add QuarantineResolutionMode enum and UploadMetrics field 9;
  carry the mode through QuarantineContext and a RunUploadOptions override.
- emit a Sentry-only tracing event (hidden_in_console) with the resolved
  mode in both paths for debugging.

Server side: trunk-io/trunk#33132

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Jul 24, 2026

Copy link
Copy Markdown

😎 Merged directly without going through the merge queue, as the queue was empty and the PR was up to date with the target branch - details.

Comment thread api/src/message.rs Outdated
Comment thread cli/src/context_quarantine.rs Outdated
anyhow::Result::Ok(response) => (Some(response), QuarantineFetchStatus::FetchSucceeded),
anyhow::Result::Ok(response) => {
// Surface which source the server resolved quarantine status from. Sent to Sentry
// only (hidden from the console) to aid debugging without adding CLI noise.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Imo would be preferable to include a visible log for it if test collection id is set

Comment thread test_report/src/report.rs Outdated
quarantined_tests.insert(quarantined_test_id.clone(), true);
}
// Surface which source the server resolved quarantine status from. Sent to Sentry
// only (hidden from the console) to aid debugging without adding CLI noise.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Likewise

@codecov-commenter

codecov-commenter commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.46154% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.17%. Comparing base (6bed25e) to head (509680e).

Files with missing lines Patch % Lines
api/src/message.rs 66.66% 10 Missing ⚠️
test_report/src/report.rs 95.31% 3 Missing ⚠️
cli/src/context_quarantine.rs 89.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1147      +/-   ##
==========================================
+ Coverage   82.90%   83.17%   +0.27%     
==========================================
  Files          70       71       +1     
  Lines       15919    16040     +121     
==========================================
+ Hits        13197    13342     +145     
+ Misses       2722     2698      -24     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@trunk-staging-io

trunk-staging-io Bot commented Jul 24, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

Failed Test Failure Summary Logs
pending_quarantine_test should be quarantined when run with variant A test marked as pending was expected to fail but unexpectedly passed. Logs ↗︎
variant_quarantine_test should be quarantined when run with variant A test expected the sum of 2 + 2 to be 5, but it was actually 4, indicating a failing assertion. Logs ↗︎

View Full Report ↗︎Docs

Introduce a typed api::message::QuarantineResolutionMode enum with a tolerant
deserializer (unknown or absent values -> Unspecified) so a new server-side
mode never breaks deserialization on older clients. It replaces the
Option<String> previously threaded through the response, QuarantineContext,
TestReport, and the quarantine disk cache, and collapses the two duplicated
string-match sites into a single From impl.

Also:
- Cache the resolution mode in the disk-cache entry and restore it on a cache
  hit, so telemetry reports the true mode without a re-fetch.
- Rework resolution-mode logging into human-readable messages, emitted at most
  once per report.
- Drop the redundant standalone TestReport field (telemetry now reads from
  quarantine_config).
- Populate quarantine_resolution_mode in the QuarantineContext test
  constructors the vendored-openssl build never compiled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@max-trunk
max-trunk marked this pull request as ready for review July 24, 2026 20:42
@trunk-io

trunk-io Bot commented Jul 24, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

max-trunk and others added 3 commits July 24, 2026 21:12
… parse, cache key

- BLOCKING: the traditional CLI path built getQuarantineConfig with
  test_collection_short_id always None. meta.base_props.test_collection isn't
  populated until upload_bundle (after the request is built), and only when the
  upload-intent response returns collection metadata, so the CLI value was
  silently dropped. Thread upload_args.test_collection_short_id (empty-filtered)
  into gather_exit_code_and_quarantined_tests_context and use it directly,
  matching the rspec path.
- Include the collection id in the rspec disk-cache key so two runs in the same
  repo with different TRUNK_TEST_COLLECTION_ID values can't share an entry (and
  the wrong quarantine list).
- Make QuarantineResolutionMode's deserializer tolerant of non-string JSON
  types (number/bool/object/null), not just unknown strings.
- Filter empty TRUNK_TEST_COLLECTION_ID so an empty env var doesn't send "".
- Collapse the duplicated resolution-mode log message into a
  QuarantineResolutionMode::resolution_log_line helper; mark cached lookups.
- Inline the trivial quarantine_resolution_mode() mapping fn at its one call
  site; use the imported enum name consistently.
- Tests: assert the collection id reaches the getQuarantineConfig request on
  the traditional path (cli/tests/upload.rs), plus a non-string deserialize case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ests

- Shorten the QuarantineResolutionMode doc comment; drop the deserializer and
  resolution_log_line comments in api/src/message.rs.
- Remove the api/src/message.rs serde unit tests (type-only, low value).
- Prune the per-variant and trailing comments on the proto
  QuarantineResolutionMode enum, keeping only the top-level line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@trunk-io
trunk-io Bot merged commit 846c623 into main Jul 27, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants