Skip to content

Propagate errors in macOS FMA install scripts - #50198

Merged
allenhouchins merged 3 commits into
mainfrom
fix-50056-fma-install-scripts-ignore-errors
Jul 30, 2026
Merged

Propagate errors in macOS FMA install scripts#50198
allenhouchins merged 3 commits into
mainfrom
fix-50056-fma-install-scripts-ignore-errors

Conversation

@cdcme

@cdcme cdcme commented Jul 30, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #50056

Summary

macOS FMA install scripts never checked the exit code of the install command (installer -pkg / cp -R) — the script's last statement is always relaunch_application, which exits 0 — so a failed install exited 0 and Fleet reported it installed.

Generated scripts. The generator now propagates failure: both installer -pkg variants end with || exit $?, and the cp -R path exits non-zero on a failed copy, removes the partial copy (so a failed fresh install isn't inventoried as the new version), and restores the app it moved aside. Regenerated outputs/ for non-frozen generated apps are produced by the ingest-maintained-apps job, so they aren't committed here.

Custom scripts. 9 of the 18 custom input scripts had the same bug and are fixed with the same pattern: Google Chrome, Zoom, Microsoft Edge, GitHub Desktop, Webex, Cycling '74 Max, Pd, Grammarly Desktop, and P4V. The DMG-based ones also now fail before removing/moving the existing app when the mount or staging copy fails, so a bad download can't leave a host with nothing. Their outputs/*/darwin.json are updated in the same commit (script content + recomputed 8-char sha256 ref, versions untouched), following the precedent of #49033. Docker Desktop (set -euo pipefail), 1Password/Slack/LogiTune (installer is the last statement), and the rest already propagated errors.

Frozen apps. The ingest job never rewrites frozen outputs, so the 10 frozen apps with generated scripts (adobe-acrobat-pro, comet, evernote, firealpaca, keeper-password-manager, nvidia-geforce-now, pritunl, vnc-viewer, wins, worksheet-crafter) had the fix applied directly to their published darwin.json scripts — the exact text the current generator would emit, with pinned versions/URLs/hashes untouched. The 11th frozen app (logi-options+) uses a custom script that was already correct and in sync.

Checklist for submitter

  • Changes file added for user-visible changes in changes/ (changes/50056-fma-install-scripts-ignore-errors).
  • Untrusted data interpolated into shell scripts is validated against shell metacharacters. (No new untrusted interpolation: the guard reuses the same curated cask-derived name the adjacent lines already interpolate.)

Testing

  • Added/updated automated tests (three generator tests: pkg, pkg-with-choices, cp-R restore — the last now pins the exact emitted block).
  • All 19 updated output manifests validated: embedded scripts pass bash -n, refs match sha256(script)[:8], refs map stays key-sorted like Go's encoder.
  • QA'd all new/changed functionality manually.

Summary by CodeRabbit

  • Bug Fixes
    • macOS Fleet-maintained app installations now fail fast when installers, DMG extraction/mounting, or app copy steps error.
    • If an upgrade fails, the system removes any partial app and restores the previously installed version when available.
    • Improved robustness during app staging/copying, including safer handling of paths with spaces or special characters.
  • Tests
    • Added unit coverage to verify installer failure propagation and rollback behavior.
  • Documentation
    • Clarified that the install-script error handling applies to both generated and custom scripts, including already-published frozen apps.

Copilot AI review requested due to automatic review settings July 30, 2026 00:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

  • Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.

Pull request overview

Fixes macOS Fleet-maintained app (FMA) install-script generation so install failures don’t get masked by a trailing relaunch_application that exits 0, ensuring Fleet reports failed installs as failures.

Changes:

  • Update the Homebrew macOS install-script generator to propagate failures from installer -pkg and from the final cp -R app install step (including restore-on-failure behavior for the cp -R path).
  • Remove the now-unused scriptBuilder.Copy helper.
  • Add generator tests covering pkg, pkg-with-choices, and app copy failure-propagation behavior.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
ee/maintained-apps/ingesters/homebrew/scripts.go Adjusts generated bash to exit non-zero on install failures and restore apps on failed copy installs.
ee/maintained-apps/ingesters/homebrew/scripts_test.go Adds regression tests asserting failure propagation / restore snippets are present in generated scripts.
changes/50056-fma-install-scripts-ignore-errors User-visible change note (content excluded from review).
Files excluded by content exclusion policy (1)
  • changes/50056-fma-install-scripts-ignore-errors
Comments suppressed due to low confidence (1)

ee/maintained-apps/ingesters/homebrew/scripts.go:58

  • The cp -R failure path always exits with status 1, which loses the real exit code from cp/sudo. If this fails in the field, preserving the original non-zero status can make diagnosing failures easier (and avoids masking distinctions like permission vs. missing source).
		sudo rm -rf "$APPDIR/%[1]s"
		sudo mv "$TMPDIR/%[1]s.bkp" "$APPDIR/%[1]s"
	fi
	exit 1
fi`, appPath)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ee/maintained-apps/ingesters/homebrew/scripts.go
Comment thread ee/maintained-apps/ingesters/homebrew/scripts.go Outdated
@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.10%. Comparing base (bf95fda) to head (ae5203d).
⚠️ Report is 27 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #50198      +/-   ##
==========================================
+ Coverage   68.08%   68.10%   +0.02%     
==========================================
  Files        3936     3936              
  Lines      250690   250927     +237     
  Branches    13437    13437              
==========================================
+ Hits       170687   170905     +218     
+ Misses      64690    64687       -3     
- Partials    15313    15335      +22     
Flag Coverage Δ
backend 69.44% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

Copilot AI review requested due to automatic review settings July 30, 2026 01:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

  • Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated no new comments.

Files excluded by content exclusion policy (1)
  • changes/50056-fma-install-scripts-ignore-errors
Comments suppressed due to low confidence (1)

ee/maintained-apps/ingesters/homebrew/scripts_test.go:99

  • This assertion is too broad: "exit 1" will also match the DMG extraction guard (... || exit 1), so this test could pass even if the new copy-failure/restore block (with its own exit 1) is missing. Make the match specific to the restore block (e.g. include the following fi).
	require.Contains(t, script, `sudo mv "$APPDIR/Foo.app" "$TMPDIR/Foo.app.bkp" || exit $?`)
	require.Contains(t, script, `if ! sudo cp -R "$TMPDIR/Foo.app" "$APPDIR"; then`)
	require.Contains(t, script, `sudo mv "$TMPDIR/Foo.app.bkp" "$APPDIR/Foo.app"`)
	require.Contains(t, script, "exit 1")
}

@cdcme
cdcme marked this pull request as ready for review July 30, 2026 12:27
@cdcme
cdcme requested a review from a team as a code owner July 30, 2026 12:28
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Generated macOS install scripts now propagate failures from package installers, extraction, mounting, and application-copy operations. Existing applications are backed up conditionally, partial copies are removed, and previous versions are restored after failed replacements. Published app metadata references updated scripts, with tests covering package installs, choice changes, quoted paths, and application rollback. The changelog identifies the affected script categories.

Possibly related issues

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed It clearly states the main change: propagating errors in macOS FMA install scripts.
Description check ✅ Passed It follows the template with related issue, summary, checklist, and testing sections.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-50056-fma-install-scripts-ignore-errors

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 `@ee/maintained-apps/ingesters/homebrew/scripts_test.go`:
- Around line 50-51: Strengthen the assertions in
ee/maintained-apps/ingesters/homebrew/scripts_test.go at lines 50-51, 72-74, and
94-98: assert relaunch_application follows the guarded installer command;
validate one complete choices-based installer command using a pkg filename with
spaces; and assert partial-target removal, restoration, then exit 1 occur in
order within the failed-copy branch, using index comparisons or complete
command-block matching rather than independent fragments.

In `@ee/maintained-apps/ingesters/homebrew/scripts.go`:
- Around line 48-57: Update the replacement script generated by the app-install
flow around the appPath backup logic to use a fresh, non-existing backup path
for every replacement. Ensure the same unique path is used by the failure
restore branch, preventing mv from nesting an existing backup and restoring the
original app layout correctly.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 38a36a0b-5b81-46e8-9d33-82134f9ea194

📥 Commits

Reviewing files that changed from the base of the PR and between bf95fda and e68ea49.

📒 Files selected for processing (3)
  • changes/50056-fma-install-scripts-ignore-errors
  • ee/maintained-apps/ingesters/homebrew/scripts.go
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go

Comment on lines +50 to +51
// relaunch still runs, but only after the install command's exit code is checked.
require.Contains(t, script, "relaunch_application 'com.example.Foo'")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert the failure-flow structure, not independent fragments.

These checks can all pass if commands are reordered or emitted outside the intended failure branch. Compare indices or assert complete command blocks.

  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L50-L51: assert relaunch_application occurs after the guarded installer command.
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L72-L74: assert one complete choices-based installer command, using a pkg filename containing spaces.
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L94-L98: assert partial-target removal, restoration, and exit 1 occur in that order inside the failed-copy branch.
📍 Affects 1 file
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L50-L51 (this comment)
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L72-L74
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go#L94-L98
🤖 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 `@ee/maintained-apps/ingesters/homebrew/scripts_test.go` around lines 50 - 51,
Strengthen the assertions in
ee/maintained-apps/ingesters/homebrew/scripts_test.go at lines 50-51, 72-74, and
94-98: assert relaunch_application follows the guarded installer command;
validate one complete choices-based installer command using a pkg filename with
spaces; and assert partial-target removal, restoration, then exit 1 occur in
order within the failed-copy branch, using index comparisons or complete
command-block matching rather than independent fragments.

Comment on lines 48 to +57
sb.Writef(`if [ -d "$APPDIR/%[1]s" ]; then
sudo mv "$APPDIR/%[1]s" "$TMPDIR/%[1]s.bkp"
sudo mv "$APPDIR/%[1]s" "$TMPDIR/%[1]s.bkp" || exit $?
fi`, appPath)
sb.Writef(`if ! sudo cp -R "$TMPDIR/%[1]s" "$APPDIR"; then
# restore the previous version so a failed install doesn't leave the host with nothing
if [ -d "$TMPDIR/%[1]s.bkp" ]; then
sudo rm -rf "$APPDIR/%[1]s"
sudo mv "$TMPDIR/%[1]s.bkp" "$APPDIR/%[1]s"
fi
exit 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use a fresh backup path for each replacement.

The successful path leaves "$TMPDIR/<app>.bkp" behind. Reusing that TMPDIR makes mv nest the existing app inside the prior backup; a later restore then recreates /Applications/<app> as a nested directory instead of the original app. Generate a unique backup path (or safely clean a controlled one) and use it consistently for restore.

🤖 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 `@ee/maintained-apps/ingesters/homebrew/scripts.go` around lines 48 - 57,
Update the replacement script generated by the app-install flow around the
appPath backup logic to use a fresh, non-existing backup path for every
replacement. Ensure the same unique path is used by the failure restore branch,
preventing mv from nesting an existing backup and restoring the original app
layout correctly.

Copilot AI review requested due to automatic review settings July 30, 2026 16:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

  • Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.

Pull request overview

Copilot reviewed 30 out of 31 changed files in this pull request and generated no new comments.

Files excluded by content exclusion policy (1)
  • changes/50056-fma-install-scripts-ignore-errors

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🤖 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 `@ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh`:
- Around line 74-79: Update the Grammarly installation flow around the sudo cp
failure branch to move the existing Grammarly Desktop.app to a backup location
before replacing it, then restore that backup after removing the partial copy
when installation fails. Preserve the current failure message and exit behavior,
and clean up the backup after a successful replacement.

In `@ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh`:
- Around line 92-97: Update the failed-copy branch of the Microsoft Edge
installation flow to restore $TMPDIR/Microsoft Edge.app.bkp back to
$APPDIR/Microsoft Edge.app after removing the partial copy and before exiting.
Preserve the existing failure message and exit status, and only perform the
restore when the backup exists.

In `@ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json`:
- Line 19: Guard each archive extraction before proceeding: in
ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json at lines 19-19, check
the DMG copy and detach operations and exit on failure; in
ee/maintained-apps/outputs/comet/darwin.json at lines 19-19 and
ee/maintained-apps/outputs/evernote/darwin.json at lines 19-19, check the DMG
copy before moving or replacing the existing application; in
ee/maintained-apps/outputs/wins/darwin.json at lines 20-20, check unzip before
copying Wins.app.

In `@ee/maintained-apps/outputs/firealpaca/darwin.json`:
- Line 19: Update the failed-copy rollback in the generated FireAlpaca installer
script so the backup restoration command is checked explicitly. If moving
FireAlpaca.app.bkp back to APPDIR fails, report the restoration error and exit
nonzero rather than continuing as though rollback succeeded; preserve the
existing cleanup and successful restoration behavior.
- Line 19: Make rollback restoration mandatory and checked in the installation
failure paths: in ee/maintained-apps/outputs/firealpaca/darwin.json:19-19,
ee/maintained-apps/outputs/github/darwin.json:20-20,
ee/maintained-apps/outputs/keeper-password-manager/darwin.json:20-20,
ee/maintained-apps/outputs/nvidia-geforce-now/darwin.json:20-20, and
ee/maintained-apps/outputs/pd/darwin.json:19-19, check the backup-app mv
operation and fail explicitly if restoration fails. In
ee/maintained-apps/outputs/microsoft-edge/darwin.json:19-20, create a per-run
backup before replacement and check its restoration in the same failure path;
preserve removal of the partial replacement before attempting restoration.

In `@ee/maintained-apps/outputs/grammarly-desktop/darwin.json`:
- Line 20: Update the install flow around quit_application and the existing
Grammarly Desktop.app removal to move the current app to a temporary backup
instead of deleting it. If copying the replacement fails, remove the partial app
and restore the backup; delete the backup only after a successful copy,
preserving the existing behavior when no prior app exists.

In `@ee/maintained-apps/outputs/keeper-password-manager/darwin.json`:
- Line 20: The failure path in the installation block must verify restoration of
“Keeper Password Manager.app.bkp” after a failed replacement copy. Update the
rollback logic following the failed `sudo cp -R` so a failed `sudo mv`
restoration is detected and surfaced with an error message and nonzero exit
status, while preserving the existing cleanup and successful restoration
behavior.

In `@ee/maintained-apps/outputs/nvidia-geforce-now/darwin.json`:
- Line 20: Update the failed-copy rollback block after the sudo cp command to
check the status of restoring GeForceNOW.app.bkp via sudo mv. If restoration
fails, report the failure and exit nonzero; otherwise preserve the existing
rollback and exit behavior.

In `@ee/maintained-apps/outputs/p4v/darwin.json`:
- Line 19: Update the installation loop in the generated script to validate that
the required p4v.app bundle exists at MOUNT_POINT before copying applications.
If it is missing, detach the mounted DMG, print an installation failure message,
and exit nonzero; preserve the existing handling for optional p4merge.app and
p4admin.app bundles.
- Line 19: Update the installation loop for p4v.app, p4merge.app, and
p4admin.app to back up each existing application bundle before removing it, then
restore that backup if ditto fails. Preserve the existing cleanup of partial
copies and ensure successful installations remove the backup only after the
replacement completes.

In `@ee/maintained-apps/outputs/pd/darwin.json`:
- Line 19: Update the failed-copy rollback block around the sudo mv command
restoring $TMPDIR/$APP_NAME.bkp so its failure is checked and propagated instead
of ignored. Preserve the existing cleanup and exit behavior, but ensure the
script exits unsuccessfully when restoration of the previous Pd bundle fails.

In `@ee/maintained-apps/outputs/pritunl/darwin.json`:
- Line 20: Update the extraction flow before quit_and_track_application and
installer so unzip failure immediately exits with its status, then verify the
expected Pritunl.pkg exists in the current TMPDIR extraction output before
invoking installer. Do not proceed to installation or relaunch when extraction
fails or the package is missing.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 484f55b9-eeca-4715-94fc-202c9dd72f77

📥 Commits

Reviewing files that changed from the base of the PR and between e68ea49 and ae5203d.

📒 Files selected for processing (31)
  • changes/50056-fma-install-scripts-ignore-errors
  • ee/maintained-apps/ingesters/homebrew/scripts.go
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go
  • ee/maintained-apps/inputs/homebrew/scripts/cycling74-max-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/github-desktop-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/google_chrome_install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/pd-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/webex_install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/zoom_install.sh
  • ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json
  • ee/maintained-apps/outputs/comet/darwin.json
  • ee/maintained-apps/outputs/cycling74-max/darwin.json
  • ee/maintained-apps/outputs/evernote/darwin.json
  • ee/maintained-apps/outputs/firealpaca/darwin.json
  • ee/maintained-apps/outputs/github/darwin.json
  • ee/maintained-apps/outputs/google-chrome/darwin.json
  • ee/maintained-apps/outputs/grammarly-desktop/darwin.json
  • ee/maintained-apps/outputs/keeper-password-manager/darwin.json
  • ee/maintained-apps/outputs/microsoft-edge/darwin.json
  • ee/maintained-apps/outputs/nvidia-geforce-now/darwin.json
  • ee/maintained-apps/outputs/p4v/darwin.json
  • ee/maintained-apps/outputs/pd/darwin.json
  • ee/maintained-apps/outputs/pritunl/darwin.json
  • ee/maintained-apps/outputs/vnc-viewer/darwin.json
  • ee/maintained-apps/outputs/webex/darwin.json
  • ee/maintained-apps/outputs/wins/darwin.json
  • ee/maintained-apps/outputs/worksheet-crafter/darwin.json
  • ee/maintained-apps/outputs/zoom/darwin.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • changes/50056-fma-install-scripts-ignore-errors

Comment thread ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json
Comment thread ee/maintained-apps/outputs/firealpaca/darwin.json
Comment thread ee/maintained-apps/outputs/grammarly-desktop/darwin.json
Comment thread ee/maintained-apps/outputs/keeper-password-manager/darwin.json
Comment thread ee/maintained-apps/outputs/nvidia-geforce-now/darwin.json
Comment thread ee/maintained-apps/outputs/p4v/darwin.json
Comment thread ee/maintained-apps/outputs/pd/darwin.json
Comment thread ee/maintained-apps/outputs/pritunl/darwin.json
@allenhouchins

Copy link
Copy Markdown
Member

@cdcme thanks for catching this! I updated all the custom install scripts and frozen app scripts to replicate this new behavior too since those don't go through the scripts generator.

Once this has go approval, could you leave the merge up to me? It will regen all of our macOS FMAs so I want to make sure its merged at a time I can quickly respond to any issues.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json

=== Install // 7bd42f17 -> afddc3a7 ===

--- /tmp/old.ZaBUav	2026-07-30 17:04:20.189421407 +0000
+++ /tmp/new.5HxFtk	2026-07-30 17:04:20.189421407 +0000
@@ -101,5 +101,5 @@
 hdiutil detach "$MOUNT_POINT" || true
 # install pkg files
 quit_and_track_application 'com.adobe.Acrobat.Pro'
-sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target / || exit $?
 relaunch_application 'com.adobe.Acrobat.Pro'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/comet/darwin.json

=== Install // af8d196c -> 702b27b8 ===

--- /tmp/old.tLUwKN	2026-07-30 17:04:20.256421745 +0000
+++ /tmp/new.K0ZpW3	2026-07-30 17:04:20.256421745 +0000
@@ -102,7 +102,15 @@
 # copy to the applications folder
 quit_and_track_application 'ai.perplexity.comet'
 if [ -d "$APPDIR/Comet.app" ]; then
-	sudo mv "$APPDIR/Comet.app" "$TMPDIR/Comet.app.bkp"
+	sudo mv "$APPDIR/Comet.app" "$TMPDIR/Comet.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Comet.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Comet.app"
+	if [ -d "$TMPDIR/Comet.app.bkp" ]; then
+		sudo mv "$TMPDIR/Comet.app.bkp" "$APPDIR/Comet.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Comet.app" "$APPDIR"
 relaunch_application 'ai.perplexity.comet'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cycling74-max/darwin.json

=== Install // b553ba8e -> 3c5d2cd6 ===

--- /tmp/old.EcKMVr	2026-07-30 17:04:20.312422027 +0000
+++ /tmp/new.5VZFaA	2026-07-30 17:04:20.312422027 +0000
@@ -101,12 +101,23 @@
 # DMG never mounts, and nothing gets installed.
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
-sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+if ! sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"; then
+	hdiutil detach "$MOUNT_POINT" || true
+	exit 1
+fi
 hdiutil detach "$MOUNT_POINT" || true
 # copy to the applications folder
 quit_and_track_application 'com.cycling74.Max'
 if [ -d "$APPDIR/Max.app" ]; then
-	sudo mv "$APPDIR/Max.app" "$TMPDIR/Max.app.bkp"
+	sudo mv "$APPDIR/Max.app" "$TMPDIR/Max.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Max.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Max.app"
+	if [ -d "$TMPDIR/Max.app.bkp" ]; then
+		sudo mv "$TMPDIR/Max.app.bkp" "$APPDIR/Max.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Max.app" "$APPDIR"
 relaunch_application 'com.cycling74.Max'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/evernote/darwin.json

=== Install // 67a65f7d -> 4cd3103c ===

--- /tmp/old.J8LPa6	2026-07-30 17:04:20.388422410 +0000
+++ /tmp/new.GHEKgr	2026-07-30 17:04:20.388422410 +0000
@@ -102,7 +102,15 @@
 # copy to the applications folder
 quit_and_track_application 'com.evernote.Evernote'
 if [ -d "$APPDIR/Evernote.app" ]; then
-	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp"
+	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Evernote.app"
+	if [ -d "$TMPDIR/Evernote.app.bkp" ]; then
+		sudo mv "$TMPDIR/Evernote.app.bkp" "$APPDIR/Evernote.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"
 relaunch_application 'com.evernote.Evernote'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firealpaca/darwin.json

=== Install // f2cad371 -> a03f6a1f ===

--- /tmp/old.pYPKpv	2026-07-30 17:04:20.458422762 +0000
+++ /tmp/new.a1P4AG	2026-07-30 17:04:20.458422762 +0000
@@ -99,7 +99,15 @@
 # copy to the applications folder
 quit_and_track_application 'com.firealpaca'
 if [ -d "$APPDIR/FireAlpaca.app" ]; then
-	sudo mv "$APPDIR/FireAlpaca.app" "$TMPDIR/FireAlpaca.app.bkp"
+	sudo mv "$APPDIR/FireAlpaca.app" "$TMPDIR/FireAlpaca.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/FireAlpaca.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/FireAlpaca.app"
+	if [ -d "$TMPDIR/FireAlpaca.app.bkp" ]; then
+		sudo mv "$TMPDIR/FireAlpaca.app.bkp" "$APPDIR/FireAlpaca.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/FireAlpaca.app" "$APPDIR"
 relaunch_application 'com.firealpaca'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/github/darwin.json

=== Install // c91ea2b5 -> 7ed6a869 ===

--- /tmp/old.ZjQdVy	2026-07-30 17:04:20.511423029 +0000
+++ /tmp/new.wkgh91	2026-07-30 17:04:20.511423029 +0000
@@ -94,14 +94,22 @@
 }
 
 # Extract with ditto and --noqtn so extracted files do NOT get quarantine.
-ditto -xk --noqtn "$INSTALLER_PATH" "$TMPDIR"
+ditto -xk --noqtn "$INSTALLER_PATH" "$TMPDIR" || exit $?
 
 # copy to the applications folder (do not modify the app bundle after extraction)
 quit_and_track_application 'com.github.GitHubClient'
 if [ -d "$APPDIR/GitHub Desktop.app" ]; then
-  sudo mv "$APPDIR/GitHub Desktop.app" "$TMPDIR/GitHub Desktop.app.bkp"
+  sudo mv "$APPDIR/GitHub Desktop.app" "$TMPDIR/GitHub Desktop.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/GitHub Desktop.app" "$APPDIR"; then
+  # remove the partial copy so a failed install isn't inventoried as the new
+  # version, then restore the previous version if there was one
+  sudo rm -rf "$APPDIR/GitHub Desktop.app"
+  if [ -d "$TMPDIR/GitHub Desktop.app.bkp" ]; then
+    sudo mv "$TMPDIR/GitHub Desktop.app.bkp" "$APPDIR/GitHub Desktop.app"
+  fi
+  exit 1
 fi
-sudo cp -R "$TMPDIR/GitHub Desktop.app" "$APPDIR"
 
 relaunch_application 'com.github.GitHubClient'
 

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-chrome/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/grammarly-desktop/darwin.json

=== Install // df3d0525 -> 8274b7dd ===

--- /tmp/old.rVo5ho	2026-07-30 17:04:20.591423432 +0000
+++ /tmp/new.cNJejc	2026-07-30 17:04:20.591423432 +0000
@@ -46,9 +46,17 @@
 }
 
 # extract contents
+# Fail before the existing app is removed below, so a bad download can't leave
+# the host without a working install.
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
-sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+if ! hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"; then
+	echo "Failed to mount DMG '$INSTALLER_PATH'." >&2
+	exit 1
+fi
+if ! sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"; then
+	hdiutil detach "$MOUNT_POINT" || true
+	exit 1
+fi
 hdiutil detach "$MOUNT_POINT"
 
 # copy to the applications folder
@@ -63,7 +71,12 @@
 
 # Copy Grammarly Installer.app from temp directory to Applications as Grammarly Desktop.app
 if [ -d "$TMPDIR/Grammarly Installer.app" ]; then
-	sudo cp -R "$TMPDIR/Grammarly Installer.app" "$APPDIR/Grammarly Desktop.app"
+	if ! sudo cp -R "$TMPDIR/Grammarly Installer.app" "$APPDIR/Grammarly Desktop.app"; then
+		# remove the partial copy so a failed install isn't inventoried as the new version
+		sudo rm -rf "$APPDIR/Grammarly Desktop.app"
+		echo "Installation failed"
+		exit 1
+	fi
 	echo "Installation verified"
 else
 	echo "Error: Grammarly Installer.app not found in extracted files"

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/keeper-password-manager/darwin.json

=== Install // 7b4bffee -> bd9c8589 ===

--- /tmp/old.ISvFA1	2026-07-30 17:04:20.660423780 +0000
+++ /tmp/new.EafrXR	2026-07-30 17:04:20.661423785 +0000
@@ -102,7 +102,15 @@
 # copy to the applications folder
 quit_and_track_application 'com.keepersecurity.passwordmanager'
 if [ -d "$APPDIR/Keeper Password Manager.app" ]; then
-	sudo mv "$APPDIR/Keeper Password Manager.app" "$TMPDIR/Keeper Password Manager.app.bkp"
+	sudo mv "$APPDIR/Keeper Password Manager.app" "$TMPDIR/Keeper Password Manager.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Keeper Password Manager.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Keeper Password Manager.app"
+	if [ -d "$TMPDIR/Keeper Password Manager.app.bkp" ]; then
+		sudo mv "$TMPDIR/Keeper Password Manager.app.bkp" "$APPDIR/Keeper Password Manager.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Keeper Password Manager.app" "$APPDIR"
 relaunch_application 'com.keepersecurity.passwordmanager'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-edge/darwin.json

=== Install // 81ff19c2 -> 4c051c40 ===

--- /tmp/old.abnxaj	2026-07-30 17:04:20.709424027 +0000
+++ /tmp/new.tuyFl9	2026-07-30 17:04:20.709424027 +0000
@@ -46,9 +46,17 @@
 }
 
 # extract contents
+# Fail before the existing app is removed below, so a bad download can't leave
+# the host without a working install.
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
-sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+if ! hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"; then
+	echo "Failed to mount DMG '$INSTALLER_PATH'." >&2
+	exit 1
+fi
+if ! sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"; then
+	hdiutil detach "$MOUNT_POINT" || true
+	exit 1
+fi
 hdiutil detach "$MOUNT_POINT"
 
 # Clean up any backup files that might exist from previous failed installations
@@ -81,7 +89,12 @@
 fi
 
 # Install the new app
-sudo cp -R "$TMPDIR/Microsoft Edge.app" "$APPDIR"
+if ! sudo cp -R "$TMPDIR/Microsoft Edge.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new version
+	sudo rm -rf "$APPDIR/Microsoft Edge.app"
+	echo "Installation failed"
+	exit 1
+fi
 
 # Verify installation and do final cleanup
 if [ -d "$APPDIR/Microsoft Edge.app" ]; then

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nvidia-geforce-now/darwin.json

=== Install // a9979922 -> 88b8bf1c ===

--- /tmp/old.gb0qtR	2026-07-30 17:04:20.778424375 +0000
+++ /tmp/new.GPNWrF	2026-07-30 17:04:20.778424375 +0000
@@ -102,7 +102,15 @@
 # copy to the applications folder
 quit_and_track_application 'com.nvidia.gfnpc.mall'
 if [ -d "$APPDIR/GeForceNOW.app" ]; then
-	sudo mv "$APPDIR/GeForceNOW.app" "$TMPDIR/GeForceNOW.app.bkp"
+	sudo mv "$APPDIR/GeForceNOW.app" "$TMPDIR/GeForceNOW.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/GeForceNOW.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/GeForceNOW.app"
+	if [ -d "$TMPDIR/GeForceNOW.app.bkp" ]; then
+		sudo mv "$TMPDIR/GeForceNOW.app.bkp" "$APPDIR/GeForceNOW.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/GeForceNOW.app" "$APPDIR"
 relaunch_application 'com.nvidia.gfnpc.mall'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/p4v/darwin.json

=== Install // 7f44eda5 -> 3604c875 ===

--- /tmp/old.j6EV2x	2026-07-30 17:04:20.837424672 +0000
+++ /tmp/new.DfoWCG	2026-07-30 17:04:20.837424672 +0000
@@ -31,13 +31,24 @@
 for app in p4v.app p4merge.app p4admin.app; do
   if [[ -d "$MOUNT_POINT/$app" ]]; then
     rm -rf "$APPDIR/$app" >/dev/null 2>&1 || true
-    ditto "$MOUNT_POINT/$app" "$APPDIR/$app" >/dev/null 2>&1
+    if ! ditto "$MOUNT_POINT/$app" "$APPDIR/$app"; then
+      # remove the partial copy so a failed install isn't inventoried as installed
+      rm -rf "$APPDIR/$app" >/dev/null 2>&1 || true
+      hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
+      echo "failed to install $app"
+      exit 1
+    fi
   fi
 done
 
 # Install p4vc command line binary to /usr/local/bin
 if [[ -f "$MOUNT_POINT/p4vc" ]]; then
-  cp "$MOUNT_POINT/p4vc" /usr/local/bin/p4vc
+  mkdir -p /usr/local/bin
+  if ! cp "$MOUNT_POINT/p4vc" /usr/local/bin/p4vc; then
+    hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
+    echo "failed to install p4vc"
+    exit 1
+  fi
   chmod +x /usr/local/bin/p4vc
   chown root:wheel /usr/local/bin/p4vc
 fi

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pd/darwin.json

=== Install // 8a005b0c -> 2498acb1 ===

--- /tmp/old.oKV6I3	2026-07-30 17:04:20.906425020 +0000
+++ /tmp/new.xVD15p	2026-07-30 17:04:20.906425020 +0000
@@ -100,7 +100,7 @@
 # first, then mount the embedded DMG and copy whichever .app it contains. This
 # keeps the script version-agnostic across Homebrew bumps.
 EXTRACT_DIR=$(mktemp -d /tmp/pd_extract_XXXXXX)
-unzip -q "$INSTALLER_PATH" -d "$EXTRACT_DIR"
+unzip -q "$INSTALLER_PATH" -d "$EXTRACT_DIR" || exit $?
 DMG_PATH=$(find "$EXTRACT_DIR" -maxdepth 2 -name "*.dmg" | head -1)
 if [ -z "$DMG_PATH" ]; then
   echo "No DMG found inside the Pd archive" >&2
@@ -118,8 +118,17 @@
 # copy to the applications folder
 quit_and_track_application 'org.puredata.pd.pd-gui'
 if [ -d "$APPDIR/$APP_NAME" ]; then
-	sudo mv "$APPDIR/$APP_NAME" "$TMPDIR/$APP_NAME.bkp"
+	sudo mv "$APPDIR/$APP_NAME" "$TMPDIR/$APP_NAME.bkp" || exit $?
+fi
+if ! sudo cp -R "$APP_BUNDLE" "$APPDIR"; then
+  # remove the partial copy so a failed install isn't inventoried as the new
+  # version, then restore the previous version if there was one
+  sudo rm -rf "$APPDIR/$APP_NAME"
+  if [ -d "$TMPDIR/$APP_NAME.bkp" ]; then
+    sudo mv "$TMPDIR/$APP_NAME.bkp" "$APPDIR/$APP_NAME"
+  fi
+  hdiutil detach "$MOUNT_POINT" || true
+  exit 1
 fi
-sudo cp -R "$APP_BUNDLE" "$APPDIR"
 hdiutil detach "$MOUNT_POINT" || true
 relaunch_application 'org.puredata.pd.pd-gui'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/darwin.json

=== Install // 50fa15ff -> d5a06183 ===

--- /tmp/old.bPxG7z	2026-07-30 17:04:20.964425312 +0000
+++ /tmp/new.RLWfbb	2026-07-30 17:04:20.964425312 +0000
@@ -98,5 +98,5 @@
 unzip "$INSTALLER_PATH" -d "$TMPDIR"
 # install pkg files
 quit_and_track_application 'com.electron.pritunl'
-sudo installer -pkg "$TMPDIR/Pritunl.pkg" -target /
+sudo installer -pkg "$TMPDIR/Pritunl.pkg" -target / || exit $?
 relaunch_application 'com.electron.pritunl'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/vnc-viewer/darwin.json

=== Install // 932783c1 -> f79954c2 ===

--- /tmp/old.jG4Mc6	2026-07-30 17:04:21.047425731 +0000
+++ /tmp/new.bCZt35	2026-07-30 17:04:21.047425731 +0000
@@ -96,7 +96,7 @@
 
 # install pkg files
 quit_and_track_application 'com.realvnc.rvncconnect'
-sudo installer -pkg "$TMPDIR/RealVNC-Connect-Viewer-8.4.2-MacOSX-universal.pkg" -target /
+sudo installer -pkg "$TMPDIR/RealVNC-Connect-Viewer-8.4.2-MacOSX-universal.pkg" -target / || exit $?
 relaunch_application 'com.realvnc.rvncconnect'
 # Remove the legacy VNC Viewer (pre-rebrand bundle id com.realvnc.vncviewer) so the rebranded
 # RealVNC Connect Viewer supersedes it and the patch policy converges.

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/webex/darwin.json

=== Install // d105863f -> 8ff3811b ===

--- /tmp/old.IyoDuM	2026-07-30 17:04:21.100425998 +0000
+++ /tmp/new.66tgW7	2026-07-30 17:04:21.100425998 +0000
@@ -115,13 +115,24 @@
 # extract contents
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
-sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+if ! sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"; then
+	hdiutil detach "$MOUNT_POINT" || true
+	exit 1
+fi
 hdiutil detach "$MOUNT_POINT" || true
 # copy to the applications folder
 quit_and_track_application 'Cisco-Systems.Spark'
 if [ -d "$APPDIR/Webex.app" ]; then
-	sudo mv "$APPDIR/Webex.app" "$TMPDIR/Webex.app.bkp"
+	sudo mv "$APPDIR/Webex.app" "$TMPDIR/Webex.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Webex.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Webex.app"
+	if [ -d "$TMPDIR/Webex.app.bkp" ]; then
+		sudo mv "$TMPDIR/Webex.app.bkp" "$APPDIR/Webex.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Webex.app" "$APPDIR"
 remove_stale_upgrade_bundles
 relaunch_application 'Cisco-Systems.Spark'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/wins/darwin.json

=== Install // 16e109de -> 9d1f8a20 ===

--- /tmp/old.SI3fk5	2026-07-30 17:04:21.178426391 +0000
+++ /tmp/new.AYlG5q	2026-07-30 17:04:21.178426391 +0000
@@ -99,7 +99,15 @@
 # copy to the applications folder
 quit_and_track_application 'cools.wins.main'
 if [ -d "$APPDIR/Wins.app" ]; then
-	sudo mv "$APPDIR/Wins.app" "$TMPDIR/Wins.app.bkp"
+	sudo mv "$APPDIR/Wins.app" "$TMPDIR/Wins.app.bkp" || exit $?
+fi
+if ! sudo cp -R "$TMPDIR/Wins.app" "$APPDIR"; then
+	# remove the partial copy so a failed install isn't inventoried as the new
+	# version, then restore the previous version if there was one
+	sudo rm -rf "$APPDIR/Wins.app"
+	if [ -d "$TMPDIR/Wins.app.bkp" ]; then
+		sudo mv "$TMPDIR/Wins.app.bkp" "$APPDIR/Wins.app"
+	fi
+	exit 1
 fi
-sudo cp -R "$TMPDIR/Wins.app" "$APPDIR"
 relaunch_application 'cools.wins.main'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/worksheet-crafter/darwin.json

=== Install // 545289c7 -> aa497eb5 ===

--- /tmp/old.TUIx9t	2026-07-30 17:04:21.255426779 +0000
+++ /tmp/new.VWWSjl	2026-07-30 17:04:21.257426789 +0000
@@ -96,5 +96,5 @@
 
 # install pkg files
 quit_and_track_application 'com.SchoolCraft.WillBeReplacedByQMake'
-sudo installer -pkg "$TMPDIR/worksheet-crafter_2026.2.4.pkg" -target /
+sudo installer -pkg "$TMPDIR/worksheet-crafter_2026.2.4.pkg" -target / || exit $?
 relaunch_application 'com.SchoolCraft.WillBeReplacedByQMake'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zoom/darwin.json

=== Install // ab84b572 -> 63cd9eb1 ===

--- /tmp/old.d5yONl	2026-07-30 17:04:21.313427071 +0000
+++ /tmp/new.ThbHUo	2026-07-30 17:04:21.313427071 +0000
@@ -54,7 +54,7 @@
   quit_application 'us.zoom.xos' "$CONSOLE_USER"
 fi
 
-installer -pkg "$INSTALLER_PATH" -target /
+installer -pkg "$INSTALLER_PATH" -target / || exit $?
 
 # Restart Zoom if it was running before installation
 if [[ "$ZOOM_WAS_RUNNING" == "true" ]]; then

=== Uninstall Script (no changes) ===

@cdcme

cdcme commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

@allenhouchins Yes, absolutely 👍

@allenhouchins
allenhouchins merged commit 0594f65 into main Jul 30, 2026
54 checks passed
@allenhouchins
allenhouchins deleted the fix-50056-fma-install-scripts-ignore-errors branch July 30, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FMA install scripts for macOS apps ignore some errors

4 participants