🧪 Harden Swift beta tester readiness - #2627
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe changes update Swift app behavior, cross-platform UI tests, E2E runners and screenshot tooling, local API stubs, OAuth metadata routing, CI workflows, and platform release assets. ChangesSwift application behavior
E2E, API, and platform tooling
Platform assets and validation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Coverage Report for packages/units (./packages/units)
File CoverageNo changed files found. |
Coverage Report for packages/overpass (./packages/overpass)
File CoverageNo changed files found. |
Coverage Report for packages/utils (./packages/utils)
File CoverageNo changed files found. |
Coverage Report for packages/analytics (./packages/analytics)
File CoverageNo changed files found. |
Coverage Report for apps/expo (./apps/expo)
File CoverageNo changed files found. |
Coverage Report for packages/mcp (./packages/mcp)
File CoverageNo changed files found. |
Coverage Report for packages/api (./packages/api)
File Coverage |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/swift/scripts/capture-visual-screenshots.ts (1)
787-815: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winOnly auto-create after a successful device inventory.
A timeout, nonzero status, or JSON parse failure currently falls through to simulator creation. Transient inventory failures can therefore create duplicate persistent
PackRat E2E iPaddevices.Proposed fix
const result = spawnSync('xcrun', ['simctl', 'list', 'devices', 'available', '-j'], { encoding: 'utf8', timeout: 10_000, maxBuffer: 10 * 1024 * 1024, }); + let inventorySucceeded = false; if (result.status === 0) { try { const parsed = safeJsonParse<{ devices?: Record<string, Array<{ name?: string; udid?: string; isAvailable?: boolean }>>; }>(result.stdout, { strict: true }); + inventorySucceeded = true; const availableDevices = Object.values(parsed.devices ?? {}).flat(); // Existing selection logic... } catch {} } - if (createIfMissing) { + if (createIfMissing && inventorySucceeded) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/swift/scripts/capture-visual-screenshots.ts` around lines 787 - 815, Update the simulator-selection flow around the xcrun inventory result and safeJsonParse so createIOSSimulator is called only after a successful command and valid JSON inventory. Track inventory success separately from whether a preferred device was found, and gate the createIfMissing fallback on that success; keep returning matching device UDIDs unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/swift/scripts/capture-visual-screenshots.ts`:
- Around line 1683-1687: Update the non-empty-file branch in the contact-sheet
render loop to await exitPromise and require an exit code of 0 before returning,
rather than relying only on the bounded wait. If Chrome does not exit cleanly,
use stopProcessGroup with SIGKILL before returning so cleanup cannot race with
the live process.
In `@apps/swift/scripts/lib/args.ts`:
- Around line 18-20: Update positional-mode handling where positionalMode.plan
is applied so unit and ios-unit do not overwrite an explicitly provided --plan
when they have no plan value; preserve the existing plan unless the mode defines
one, or reject the conflicting combination. Add regression coverage for both
argument orders using the positional-mode parsing logic and POSITIONAL_MODES
entries.
In `@apps/swift/Tests/PackRatUITests/HomeTileTests.swift`:
- Around line 101-106: Update the macOS branch of the destination assertion
helper to poll for both app.staticTexts[title] and app.navigationBars[title]
during the timeout, returning immediately when either exists. Preserve the
existing timeout as the overall deadline and return false when neither element
appears, while leaving the non-macOS behavior unchanged.
In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift`:
- Around line 588-598: In captureHomeAction, extract the repeated destination
verification, capture, and optional dismissal sequence into a nested
verifyAndCapture closure near the start of the function. Replace each duplicated
block with calls to this closure, preserving the existing destinationIdentifier
check, assertion message, capture(name), and dismissAfterCapture behavior.
- Around line 1368-1375: Cache container.buttons.allElementsBoundByIndex once
before the label loop, then reuse that collection when filtering for matching
buttons. Preserve the existing label/identifier matching and
hittable/existing-button selection behavior in the loop.
---
Outside diff comments:
In `@apps/swift/scripts/capture-visual-screenshots.ts`:
- Around line 787-815: Update the simulator-selection flow around the xcrun
inventory result and safeJsonParse so createIOSSimulator is called only after a
successful command and valid JSON inventory. Track inventory success separately
from whether a preferred device was found, and gate the createIfMissing fallback
on that success; keep returning matching device UDIDs unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ed8588dd-a468-4cdb-83c5-3d9fe6cc97f2
📒 Files selected for processing (13)
apps/swift/Sources/PackRat/Features/Packs/PacksListView.swiftapps/swift/Sources/PackRat/Features/Packs/PacksViewModel.swiftapps/swift/Sources/PackRat/Features/Trips/TripsListView.swiftapps/swift/Sources/PackRat/Features/Trips/TripsViewModel.swiftapps/swift/Sources/PackRat/PackRatApp.swiftapps/swift/Sources/PackRat/Persistence/PersistenceController.swiftapps/swift/Tests/PackRatUITests/HomeTileTests.swiftapps/swift/Tests/PackRatUITests/ScreenshotSmokeTests.swiftapps/swift/Tests/PackRatUITests/VisualScreenshotTests.swiftapps/swift/scripts/__tests__/args.test.tsapps/swift/scripts/capture-visual-screenshots.tsapps/swift/scripts/lib/args.tspackage.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift (1)
1342-1350: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winPush predicate matching to the query engine to avoid excessive IPC overhead.
Although caching
allElementsBoundByIndexavoids re-fetching the array of proxy objects, evaluating.labeland.identifieron each proxy still triggers cross-process IPC calls back to the target app on every loop iteration. For UI tests with many buttons, this causes significant lag.Evaluate the properties directly in the target app process using an
NSPredicateto retrieve only the matching elements.⚡ Proposed refactor
`#if` os(macOS) - let allButtons = container.buttons.allElementsBoundByIndex for label in ["Remind Me Later", "Not Now", "Continue", "OK", "Allow", "Dismiss", "Close"] { - let matchingButtons = allButtons - .filter { $0.label == label || $0.identifier == label } + let query = container.buttons.matching(NSPredicate(format: "label == %@ OR identifier == %@", label, label)) + let matchingButtons = query.allElementsBoundByIndex if let button = matchingButtons.first(where: { $0.exists && $0.isHittable }) ?? matchingButtons.first(where: { $0.exists }) { button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).click() return true } } `#endif`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift` around lines 1342 - 1350, Update the button lookup in the screenshot test to use an NSPredicate against the UI query engine, matching each candidate label or identifier directly in the target app process. Preserve the existing label priority, existence/hittability preference, coordinate click, and early return behavior while eliminating per-proxy .label and .identifier access in the loop.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift`:
- Around line 1342-1350: Update the button lookup in the screenshot test to use
an NSPredicate against the UI query engine, matching each candidate label or
identifier directly in the target app process. Preserve the existing label
priority, existence/hittability preference, coordinate click, and early return
behavior while eliminating per-proxy .label and .identifier access in the loop.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4b6665c7-ead8-4268-9b51-d8b869cf7d12
📒 Files selected for processing (6)
.github/workflows/swift-ci.ymlapps/swift/Tests/PackRatUITests/HomeTileTests.swiftapps/swift/Tests/PackRatUITests/VisualScreenshotTests.swiftapps/swift/scripts/__tests__/args.test.tsapps/swift/scripts/capture-visual-screenshots.tsapps/swift/scripts/lib/args.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/swift/project.yml`:
- Around line 173-174: Remove AppIcon-watch-marketing-1024.png from the
postbuildScripts loop in apps/swift/project.yml:173-174, including the preceding
line’s trailing backslash; remove the same entry from the CFBundleIconFiles list
in apps/swift/project.yml:197-198 and from the CFBundleIconFiles array in
apps/swift/Resources/Info-watchOS.plist:26-28. Keep the remaining watchOS icon
entries unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ffb6552d-bb0c-4bce-8c16-3f7fd159c2d8
⛔ Files ignored due to path filters (32)
apps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-20.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-20@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-29.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-29@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-40.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-40@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-76.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-76@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPad-83.5@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-20@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-20@3x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-29@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-29@3x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-40@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-40@3x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-60@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-iPhone-60@3x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-launcher-40@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-launcher-44@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-launcher-50@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-longlook-44x44@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-longlook-50x50@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-marketing-1024.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-notification-24@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-notification-27.5@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-quicklook-108@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-quicklook-44@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-quicklook-50@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-quicklook-86@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-quicklook-98@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-settings-29@2x.pngis excluded by!**/*.pngapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-watch-settings-29@3x.pngis excluded by!**/*.png
📒 Files selected for processing (7)
apps/swift/Resources/Assets.xcassets/AppIcon.appiconset/Contents.jsonapps/swift/Resources/Info-iOS.plistapps/swift/Resources/Info-macOS.plistapps/swift/Resources/Info-watchOS.plistapps/swift/project.ymlapps/swift/scripts/__tests__/app-store-assets.test.tsapps/swift/scripts/lib/app-store-assets.ts
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/api/src/routes/seasonSuggestions.ts (1)
136-137: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winHandle Workers AI SDK errors gracefully.
As per path instructions, Workers AI / Vercel AI SDK calls should handle rate-limit and upstream errors gracefully. The
generateObjectcall immediately following this setup (line 145) lacks atry/catchblock and acaptureApiExceptioncall to safely handle and log these upstream errors.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/api/src/routes/seasonSuggestions.ts` around lines 136 - 137, Wrap the generateObject call following createAIProvider in a try/catch, and invoke captureApiException in the catch handler to safely log and handle Workers AI/Vercel AI SDK rate-limit and upstream errors. Preserve the existing successful generation flow and return behavior.Source: Path instructions
apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift (1)
1280-1299: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winUse the runner’s PackRat credential environment consistently.
Unlike
AppUITestCase, this launch ignoresPACKRAT_E2E_EMAILandPACKRAT_E2E_USER_ID. When the runner supplies those values without a precomputed token, the token is derived from fallback credentials and may not authenticate against the configured local API.Proposed fix
- let email = (bundle.object(forInfoDictionaryKey: "PACKRAT_E2E_EMAIL") as? String) + let email = ProcessInfo.processInfo.environment["PACKRAT_E2E_EMAIL"] + ?? (bundle.object(forInfoDictionaryKey: "PACKRAT_E2E_EMAIL") as? String) ?? "e2e@packrat.test" - let userId = ProcessInfo.processInfo.environment["E2E_TEST_USER_ID"] + let userId = ProcessInfo.processInfo.environment["PACKRAT_E2E_USER_ID"] + ?? ProcessInfo.processInfo.environment["E2E_TEST_USER_ID"] ?? (bundle.object(forInfoDictionaryKey: "PACKRAT_E2E_USER_ID") as? String)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift` around lines 1280 - 1299, Update the credential resolution in the visual screenshot launch setup to use the runner’s PackRat credential environment consistently, matching AppUITestCase rather than relying on bundle keys or fallback values. Ensure PACKRAT_E2E_EMAIL and PACKRAT_E2E_USER_ID from the process environment are used when deriving visualE2ESessionToken, while preserving the existing launchEnvironment assignments.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/swift-e2e.yml:
- Around line 127-128: Update both credential validation blocks in
.github/workflows/swift-e2e.yml at lines 127-128 and 255-256 to skip E2E_EMAIL
and E2E_PASSWORD checks for local macOS and iOS runs, while retaining validation
for non-local runs so the local API lifecycle can provide credentials.
In @.github/workflows/swift-visual.yml:
- Around line 119-125: Update the “Boot iOS simulator” step’s if condition so it
runs only when github.event.inputs.platform is ios, all, or both. Exclude ipad,
watch, and macos while preserving the existing default-to-all behavior.
In `@apps/swift/scripts/capture-visual-screenshots.ts`:
- Around line 927-931: Update the screenshot capture flows around
injectVisualSchemeEnvironment and the referenced credential-injection blocks to
avoid modifying tracked Xcode schemes with E2E credentials. Use a temporary
scheme/project copy for each run, or capture and exactly restore the original
scheme content in guaranteed cleanup, including failure paths; preserve the
existing screenshot behavior while ensuring no credentials remain persisted.
In `@apps/swift/scripts/lib/e2e-api.ts`:
- Around line 93-103: Handle child-process spawn failures at all three sites: in
apps/swift/scripts/lib/e2e-api.ts lines 93-103, attach an error handler to the
child used by waitForHealthy and reject that flow; in
apps/swift/scripts/run-e2e.ts lines 290-303 and
apps/swift/scripts/run-e2e-macos.ts lines 296-309, update the xcodebuild promise
to reject on the child process error event, while preserving existing exit
handling.
In `@apps/swift/scripts/run-e2e.ts`:
- Around line 119-126: Update the session-token derivation in
apps/swift/scripts/run-e2e.ts lines 119-126 to use BETTER_AUTH_SECRET for the
secret, preserving the existing fallback only if required by the API contract.
In apps/swift/scripts/run-e2e-macos.ts lines 137-144, remove PACKRAT_AUTH_SECRET
precedence so both scripts derive tokens identically to the API contract.
- Around line 97-98: Wrap the complete lifecycle after acquiring localAPI in
run-e2e.ts around ensureLocalE2EAPI with a try/finally, ensuring cleanup
executes for every subsequent path. Apply the same boundary and cleanup behavior
in run-e2e-macos.ts immediately after its localAPI acquisition.
In `@apps/swift/Sources/PackRat/Services/CatalogService.swift`:
- Around line 23-26: Update the catalog search flow around CatalogSearchResponse
so the endpoint request is performed only once. Fetch the response payload once,
then decode it in memory as either the wrapped CatalogSearchResponse or an
unwrapped [CatalogItem] array, while propagating network errors without retrying
the request.
In `@apps/swift/Tests/PackRatTests/OfflineAITests.swift`:
- Around line 270-271: Update the test setup around Defaults[.useRealLocalLLM]
to capture its original value before forcing it to true, then restore that
captured value in the defer block instead of always assigning false. Keep the
test’s existing behavior while preventing shared preference state from affecting
later tests.
In `@apps/swift/Tests/PackRatUITests/AppUITestCase.swift`:
- Around line 332-343: Update tapTabBarButton to perform only one coordinate tap
for valid element frames, then wait deterministically for the destination
landmark instead of sleeping and tapping again. Preserve the existing fallback
element.tap() behavior for zero-sized frames, and replace the fixed Thread.sleep
delay with the test’s established landmark-wait mechanism.
In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift`:
- Around line 791-794: Ensure guest-limit content is validated before
screenshots are captured: in captureGuestLimitedTab, perform
assertExpectedAccountRequiredState before captureTab, and at
apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift lines 932-946 move
each account-required assertion before its corresponding capture. Preserve the
existing navigation and assertion targets.
In `@packages/api/scripts/e2e-local-start.ts`:
- Around line 34-42: Update the command execution flow around child.exited so
captured stdout and stderr are emitted before handling a nonzero exit code.
Preserve the existing output behavior for successful commands, then throw the
exit error while retaining the captured diagnostics for failures.
In `@packages/api/src/e2e-worker.ts`:
- Around line 43-53: The E2E worker’s well-known metadata branch lacks the
production CORS behavior for metadata and preflight requests. Update the GET
handling around wellKnownMetadataKind and the related OPTIONS/appBase.fetch path
in the worker entrypoint to mirror index.ts, applying the established well-known
CORS headers and preflight response behavior; add an Origin-based test covering
metadata and OPTIONS requests.
In `@packages/api/src/index.ts`:
- Around line 162-185: Fix mounted OpenID discovery classification in
wellKnownMetadataPath and wellKnownMetadataKind so
/api/auth/.well-known/openid-configuration is recognized while preserving
unmounted and authorization-server routes. Apply the corresponding routing
update in packages/api/src/e2e-worker.ts at lines 21-35, and add mounted OpenID
URL coverage in packages/api/src/__tests__/auth-cors.test.ts lines 153-178 and
packages/api/src/__tests__/e2e-worker-env.test.ts lines 88-105.
In `@packages/api/src/routes/catalog/index.ts`:
- Around line 41-47: Extract the duplicated local E2E environment detection from
isLocalE2ECatalogEnv into the shared env-validation utility, exposing a reusable
predicate for the OPENAI_API_KEY and local NEON_DATABASE_URL checks. Update this
route and the corresponding checks in guides/index.ts and seasonSuggestions.ts
to use the shared utility, preserving the existing detection behavior.
- Around line 176-201: Use captureApiException from `@packrat/api/utils/sentry` in
the catch blocks for the /catalog/vector-search route in
packages/api/src/routes/catalog/index.ts (lines 176-201), and the GET /guides
(109-126), GET /guides/categories (225-231), GET /guides/search (292-315), and
GET /guides/:id (411-416) handlers in packages/api/src/routes/guides/index.ts;
replace or augment existing console.error-only handling while preserving each
route’s existing response behavior.
In `@packages/api/src/routes/weather.ts`:
- Around line 20-155: Move the weather E2E fixture symbols from the route module
into a dedicated service under src/services/, including stub location matching
and forecast construction helpers such as getStubLocation, searchStubLocations,
buildStubForecast, buildStubCurrent, and buildStubForecastDay. Keep the route
responsible only for detecting stub mode and delegating to the service,
preserving the existing stub responses and behavior.
---
Outside diff comments:
In `@apps/swift/Tests/PackRatUITests/VisualScreenshotTests.swift`:
- Around line 1280-1299: Update the credential resolution in the visual
screenshot launch setup to use the runner’s PackRat credential environment
consistently, matching AppUITestCase rather than relying on bundle keys or
fallback values. Ensure PACKRAT_E2E_EMAIL and PACKRAT_E2E_USER_ID from the
process environment are used when deriving visualE2ESessionToken, while
preserving the existing launchEnvironment assignments.
In `@packages/api/src/routes/seasonSuggestions.ts`:
- Around line 136-137: Wrap the generateObject call following createAIProvider
in a try/catch, and invoke captureApiException in the catch handler to safely
log and handle Workers AI/Vercel AI SDK rate-limit and upstream errors. Preserve
the existing successful generation flow and return behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a89a0c2d-ab43-4d64-9859-1992a441c53d
⛔ Files ignored due to path filters (11)
apps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-launcher-40@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-launcher-44@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-launcher-50@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-marketing-1024.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-notification-24@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-notification-27.5@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-quicklook-108@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-quicklook-86@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-quicklook-98@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-settings-29@2x.pngis excluded by!**/*.pngapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/AppIcon-watch-settings-29@3x.pngis excluded by!**/*.png
📒 Files selected for processing (68)
.github/workflows/swift-e2e.yml.github/workflows/swift-visual.ymlapps/swift/Resources/Assets.xcassets/AppIcon.appiconset/Contents.jsonapps/swift/Resources/Info-watchOS.plistapps/swift/Resources/WatchAssets.xcassets/Contents.jsonapps/swift/Resources/WatchAssets.xcassets/WatchAppIcon.appiconset/Contents.jsonapps/swift/Sources/PackRat/Features/Catalog/CatalogItemDetailView.swiftapps/swift/Sources/PackRat/Features/Catalog/CatalogView.swiftapps/swift/Sources/PackRat/Features/Chat/ChatView.swiftapps/swift/Sources/PackRat/Features/Chat/ChatViewModel.swiftapps/swift/Sources/PackRat/Features/OfflineAI/FeatureFlag.swiftapps/swift/Sources/PackRat/Features/OfflineAI/OfflineAIView.swiftapps/swift/Sources/PackRat/Features/PackTemplates/PackTemplateFormView.swiftapps/swift/Sources/PackRat/Features/PackTemplates/PackTemplatesView.swiftapps/swift/Sources/PackRat/Features/Packs/PackItemDetailView.swiftapps/swift/Sources/PackRat/Features/SeasonSuggestions/SeasonSuggestionsView.swiftapps/swift/Sources/PackRat/Features/TrailConditions/TrailConditionsView.swiftapps/swift/Sources/PackRat/Features/Weather/WeatherView.swiftapps/swift/Sources/PackRat/Navigation/AppNavigation.swiftapps/swift/Sources/PackRat/Network/AuthManager.swiftapps/swift/Sources/PackRat/Services/CatalogService.swiftapps/swift/Sources/PackRat/Shared/FormSheetSizing.swiftapps/swift/Sources/PackRat/Shared/VisualSampleData.swiftapps/swift/Sources/PackRatWatch/PackRatWatchApp.swiftapps/swift/Tests/PackRatMacUITests/MacHomeFeatureTests.swiftapps/swift/Tests/PackRatMacUITests/MacNavigationTests.swiftapps/swift/Tests/PackRatMacUITests/MacPackTripTests.swiftapps/swift/Tests/PackRatMacUITests/MacSecondaryFeatureTests.swiftapps/swift/Tests/PackRatMacUITests/MacSmokeTests.swiftapps/swift/Tests/PackRatMacUITests/MacUITestCase.swiftapps/swift/Tests/PackRatMacUITests/MacWeatherTests.swiftapps/swift/Tests/PackRatTests/OfflineAITests.swiftapps/swift/Tests/PackRatUITests/AppUITestCase.swiftapps/swift/Tests/PackRatUITests/AuthTests.swiftapps/swift/Tests/PackRatUITests/ChatMacOSTests.swiftapps/swift/Tests/PackRatUITests/ChatTests.swiftapps/swift/Tests/PackRatUITests/HomeTileTests.swiftapps/swift/Tests/PackRatUITests/PackMacOSTests.swiftapps/swift/Tests/PackRatUITests/PackSubFlowMacOSTests.swiftapps/swift/Tests/PackRatUITests/PackTemplateTests.swiftapps/swift/Tests/PackRatUITests/PackTests.swiftapps/swift/Tests/PackRatUITests/ScreenshotSmokeTests.swiftapps/swift/Tests/PackRatUITests/SeasonSuggestionsMacOSTests.swiftapps/swift/Tests/PackRatUITests/SeasonSuggestionsTests.swiftapps/swift/Tests/PackRatUITests/VisualScreenshotTests.swiftapps/swift/project.ymlapps/swift/scripts/capture-visual-screenshots.tsapps/swift/scripts/generate-swift-config.tsapps/swift/scripts/lib/e2e-api.tsapps/swift/scripts/run-e2e-macos.tsapps/swift/scripts/run-e2e.tsapps/swift/scripts/validate-app-store-assets.tsdocs/testing.mdpackage.jsonpackages/api/scripts/e2e-local-start.tspackages/api/src/__tests__/auth-cors.test.tspackages/api/src/__tests__/e2e-worker-env.test.tspackages/api/src/e2e-worker.tspackages/api/src/index.tspackages/api/src/routes/__tests__/chat-e2e-stub.test.tspackages/api/src/routes/__tests__/weather-e2e-stub.test.tspackages/api/src/routes/catalog/index.tspackages/api/src/routes/chat.tspackages/api/src/routes/guides/index.tspackages/api/src/routes/seasonSuggestions.tspackages/api/src/routes/weather.tspackages/api/src/services/__tests__/embeddingService.test.tspackages/api/src/services/embeddingService.ts
💤 Files with no reviewable changes (8)
- apps/swift/Tests/PackRatMacUITests/MacNavigationTests.swift
- apps/swift/Tests/PackRatMacUITests/MacSmokeTests.swift
- apps/swift/Tests/PackRatMacUITests/MacWeatherTests.swift
- apps/swift/Tests/PackRatMacUITests/MacSecondaryFeatureTests.swift
- apps/swift/Tests/PackRatMacUITests/MacHomeFeatureTests.swift
- apps/swift/Tests/PackRatMacUITests/MacPackTripTests.swift
- apps/swift/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
- apps/swift/Tests/PackRatMacUITests/MacUITestCase.swift
…ta-tester-readiness # Conflicts: # apps/swift/Sources/PackRat/Features/Packs/PacksListView.swift
Deploying packrat-guides with
|
| Latest commit: |
c0f223e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://4a098086.packrat-guides-6gq.pages.dev |
| Branch Preview URL: | https://codex-swift-beta-tester-read.packrat-guides-6gq.pages.dev |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
packrat-admin | c0f223e | Commit Preview URL Branch Preview URL |
Jul 21 2026, 01:18 PM |
Deploying packrat-landing with
|
| Latest commit: |
c0f223e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c56818f3.packrat-landing.pages.dev |
| Branch Preview URL: | https://codex-swift-beta-tester-read.packrat-landing.pages.dev |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Swift launch-readiness QA update from Codex:
Net: Swift app path is green locally and in GitHub; remaining red status is non-Swift E2E timeout debt. |
Summary
2.1.0with build2026072101, and forceMARKETING_VERSIONduring replacement archive flows.Fixes #2636
Fixes #2640
Fixes #2641
Fixes #2642
Validation
6b167e190: all 26 completed GitHub checks passed, with no pending or failing checkscc2bc691e: all 26 completed GitHub checks passed, with no pending or failing checks, after fixing scheduled Swift E2E to select the explicit dev API target instead of requiring the unconfiguredSWIFT_E2E_API_BASE_URLsecretmain(run 30001819415) was traced to duplicatePackRatApp.init()declarations; commit55796b21fon this PR consolidates them, and the prior head's Swift checks passedmacOS/packrat-e2erunner is online; this is an operational prerequisite and was not hidden by weakening or skipping the jobPackRat-iOS (smoke),PackRat-macOS (smoke), andSwift scripts (vitest)passediOS Swift UI E2E (Exploratory)passedMARKETING_VERSION=2.1.0andCURRENT_PROJECT_VERSION=2026072101PackRat-iOSWeatherTemperatureDisplayTestspassedScreenshot Catalog
artifacts/screenshots/ios-contact-sheet*.pngartifacts/screenshots/ipad-contact-sheet*.pngartifacts/screenshots/macos-contact-sheet*.pngNotes
2.0.28; it is not solved by this Swift beta-readiness PR.