Repository navigation
Fix NIGHTLY update bundle icon metadata - #4353
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a channel-aware bundle metadata verifier and integrates it into nightly/release post‑notarization steps; introduces AppBundleIconPersistencePolicy with app/plugin and smoke-launch wiring to control dock icon persistence; refactors keyboard-settings startup side-effect handling and updates tests including a CLI socket test refactor. ChangesBundle metadata validation and icon persistence
Sequence Diagram(s)sequenceDiagram
participant Workflow as Nightly/Release Workflow
participant Verifier as verify-app-bundle-channel-metadata.sh
participant Plist as Info.plist reader
participant Icon as .icns file check
participant Codesign as codesign verifier
Workflow->>Verifier: invoke (app-path, channel)
Verifier->>Plist: read & validate CFBundle* keys
Verifier->>Icon: check .icns exists & non-empty
Verifier->>Codesign: if _CodeSignature present -> codesign --verify
Verifier->>Workflow: exit 0 on success (continue packaging)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 1 warning)
✅ Passed checks (15 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 |
Greptile SummaryThis PR fixes NIGHTLY/debug bundle icon corruption during CI packaging by confining
Confidence Score: 5/5Safe to merge — the fix correctly owns the invariant at three layers (policy, shared defaults, post-smoke verification) with no regressions found. The Dock tile plugin now reads from the shared defaults domain rather than the wrong process's launch arguments, the smoke script seeds and cleans up the key around the launch window, and the verify script gates DMG creation on all plist/codesign invariants. The deferred side-effects path is well-tested and the ordering guarantees are preserved by the deduplicating batch structure. No correctness issues were found across the Swift, shell, or workflow changes. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant CI as CI Workflow
participant Script as smoke-launch-macos-app.sh
participant Defaults as UserDefaults bundle domain
participant App as cmuxApp.init MainActor
participant Plugin as CmuxDockTilePlugin Dock.app
participant Verify as verify-app-bundle-channel-metadata.sh
CI->>Script: run app_path
Script->>Defaults: defaults write BUNDLE_ID cmuxDisableBundleIconPersistence YES
Script->>App: open --args --cmux-disable-bundle-icon-persistence
App->>Defaults: updateDisableDefault true via UserDefaults.standard
Plugin->>Defaults: read cmuxDisableBundleIconPersistence
Defaults-->>Plugin: true so shouldPersist is false
Note over Plugin: setIcon skipped no Icon file written
Script->>Script: wait STABLE_SECONDS
Script->>App: kill APP_PID
Script->>Defaults: defaults delete key in EXIT trap
CI->>Verify: run app_path stable or nightly
Verify->>Verify: check CFBundleName CFBundleIdentifier CFBundleIconFile CFBundleIconName
Verify->>Verify: check icns present no custom icon no FinderInfo
Verify->>Verify: codesign verify deep strict if signed
Verify-->>CI: exit 0 proceed to DMG
Reviews (10): Last reviewed commit: "fix: initialize icon persistence flag be..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@Sources/AppBundleIconPersistencePolicy.swift`:
- Around line 1-23: AppBundleIconPersistencePolicy (including static properties
stableReleaseBundleIdentifier, stableReleaseAppBundleName,
disablePersistenceArgument and the method shouldPersist) is
lifecycle-independent and must be relocated out of the app target root Sources/
into a shared/helper module; move the entire enum file into an existing non-root
shared or helper directory (e.g., a utilities or Foundation-only target) so it
compiles and tests without app lifecycle dependencies, update the module
import/visibility if needed, and adjust any call sites to import the new module
or target where AppBundleIconPersistencePolicy now lives.
In `@Sources/AppIconDockTilePlugin.swift`:
- Around line 91-94: AppIconDockTilePlugin's use of
ProcessInfo.processInfo.arguments (inside NSDockTilePlugIn) cannot read the
target app's launch args so the current gate around
AppBundleIconPersistencePolicy.shouldPersist will not work; change the gating to
read a shared preference or IPC instead (e.g., a UserDefaults(suiteName:)
app-group key or DistributedNotification/CFPreferences) that both the main app
and the Dock plug-in can access. Update AppIconDockTilePlugin to check the
shared UserDefaults key (set by the main app when handling
--cmux-disable-bundle-icon-persistence) before calling
AppBundleIconPersistencePolicy.shouldPersist, and ensure the main app writes
that key at launch; alternatively use a distributed notification or other IPC to
propagate the flag from the app to the plug-in.
🪄 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: ae209b14-4170-47be-9acb-008616ea6d6a
📒 Files selected for processing (4)
Sources/AppBundleIconPersistencePolicy.swiftSources/AppIconDockTilePlugin.swiftcmux.xcodeproj/project.pbxprojcmuxTests/AppearanceSettingsTests.swift
Dismissed as outdated after the requested changes were addressed in 69c6208: the policy moved under Sources/App, the Dock tile plugin now reads shared app defaults instead of process arguments, and CodeRabbit marked the inline threads addressed.
There was a problem hiding this comment.
1 issue found across 6 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…-4350-nightly-update-quit-dialog
…date-quit-dialog # Conflicts: # Sources/KeyboardShortcutSettingsFileStore.swift
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/KeyboardShortcutSettingsFileStore.swift (1)
207-230:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDeferred side effects are dropped instead of replayed.
reload(applyLiveDefaultSideEffects: false)writes the managed defaults, but the laterreapplyManagedSettingsIfNeeded()pass only emits side effects when a value is mutated. By then the stored value already matches the imported default, sodidMutateStoredValueis false and notifications/runtime updates likeTerminalScrollBarSettingsandAgentSessionAutoResumeSettingsnever fire. The removed-key path is worse: once startup restores a backup with side effects suppressed,activeManagedUserDefaultscan be empty and the later reapply path never runs at all. Please track suppressed side effects and flush them after initialization, or let the first post-startup replay apply side effects even when no storage mutation is needed.Also applies to: 865-925, 1066-1072, 1152-1158
🤖 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 `@cmuxTests/ShortcutAndCommandPaletteTests.swift`:
- Around line 1589-1605: Add the missing fourth assertion to fully cover all
branches: in the testShouldShowConfirmationFollowsEnabledPreference function,
after setting defaults.set(false, forKey:
QuitWarningSettings.warnBeforeQuitKey), add an assertion that
QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: true,
defaults: defaults) returns false; this uses the existing defaults variable and
exercises QuitWarningSettings.shouldShowConfirmation and the
QuitWarningSettings.warnBeforeQuitKey path for the (false, true) case.
In `@tests/test_cli_socket_autodiscovery.py`:
- Around line 83-84: Replace the use of the aliased socket.timeout exception
with the builtin TimeoutError in the exception handler to be idiomatic for
Python 3.10+; locate the try/except block in
tests/test_cli_socket_autodiscovery.py (the loop that currently has "except
socket.timeout: continue") and change it to "except TimeoutError: continue" so
the test catches the canonical exception type (no new imports required).
- Around line 101-116: In _handle_connection, replace the socket-specific
exception in the except clause with the modern built-in TimeoutError to match
the earlier change: update the except tuple (currently except
(ConnectionResetError, socket.timeout):) to use TimeoutError instead of
socket.timeout so the handler catches ConnectionResetError and TimeoutError
consistently.
🪄 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: e2dedcf2-fe39-478c-8f31-c6da205acf61
📒 Files selected for processing (6)
Sources/AppDelegate.swiftSources/KeyboardShortcutSettingsFileStore.swiftSources/cmuxApp.swiftcmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swiftcmuxTests/ShortcutAndCommandPaletteTests.swifttests/test_cli_socket_autodiscovery.py
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/AppDelegate.swift">
<violation number="1" location="Sources/AppDelegate.swift:1545">
P2: Tagged DEV builds no longer bypass quit confirmation in `applicationShouldTerminate`, causing an unintended warning dialog regression.</violation>
<violation number="2" location="Sources/AppDelegate.swift:11193">
P2: `handleQuitShortcutWarning` lost the tagged DEV bypass, so Cmd+Q can now prompt instead of exiting immediately on tagged DEV builds.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| } | ||
|
|
||
| if !QuitWarningSettings.isEnabled() { | ||
| if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: false) { |
There was a problem hiding this comment.
P2: handleQuitShortcutWarning lost the tagged DEV bypass, so Cmd+Q can now prompt instead of exiting immediately on tagged DEV builds.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Sources/AppDelegate.swift, line 11193:
<comment>`handleQuitShortcutWarning` lost the tagged DEV bypass, so Cmd+Q can now prompt instead of exiting immediately on tagged DEV builds.</comment>
<file context>
@@ -11204,13 +11190,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
- }
-
- if !QuitWarningSettings.isEnabled() {
+ if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: false) {
NSApp.terminate(nil)
return true
</file context>
| if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: false) { | |
| if SocketControlSettings.isTaggedDevBuild() || !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: false) { |
There was a problem hiding this comment.
Intentional for this PR. The latest dogfood report was that tagged DEV had Warn Before Quit enabled but skipped the dialog; tagged DEV now honors the same quit-warning preference so this branch can verify that path.
— Claude Code
There was a problem hiding this comment.
Got it—thanks for the context. I’ll treat the tagged DEV bypass removal as intentional for this PR.
| if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: isQuitWarningConfirmed) { | ||
| closeAllWebInspectorsBeforeAppTeardown() | ||
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "taggedDev"]) | ||
| return .terminateNow | ||
| } | ||
|
|
||
| // If the user already confirmed via the Cmd+Q shortcut warning dialog | ||
| // (handleQuitShortcutWarning), skip the check to avoid a second alert. | ||
| if isQuitWarningConfirmed { | ||
| closeAllWebInspectorsBeforeAppTeardown() | ||
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "confirmed"]) | ||
| return .terminateNow | ||
| } | ||
|
|
||
| // Respect the "Warn Before Quit" setting even when Cmd+Q arrives via | ||
| // the Cmd+Tab app switcher, bypassing handleCustomShortcut. | ||
| guard QuitWarningSettings.isEnabled() else { | ||
| closeAllWebInspectorsBeforeAppTeardown() | ||
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "warningDisabled"]) | ||
| let reason = isQuitWarningConfirmed ? "confirmed" : "warningDisabled" | ||
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": reason]) | ||
| return .terminateNow |
There was a problem hiding this comment.
P2: Tagged DEV builds no longer bypass quit confirmation in applicationShouldTerminate, causing an unintended warning dialog regression.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Sources/AppDelegate.swift, line 1545:
<comment>Tagged DEV builds no longer bypass quit confirmation in `applicationShouldTerminate`, causing an unintended warning dialog regression.</comment>
<file context>
@@ -1540,26 +1540,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
- if SocketControlSettings.isTaggedDevBuild() {
+ // If the user already confirmed via the Cmd+Q shortcut warning dialog,
+ // or disabled the setting, skip the check to avoid a second alert.
+ if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: isQuitWarningConfirmed) {
closeAllWebInspectorsBeforeAppTeardown()
- StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "taggedDev"])
</file context>
| if !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: isQuitWarningConfirmed) { | |
| closeAllWebInspectorsBeforeAppTeardown() | |
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "taggedDev"]) | |
| return .terminateNow | |
| } | |
| // If the user already confirmed via the Cmd+Q shortcut warning dialog | |
| // (handleQuitShortcutWarning), skip the check to avoid a second alert. | |
| if isQuitWarningConfirmed { | |
| closeAllWebInspectorsBeforeAppTeardown() | |
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "confirmed"]) | |
| return .terminateNow | |
| } | |
| // Respect the "Warn Before Quit" setting even when Cmd+Q arrives via | |
| // the Cmd+Tab app switcher, bypassing handleCustomShortcut. | |
| guard QuitWarningSettings.isEnabled() else { | |
| closeAllWebInspectorsBeforeAppTeardown() | |
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": "warningDisabled"]) | |
| let reason = isQuitWarningConfirmed ? "confirmed" : "warningDisabled" | |
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": reason]) | |
| return .terminateNow | |
| if SocketControlSettings.isTaggedDevBuild() || !QuitWarningSettings.shouldShowConfirmation(isQuitWarningConfirmed: isQuitWarningConfirmed) { | |
| closeAllWebInspectorsBeforeAppTeardown() | |
| let reason = SocketControlSettings.isTaggedDevBuild() | |
| ? "taggedDev" | |
| : (isQuitWarningConfirmed ? "confirmed" : "warningDisabled") | |
| StartupBreadcrumbLog.append("appDelegate.shouldTerminate.terminateNow", fields: ["reason": reason]) | |
| return .terminateNow | |
| } |
There was a problem hiding this comment.
Intentional for this PR. The tagged DEV bypass caused the reported regression where Warn Before Quit was enabled but no confirmation appeared, so applicationShouldTerminate now uses the shared quit-warning policy.
— Claude Code
There was a problem hiding this comment.
Understood—thanks for the clarification. Noted that the change is intentional to use the shared quit-warning policy in this PR.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit aaec9d5. Configure here.
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 `@Sources/KeyboardShortcutSettingsFileStore.swift`:
- Around line 949-954: Drain deferred side effects before applying the live
batch: call drainDeferredManagedDefaultSideEffects() first, then merge the
current sideEffects into the drained batch (so the live sideEffects
overwrite/coalesce stale deferred entries), and pass that merged batch to
applyManagedDefaultBatchSideEffects(sideEffects) (leave
deferManagedDefaultSideEffects(sideEffects) in the else branch unchanged);
update the logic around drainDeferredManagedDefaultSideEffects(),
sideEffects.merge(...), and applyManagedDefaultBatchSideEffects(...) so the
drained batch is the base and the live sideEffects take precedence.
🪄 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: 443d4988-d98f-4f93-abf6-ef905248a408
📒 Files selected for processing (5)
Sources/KeyboardShortcutSettingsFileStore.swiftSources/cmuxApp.swiftcmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swiftcmuxTests/ShortcutAndCommandPaletteTests.swifttests/test_cli_socket_autodiscovery.py
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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 `@Sources/cmuxApp.swift`:
- Around line 47-57: Move the bundle-icon disable flag setup so it runs before
deferred side effects: call
AppBundleIconPersistencePolicy.updateDisableDefault(defaults:
UserDefaults.standard, launchArguments: ProcessInfo.processInfo.arguments)
before
KeyboardShortcutSettings.settingsFileStore.applyDeferredManagedDefaultSideEffects()
(so the shared disable flag is present when AppIconSettings.applyIcon()
notifications fire), effectively relocating the updateDisableDefault()
invocation above applyDeferredManagedDefaultSideEffects() and preserving the
existing defaults/launchArguments usage.
🪄 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: 22438fe6-fa6c-4a37-991f-4002525d1283
📒 Files selected for processing (5)
Sources/KeyboardShortcutSettingsFileStore.swiftSources/cmuxApp.swiftcmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swiftcmuxTests/ShortcutAndCommandPaletteTests.swifttests/test_cli_socket_autodiscovery.py
|
@coderabbitai review |
✅ Actions performedReview triggered.
|

Summary
com.cmuxterm.appmay persist a user-selected bundle iconFixes #4350.
Investigation
/Applications/cmux NIGHTLY.app/Contents/Info.plistcurrently hasCFBundleName=cmux NIGHTLY,CFBundleDisplayName=cmux NIGHTLY,CFBundleIconFile=AppIcon-Nightly, andCFBundleIconName=AppIcon-Nightly. Stable differs as expected withcmuxandAppIcon.19d70ef4fall have the correct plist keys andAppIcon-Nightly.icns, so the regression was not a checked-in plist patch removal.Icon\rfile pluscom.apple.FinderInfo, andcodesign --verify --deep --strictfails withresource fork, Finder information, or similar detritus not allowed. That metadata makes LaunchServices prefer stale/custom Finder icon state overCFBundleIconFile/CFBundleIconName, which matches the generic-folder prompt.0de573e33(Persist app icon mode on the app bundle (#2884)). It introducedNSWorkspace.shared.setIconinSources/AppIconDockTilePlugin.swift; the nightly/release workflows then smoke-launch the signed app before DMG packaging, so the runtime Dock tile path mutates the artifact.Architecture
Bundle channel identity now has one owner: build-time bundle metadata. The Dock tile plugin can still persist alternate icons for the installed stable app, but NIGHTLY/debug variants and CI smoke launches cannot write Finder custom-icon metadata into app bundles. CI smoke launches cross the Dock plug-in process boundary through the same app defaults domain the plug-in already uses for icon mode. The packaging workflows verify this invariant after the launch smoke and before DMG creation.
Testing
scripts/verify-app-bundle-channel-metadata.sh /tmp/cmux4350-mnt/cmux\ NIGHTLY.app nightlyfails on the current published NIGHTLY DMG because it containsIcon\r.scripts/verify-app-bundle-channel-metadata.sh /Applications/cmux.app stablepasses on the installed stable app.Note
Medium Risk
Touches macOS packaging/smoke-launch and managed-default side-effect application order, which can affect release pipelines and startup behavior, but is largely additive with targeted tests/guards.
Overview
Stops app-bundle icon persistence from mutating non-stable channel bundles. Adds
AppBundleIconPersistencePolicyand wires the Dock tile plugin to only persist Finder icons for the stablecom.cmuxterm.app/cmux.app, with a launch-arg/defaults kill switch.Hardens CI packaging against icon/Finder metadata drift. Smoke-launch now seeds a shared defaults flag and passes
--cmux-disable-bundle-icon-persistence, and bothnightly.ymlandrelease.ymlrun a newverify-app-bundle-channel-metadata.shcheck after smoke launch to assert expected plist name/id/icon keys, required.icns, absence ofIcon\r/com.apple.FinderInfo, and strictcodesignverification.Refines startup side effects and quit-warning gating. Managed settings import now defers live default side effects until
cmuxAppapplies language/appearance, and quit confirmation logic is centralized viaQuitWarningSettings.shouldShowConfirmationto avoid double prompts; tests expand coverage for the new policy, deferred side effects, and socket autodiscovery robustness.Reviewed by Cursor Bugbot for commit 5e4418a. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Locks bundle icon persistence to the stable app and verifies app-bundle icon metadata during packaging; also respects the quit warning in tagged DEV builds. NIGHTLY/debug builds stay codesign-clean and avoid the generic-folder icon prompt. Fixes #4350.
com.cmuxterm.app/cmux.appviaAppBundleIconPersistencePolicy; mirror--cmux-disable-bundle-icon-persistenceto shared defaults at startup, seed it inscripts/smoke-launch-macos-app.sh, and initialize this flag before replaying deferred settings side effects.nightly.ymlandrelease.ymlrunscripts/verify-app-bundle-channel-metadata.shto validate plist name/id/icon keys, required.icns, absence ofIcon\r/com.apple.FinderInfo, and strictcodesign.QuitWarningSettings.shouldShowConfirmation.Written for commit 5e4418a. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Bug Fixes
New Features
Refactor
Tests