feat(frontend): bundle dependency compatibility view#2375
feat(frontend): bundle dependency compatibility view#2375WcaleNieWolny wants to merge 4 commits into
Conversation
Adds an OTA compatibility verdict and a status-aware dependency diff to the bundle Dependencies tab, comparing the viewed bundle (candidate) against a selected baseline bundle. - Per-package status with colours: changed (blue, old -> new), added (green), removed (red), unchanged (gray). - Compatibility verdict banner (compatible vs requires-app-store-update) using logic ported from the CLI's getCompatibilityDetails: version-range intersection + native checksum changes; new native plugins block OTA. - Comparison is deep-linkable via ?compare=<versionId>. - Compare picker excludes deleted bundles and falls back past deleted deployments when choosing preferred baselines. - New unit-tested util src/services/bundleCompatibility.ts. Builds on the compare-picker fix already merged in #2373.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a shared bundle compatibility service and tests, updates design docs and i18n, improves compare-version candidate selection, and refactors the dependencies page to show baseline-driven compatibility verdicts, per-package statuses, and localized incompatibility reasons. ChangesBundle Dependency OTA Compatibility Feature
Sequence DiagramsequenceDiagram
participant User
participant DepsPage
participant URL
participant Supabase
participant CompatService
User->>DepsPage: select baseline version
DepsPage->>URL: write ?compare=versionId
DepsPage->>Supabase: fetch baseline native_packages
Supabase-->>DepsPage: baselinePackages
DepsPage->>CompatService: comparePackages(candidate, baseline)
CompatService-->>DepsPage: comparisons[]
DepsPage->>DepsPage: compute statusCounts + compatibilitySummary
DepsPage-->>User: render verdict banner + status cards + table
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90c3f20377
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
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 `@src/services/bundleCompatibility.ts`:
- Around line 85-90: Remove the redundant Boolean() wrappers around the checksum
comparisons: assign iosChanged and androidChanged directly from the logical
expressions using candidate.ios_checksum && baseline.ios_checksum &&
candidate.ios_checksum !== baseline.ios_checksum and candidate.android_checksum
&& baseline.android_checksum && candidate.android_checksum !==
baseline.android_checksum respectively so the expressions themselves produce the
boolean values (refer to iosChanged and androidChanged in the current diff).
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a83a2cfa-42af-410e-986e-cd2d040e3077
📒 Files selected for processing (6)
docs/superpowers/specs/2026-05-30-bundle-dependency-compatibility-design.mdmessages/en.jsonsrc/components/bundle/BundleCompareSelect.vuesrc/pages/app/[app].bundle.[bundle].dependencies.vuesrc/services/bundleCompatibility.tstests/bundle-compatibility.unit.test.ts
…ar nits - restoreCompareFromQuery now requires deleted=false and (dependencies mode) native_packages IS NOT NULL, matching the compare picker's eligibility. A ?compare= link to a deleted or package-less bundle is scrubbed instead of comparing against an empty baseline that reports every dep as added. (Codex P2) - Replace the void operator on router.replace with a .catch() (Sonar S3735). - Flip the negated ternary in the sort comparator (Sonar S7735).
Use explicit != null guards so iosChanged/androidChanged are still typed as boolean (bare && would infer string | boolean). Addresses CodeRabbit nitpick on #2375.
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)
src/services/bundleCompatibility.ts (1)
98-109:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign
statusForwith checksum-based incompatibility so “Unchanged” never blocks OTA
evaluateReasonsflagsios_code_changed/android_code_changed/both_platforms_changedwhen checksums differ (null-safe), butstatusForonly markschangedoncandidate.version !== baseline.version; unit tests already cover same-version/different-iOS-checksum =>status: 'unchanged'withcompatible: false.dependencies.vuerenders the pill fromentry.statuswhile rendering incompatibility reasons only when!entry.compatible, so users can see a gray “Unchanged” row alongside red “native code changed” text while the verdict banner reports blocking OTA.- Update
statusForto incorporate the same criteria asevaluateReasons(checksum diffs, and consider aligning the version-mismatch condition toversionsIntersectrather than string inequality).🤖 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 `@src/services/bundleCompatibility.ts` around lines 98 - 109, statusFor currently marks packages 'changed' only when candidate.version !== baseline.version, which misses checksum-based native-code changes used by evaluateReasons; update statusFor (function statusFor) to return 'changed' if any platform checksum differs (null-safe compare candidate.iosChecksum vs baseline.iosChecksum, candidate.androidChecksum vs baseline.androidChecksum, or both) or if versions do not intersect (use versionsIntersect(candidate.version, baseline.version) rather than plain string inequality), otherwise return 'unchanged' or the existing 'added'/'removed' cases; align logic with evaluateReasons so checksum diffs cause status 'changed' and reflect compatibility consistently.
🤖 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 `@src/services/bundleCompatibility.ts`:
- Around line 98-109: statusFor currently marks packages 'changed' only when
candidate.version !== baseline.version, which misses checksum-based native-code
changes used by evaluateReasons; update statusFor (function statusFor) to return
'changed' if any platform checksum differs (null-safe compare
candidate.iosChecksum vs baseline.iosChecksum, candidate.androidChecksum vs
baseline.androidChecksum, or both) or if versions do not intersect (use
versionsIntersect(candidate.version, baseline.version) rather than plain string
inequality), otherwise return 'unchanged' or the existing 'added'/'removed'
cases; align logic with evaluateReasons so checksum diffs cause status 'changed'
and reflect compatibility consistently.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 753a6029-a457-4ccc-af40-b09e2ba3a0eb
📒 Files selected for processing (1)
src/services/bundleCompatibility.ts
…nchanged' statusFor marked a package 'changed' only on a version-string difference, but evaluateReasons also flags incompatibility when a native checksum changes at the same version. That produced a contradictory row: a gray 'Unchanged' pill next to red 'native code changed' text while the verdict reported incompatible. Derive status from the computed reasons too, so a same-version bundle whose native code changed is shown as 'changed' and stays consistent with the verdict. Addresses CodeRabbit review on #2375.
|
Addressed the CodeRabbit "outside diff range" finding on |
|



Summary
Adds a bundle dependency compatibility view to the Dependencies tab. It compares the bundle you're viewing (the candidate — what would ship over-the-air) against a baseline bundle you pick, and tells you whether the update is OTA-safe or needs an app-store update — the same verdict as the CLI
capgo bundle compatibility.Builds on the compare-picker fix already merged in #2373 (which gated the picker on
native_packages). This PR is a single clean commit on top ofmain.What it does
Status-aware dependency diff — every native package shown with a colour-coded status and version(s):
old → newNew · <version>Removed · <version>Unchanged · <version>Counts row: Changed / Added / Removed / Unchanged.
Compatibility verdict banner — ✅ Compatible ("can be delivered over-the-air to devices running {baseline}") or ❌ Not compatible ("N packages require an app store update"), with per-package reasons. Logic is ported from the CLI's
getCompatibilityDetails: version-range intersection (@std/semver) plus iOS/Android native checksum changes; a new native plugin blocks OTA, a removed one is safe.Deep-linkable — selecting a baseline reflects in the URL as
?compare=<versionId>(history-friendlyrouter.replace); loading such a URL pre-selects the baseline.Picker hygiene — the compare dropdown excludes soft-deleted bundles, and falls back past deleted deployments when choosing preferred (deploy-history) baselines, so a channel whose latest prior deploy was deleted still gets a usable baseline.
Direction (by design)
The viewed bundle is the candidate; the picked bundle is the installed baseline — matching the CLI. So an added native plugin (green in the diff) is also what triggers a ❌ verdict (new native code → app-store update); the banner names offenders so the two readings never contradict.
Files
src/services/bundleCompatibility.ts— pure, unit-tested comparison + verdict util.tests/bundle-compatibility.unit.test.ts— 14 tests.src/pages/app/[app].bundle.[bundle].dependencies.vue— status-aware table, verdict banner,?comparesync.src/components/bundle/BundleCompareSelect.vue— exclude deleted bundles; deleted-deployment fallback.messages/en.json— new i18n keys (source locale; others fall back toen).docs/superpowers/specs/.No backend/schema/API changes.
Verification
oxlint srcandeslint src/**/*.{vue,ts,js}both cleangsapresolution note)me.wcaleniewolny.test.ionic.vue2):1.0.7-cvs0.0.0→ 3 changed packages, ❌ Not compatible; deleted1.0.4-*bundles excluded from the picker; deploy-history fallback exercised (channel with 4 deleted + 10 live deploys).Test plan
?compare=.?compare=<id>URL directly → baseline pre-selected, comparison shown.Summary by CodeRabbit
New Features
User Experience
Documentation
Localization
Tests