feat(cli): add --inspect-mode flag for remote xcresult processing#10145
feat(cli): add --inspect-mode flag for remote xcresult processing#10145
Conversation
…ocessing Allow users to choose between local and remote xcresult processing when running tuist test, matching the existing --mode flag on tuist inspect test. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…vice Move the remote xcresult upload logic from both InspectTestCommandService and TestService into a shared uploadResultBundleRemotely method on UploadResultBundleService, eliminating duplication. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ect test Both tuist test --mode and tuist inspect test --mode now use the same TUIST_INSPECT_TEST_MODE environment variable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use --inspect-mode instead of --mode to be more specific about what the flag controls and avoid potential future naming conflicts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ResultBundleRemotely to uploadResultBundle The old uploadResultBundle(testSummary:...) is now uploadTestSummary and uploadResultBundleRemotely is now simply uploadResultBundle, which better reflects what each method does. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In remote mode, the server handles parsing, so there's no need to parse the xcresult locally before uploading. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tive testing Adds TestResultStatuses, a minimal struct with just name/suite/module/status per test case, and a parseTestStatuses method that skips action log parsing, attachment extraction, failure details, and duration computation. Used in the testSchemes error path where only pass/fail status per module is needed for selective testing and quarantine checks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When uploading in remote mode, the CLI writes quarantined_tests.json into the xcresult directory before zipping and uploading. The xcode_processor reads this file after extraction and applies is_quarantined marking to the parsed test cases, ensuring remote processing uses the same quarantine list the CLI had at test time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the --inspect-mode flag to tuist xcodebuild test and tuist xcodebuild test-without-building, with the same local/remote behavior as tuist test. Moves ExpressibleByArgument conformance for TestProcessingMode into TuistKit so all commands can use it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| method: test.method | ||
| ) | ||
| } | ||
| let filePath = resultBundlePath.appending(component: "quarantined_tests.json") |
There was a problem hiding this comment.
the xcode processor needs to know about which tests were quarantined when the client was running the tests. Instead of passing that through the API, decided to include that in the .xcresult, so the xcode processor has all information it needs in the .xcresult artifact itself.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… to TestQuarantineService Share the quarantine check logic between tuist test and tuist xcodebuild test by placing it in TestQuarantineService instead of a private method on TestService. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…est remote mode In remote mode testSummary is nil, so the quarantine suppression check was never triggered. Now falls back to parseTestStatuses for the quarantine decision, matching the tuist test behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e list Let other file read errors and JSON parse errors propagate instead of silently returning an empty list. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- TestResultStatuses: hasFailures, passingModuleNames, testCasesByModule - TestQuarantineService: onlyQuarantinedTestsFailed with TestResultStatuses - UploadResultBundleService: remote upload, quarantined_tests.json writing - XCResultProcessor: quarantine marking from embedded JSON Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gModuleNames a method Move TestProcessingMode enum out of TestService.swift into its own file to fix mid-file import and improve discoverability. Change passingModuleNames from a computed property to a method to signal non-trivial computation cost. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covered by XCResultServiceTests instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # xcode_processor/lib/xcode_processor/xcresult_processor.ex # xcode_processor/test/xcode_processor/xcresult_processor_test.exs
🛠️ Tuist Run Report 🛠️Previews 📦
Tests 🧪
Flaky Tests
|
| Test case | Module | Suite |
|---|---|---|
| parseTestStatuses_returnsCorrectStatuses() | TuistXCResultServiceTests | XCResultServiceTests |
| parseTestStatuses_extractsModuleAndSuiteNames() | TuistXCResultServiceTests | XCResultServiceTests |
Builds 🔨
| Scheme | Status | Duration | Commit |
|---|---|---|---|
| TuistAcceptanceTests | ✅ | 40.3s | 1d24507a9 |
| TuistApp | ✅ | 51.8s | 1d24507a9 |
| TuistCacheEEAcceptanceTests | ✅ | 2m 35s | 1d24507a9 |
| TuistCacheEEUnitTests | ✅ | 59.2s | 774c6390d |
| TuistUnitTests | ✅ | 1m 20s | 1d24507a9 |
Bundles 🧰
| Bundle | Commit | Install size | Download size |
|---|---|---|---|
| Tuist | 1d24507a9 | 28.4 MB |
19.5 MB Δ +10 B (+0.00%) |
| @Option(name: .long, help: "The zero-based shard index to execute.") | ||
| var shardIndex: Int? | ||
|
|
||
| @Option( |
There was a problem hiding this comment.
What about surfacing this somewhere in the docs. As a user, it's not obvious when I'd opt into server-side processing and what the implications of that decision are.
There was a problem hiding this comment.
What about surfacing this somewhere in the docs. As a user, it's not obvious when I'd opt into server-side processing and what the implications of that decision are.
Agree, this is coming along with switching the default as this will be a requirement for teams using self-hosting (unless they want to run the xcode processor node)
| "xcresult_quarantine_test_#{:erlang.unique_integer([:positive])}" | ||
| ) | ||
|
|
||
| File.mkdir_p!(temp_dir) |
There was a problem hiding this comment.
Maybe for a Credo rule, but we should lean on using ExUnit's tmp_dir tag so they take care of the lifecycle for us.
The test imports XCResultParser for TestResultStatuses but the module wasn't declared as a test dependency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ceTests The testSchemes error path now calls parseTestStatuses instead of parse, so tests need the mock stubbed to avoid crashes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # cli/Sources/TuistKit/Services/TestService.swift # cli/Sources/TuistTestCommand/TestRunCommand.swift
Reset xcResultService mocks and use .any matcher to ensure parseTestStatuses stub is matched regardless of path resolution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…0145) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Summary
--inspect-mode {local|remote}flag totuist test,tuist xcodebuild test, andtuist xcodebuild test-without-building(env:TUIST_INSPECT_TEST_MODE, shared withtuist inspect test --mode)quarantined_tests.jsoninto the xcresult directory before remote upload so the xcode_processor applies the same quarantine list the CLI had at test timeparseTestStatusesmethod that only extracts test name/module/status for quarantine and selective testing checks, skipping full xcresult parsingUploadResultBundleService.uploadResultBundle(renamed fromuploadResultBundleRemotely), old local upload renamed touploadTestSummaryonlyQuarantinedTestsFailed(testStatuses:quarantinedTests:)intoTestQuarantineServicefor reuse across commandsCLI changes
TestRunCommand,XcodeBuildTestCommand,XcodeBuildTestWithoutBuildingCommand: new--inspect-modeoptionTestService,XcodeBuildTestCommandService: mode-aware upload and quarantine handlingUploadResultBundleService: writes quarantine JSON into xcresult, handles remote uploadInspectTestCommandService: simplified to use shareduploadResultBundleTestResultStatuses: new lightweight struct for quarantine/selective testing checksxcode_processor changes
quarantined_tests.jsonfrom extracted xcresultis_quarantinedmarking to parsed test cases matching the quarantine listFeedback requested
Flag naming: The flag is currently
--inspect-mode(shared env varTUIST_INSPECT_TEST_MODEwithtuist inspect test --mode). However, ontuist testthe name "inspect" may be confusing since "inspect" is a separate command. Alternatives to consider:--processing-mode-- describes what it controls (where parsing happens)--upload-mode-- describes the upload behavior--inspect-mode-- consistent with thetuist inspect testcommandWould appreciate feedback on which name feels most intuitive for users.
Test plan
tuist test --inspect-mode localbehaves identically to current behaviortuist test --inspect-mode remoteuploads raw xcresult, server processes itTUIST_INSPECT_TEST_MODE=remote tuist testworks via env vartuist xcodebuild test --inspect-mode remoteworksquarantined_tests.jsonis written into xcresult and read by xcode_processor🤖 Generated with Claude Code