Skip to content

feat(quarantine): persist quarantine resolution mode in meta.json - #1148

Merged
trunk-io[bot] merged 1 commit into
mainfrom
max/quarantine-resolution-mode-in-meta
Jul 28, 2026
Merged

feat(quarantine): persist quarantine resolution mode in meta.json#1148
trunk-io[bot] merged 1 commit into
mainfrom
max/quarantine-resolution-mode-in-meta

Conversation

@max-trunk

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

Copy link
Copy Markdown
Contributor

Why

#1147 taught the CLI to parse quarantineResolutionMode off the /metrics/getQuarantineConfig response — whether the server resolved quarantine status from the repo or the test collection. That value currently reaches only a tracing::info! line and UploadMetrics telemetry, so it can't be tied back to a specific upload.

Writing it into meta.json lets the services side persist it per upload.

The config fetch completes before upload_bundle serializes meta.json into the tarball, so the value can ride along in the bundle rather than on the createBundleUpload request.

What

  • Moves QuarantineResolutionMode from api into bundle (new bundle/src/quarantine_resolution_mode.rs). BundleMetaBaseProps can't hold an api type — api depends on bundle, so that's a cycle — and consumers of the meta schema depend on bundle/context/proto without api. api::message re-exports it, so existing call sites are untouched; the From<_> for proto::… impl moves with the enum, since leaving it behind violates the orphan rule.
  • Adds #[serde(default)] quarantine_resolution_mode to BundleMetaBaseProps.
  • run_upload resolves the mode before upload_bundle and converts to the proto enum only at the telemetry site, so UploadMetrics stays byte-identical.
  • RSpec path: quarantine_resolution_mode_for_telemetry returns the bundle-level enum and drops its now-inaccurate suffix, since it feeds meta.json too.

Why no new BundleMetaV0_7_9

#[serde(default)] on the shared base props is load-bearing: parse_meta tries V0_7_8 and falls back through six older structs that all flatten these same props, so a non-defaulted field fails every arm for bundles from older CLIs. Precedent is one line up — test_collection is a #[serde(flatten, default)] addition to the same struct. A new variant would cost a VersionedBundle arm plus a downgrade impl per version and buy nothing: cli_version already distinguishes a pre-field CLI from a genuine Unspecified. There's no deny_unknown_fields anywhere, so older readers ignore the new key.

Testing

  • cli/tests/upload.rs asserts a test_collection response reaches the extracted meta.json and that telemetry still carries the same value.
  • Both bindings' fixtures round-trip the new field, verified by building the real artifacts (wasm-pack build, maturin develop):
    • context-js compares a parsed bundle against its input fixture. Without the fixture field, 6 tests fail — a runtime deep-equality diff, not a type error, since tsify renders the field optional because of #[serde(default)]. 28/28 pass.
    • context-py's roundtrip test compares dumped JSON against an expected dict, so the defaulted key goes on the expected side (mirroring test_collection_id). 35/35 pass.
  • Unrelated pre-existing flake: test_report/tests/publish.rs fails exactly one of publish_environment_variable_overrides / publish_variant_priority_constructor_over_env per run, and which one varies between runs — reproduced on unmodified main.

🤖 Generated with Claude Code

@trunk-io

trunk-io Bot commented Jul 27, 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.

@codecov-commenter

codecov-commenter commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.21%. Comparing base (846c623) to head (2739e5f).

Files with missing lines Patch % Lines
bundle/src/quarantine_resolution_mode.rs 80.64% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1148      +/-   ##
==========================================
+ Coverage   82.93%   83.21%   +0.27%     
==========================================
  Files          71       71              
  Lines       16040    16044       +4     
==========================================
+ Hits        13303    13351      +48     
+ Misses       2737     2693      -44     

☔ 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 27, 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

@trunk-io

trunk-io Bot commented Jul 27, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@max-trunk
max-trunk force-pushed the max/quarantine-resolution-mode-in-meta branch from 5b5339d to c060630 Compare July 28, 2026 15:08
Comment thread api/src/message.rs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this file's diff is just moving code to the bundle crate to avoid circular import

@max-trunk
max-trunk force-pushed the max/quarantine-resolution-mode-in-meta branch from c060630 to 3f83df3 Compare July 28, 2026 15:19
@max-trunk
max-trunk marked this pull request as ready for review July 28, 2026 15:36
Comment on lines +47 to +65
impl QuarantineResolutionMode {
pub fn resolution_log_line(
&self,
test_collection_id: Option<&str>,
repo: &RepoUrlParts,
) -> Option<String> {
match self {
Self::TestCollection => Some(format!(
"Resolved quarantine status for test collection {}",
test_collection_id.unwrap_or("unknown"),
)),
Self::Repo => Some(format!(
"Resolved quarantine status for repo {}",
repo.repo_full_name()
)),
Self::Unspecified => None,
}
}
}

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.

I know this is just ported but optional note on copy:
Quarantine status applied from test collection {}

Quarantine status applied from repo {}

Resolved imo doesn't make much sense to the user since that's a bit internal to us

}
}

impl QuarantineResolutionMode {

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.

I love rust sometimes

The CLI already parses `quarantineResolutionMode` off the
/metrics/getQuarantineConfig response (#1147), but only logs it and sends it as
UploadMetrics telemetry — which cannot be tied back to a specific upload. Write
it into meta.json so the services side can persist it per upload.

Moves `QuarantineResolutionMode` from `api` into `bundle`: `BundleMetaBaseProps`
cannot hold a type from `api` (which depends on `bundle`) without a dependency
cycle, and consumers of the meta schema depend on `bundle`, `context`, and
`proto` without `api`. `api::message` re-exports it, so existing call sites are
untouched. The `From<_> for proto::…` impl moves with the enum — left behind it
would violate the orphan rule.

The field is `#[serde(default)]` on the shared base props rather than a new
schema version: `parse_meta` tries V0_7_8 and falls back through six older
structs that all flatten those same base props, so a non-defaulted field would
fail every arm for bundles from older CLIs. There is no `deny_unknown_fields`
anywhere, so an older reader ignores the new key.

`run_upload` now resolves the mode before `upload_bundle` (which serializes
meta.json into the tarball) and converts to the proto enum only at the telemetry
site, so UploadMetrics stays byte-identical.

The bindings' meta fixtures gain the new field: context-js round-trips a parsed
bundle against its input fixture, and context-py's roundtrip test compares dumped
JSON against an expected dict, so both see the newly serialized key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@max-trunk
max-trunk force-pushed the max/quarantine-resolution-mode-in-meta branch from 3f83df3 to 2739e5f Compare July 28, 2026 16:55
@trunk-io
trunk-io Bot merged commit c6d15a9 into main Jul 28, 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.

3 participants