Skip to content

Update Fleet-maintained apps - #45503

Merged
allenhouchins merged 5 commits into
mainfrom
fma-2605141636
May 14, 2026
Merged

Update Fleet-maintained apps#45503
allenhouchins merged 5 commits into
mainfrom
fma-2605141636

Conversation

@fleet-release

@fleet-release fleet-release commented May 14, 2026

Copy link
Copy Markdown
Contributor

Automated ingestion of latest Fleet-maintained app data.

Summary by CodeRabbit

  • Chores
    • Bumped installer metadata (version, download URLs, checksums, patch checks) for multiple maintained apps to new releases.
    • Adjusted Homebrew ingester logic to handle Camtasia year-prefixed versions.
  • Bug Fixes
    • macOS uninstall cleanup updated for Camtasia to remove an additional shared-filelist and preserve user files by moving them to Trash.
    • Windows Docker install/uninstall improved: per-user silent install, registry polling for completion, and more robust registry lookup/error handling.
  • Tests
    • Added unit tests for Camtasia version transformation.

Review Change Stack

Generated automatically with cmd/maintained-apps.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

=== Install Script (no changes) ===
=== Uninstall // 4603b920 -> 007deada ===

--- /tmp/old.ltWdgz	2026-05-14 16:39:32.668512504 +0000
+++ /tmp/new.UHoLg4	2026-05-14 16:39:32.668512504 +0000
@@ -29,7 +29,7 @@
 
 sudo rm -rf "$APPDIR/Camtasia.app"
 trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
-trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.techsmith.camtasia*'

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

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

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR updates maintained-app metadata for many applications by bumping versions, adjusting SQL patched-version checks, updating installer URLs, and replacing SHA256 checksums. Docker Desktop (Windows) metadata and referenced PowerShell scripts now perform per-user installs with HKCU polling and prefer HKCU when locating the uninstall registry entry; corresponding Winget scripts were updated. Camtasia’s darwin entry was bumped to 2026.1.0 and its uninstall script reference and embedded uninstall sharedfilelist glob were updated; a Homebrew uninstall script and an uninstall_script_path were also added, and the Camtasia version transformer gained a regex guard with unit tests.

Possibly related PRs

  • fleetdm/fleet#45010: Also modifies the Cursor macOS manifest (ee/maintained-apps/outputs/cursor/darwin.json) by bumping version, patched-query, installer URL, and sha256.
  • fleetdm/fleet#45334: Updates Docker Desktop Windows maintained-app metadata and embedded PowerShell scripts to align installer/uninstaller behavior for Docker Desktop.
  • fleetdm/fleet#45026: Also updates Granola macOS maintained-app metadata (version bump and corresponding installer/sha256 changes).
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal ('Automated ingestion of latest Fleet-maintained app data') but does not follow the repository template, missing checklist items like changes files, testing, and validation. Add a completed checklist from the description template indicating whether changes files were added, tests were performed, and validation checks were completed.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Update Fleet-maintained apps' directly relates to the main objective of updating version information and scripts for multiple maintained applications across the codebase.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 fma-2605141636

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

@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: 3

🤖 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/outputs/camtasia/darwin.json`:
- Line 19: The uninstall script's shared filelist removal only targets
"com.techsmith.camtasia2026.sfl*" so older Camtasia 26.x files
("com.techsmith.camtasia26.sfl*") are left behind; update the call(s) that
invoke trash for the com.apple.LSSharedFileList.ApplicationRecentDocuments
pattern (the line that currently contains "com.techsmith.camtasia2026.sfl*") to
also remove the "com.techsmith.camtasia26.sfl*" pattern (either by adding a
second trash invocation with that pattern or using a glob/brace pattern to match
both) so the trash() function covers both version patterns.
- Line 4: The version field "202026.1.0" is incorrect and must match the
installer_url and uninstall pattern; update the version property in darwin.json
from "202026.1.0" to "2026.1.0" so that the version_compare() logic in the
patched query, the installer_url that contains "2026.1.0", and the uninstall
script pattern referencing "camtasia2026" are all consistent.

In `@ee/maintained-apps/outputs/splashtop-business/darwin.json`:
- Line 12: The sha256 field in
ee/maintained-apps/outputs/splashtop-business/darwin.json contains a checksum
that failed verification and the actual hash was empty; re-download the
Splashtop Business installer, compute its SHA-256 locally and replace the
"sha256" value with the correct hash in that JSON, and also audit the
download-and-hash workflow to ensure the downloader writes the file and the
checksum routine returns a non-empty string (handle HTTP redirects, failed
writes, and verify the code path that populates the "sha256" field so it doesn't
accept empty results).
🪄 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

Run ID: 01a61b9d-bd41-4346-89ce-194ecdfcbac0

📥 Commits

Reviewing files that changed from the base of the PR and between 5fac791 and 34b49d0.

📒 Files selected for processing (14)
  • ee/maintained-apps/outputs/camtasia/darwin.json
  • ee/maintained-apps/outputs/coteditor/darwin.json
  • ee/maintained-apps/outputs/cursor/darwin.json
  • ee/maintained-apps/outputs/docker/windows.json
  • ee/maintained-apps/outputs/granola/darwin.json
  • ee/maintained-apps/outputs/granola/windows.json
  • ee/maintained-apps/outputs/miro/darwin.json
  • ee/maintained-apps/outputs/nordvpn/darwin.json
  • ee/maintained-apps/outputs/ollama/darwin.json
  • ee/maintained-apps/outputs/opera/darwin.json
  • ee/maintained-apps/outputs/postman/darwin.json
  • ee/maintained-apps/outputs/raycast/darwin.json
  • ee/maintained-apps/outputs/snagit/darwin.json
  • ee/maintained-apps/outputs/splashtop-business/darwin.json

Comment thread ee/maintained-apps/outputs/camtasia/darwin.json Outdated
Comment thread ee/maintained-apps/outputs/camtasia/darwin.json Outdated
"install_script_ref": "4013dae8",
"uninstall_script_ref": "217e1dc3",
"sha256": "ca7921340792f96cf6fb4999886b9957b2755fe11ff20457f5378d56e63101c9",
"sha256": "a06c5616bc8c6a4f1c238d2fb22d71da0c1e8ded2fc621f2cab9ddddaca90d34",

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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify Splashtop Business installer URL and SHA256

SPLASHTOP_URL="https://d17kmd0va0f0mp.cloudfront.net/macclient/STB/Splashtop_Business_Mac_INSTALLER_v3.8.4.0.dmg"
EXPECTED_SHA256="a06c5616bc8c6a4f1c238d2fb22d71da0c1e8ded2fc621f2cab9ddddaca90d34"

echo "Checking Splashtop Business installer URL accessibility..."
HTTP_CODE=$(curl -I -s -o /dev/null -w "%{http_code}" "$SPLASHTOP_URL")
echo "HTTP Status: $HTTP_CODE"

if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
  echo "Downloading Splashtop Business installer to verify SHA256..."
  TEMP_FILE=$(mktemp)
  curl -s -L "$SPLASHTOP_URL" -o "$TEMP_FILE"
  
  ACTUAL_SHA256=$(sha256sum "$TEMP_FILE" 2>/dev/null | awk '{print $1}' || shasum -a 256 "$TEMP_FILE" | awk '{print $1}')
  
  echo "Expected: $EXPECTED_SHA256"
  echo "Actual:   $ACTUAL_SHA256"
  
  if [ "$EXPECTED_SHA256" = "$ACTUAL_SHA256" ]; then
    echo "✓ SHA256 matches"
  else
    echo "✗ SHA256 mismatch!"
  fi
  
  rm -f "$TEMP_FILE"
else
  echo "✗ URL not accessible"
fi

Repository: fleetdm/fleet

Length of output: 299


Investigate failed SHA256 verification for Splashtop Business installer.

The installer URL is accessible (HTTP 200), but the SHA256 checksum verification failed with an empty actual hash. This indicates a potential issue with the installer file integrity or download process. The checksum in the file cannot be validated with the current setup.

🤖 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/outputs/splashtop-business/darwin.json` at line 12, The
sha256 field in ee/maintained-apps/outputs/splashtop-business/darwin.json
contains a checksum that failed verification and the actual hash was empty;
re-download the Splashtop Business installer, compute its SHA-256 locally and
replace the "sha256" value with the correct hash in that JSON, and also audit
the download-and-hash workflow to ensure the downloader writes the file and the
checksum routine returns a non-empty string (handle HTTP redirects, failed
writes, and verify the code path that populates the "sha256" field so it doesn't
accept empty results).

Make Docker Desktop Windows installers robust for per-user installs: install script now runs the installer with --user and --accept-license (to avoid admin/all-user hangs on Windows Server) and polls the HKCU Uninstall key for up to 4 minutes to detect completion. Uninstall script now checks HKCU first and then HKLM (supports per-user and all-user installs), discovers the uninstall command, and preserves existing exit-code handling. Update windows.json to reference the new install/uninstall script revisions and their corresponding refs.
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

=== Install Script (no changes) ===
=== Uninstall // 4603b920 -> 007deada ===

--- /tmp/old.tpevVw	2026-05-14 18:13:38.303821743 +0000
+++ /tmp/new.WeZfgl	2026-05-14 18:13:38.303821743 +0000
@@ -29,7 +29,7 @@
 
 sudo rm -rf "$APPDIR/Camtasia.app"
 trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
-trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.techsmith.camtasia*'

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

=== Install // f938db79 -> b06042dd ===

--- /tmp/old.phg55o	2026-05-14 18:13:38.426820462 +0000
+++ /tmp/new.t91j1Q	2026-05-14 18:13:38.426820462 +0000
@@ -4,26 +4,31 @@
 $exeFilePath = "${env:INSTALLER_PATH}"
 
 try {
+    # Docker Desktop 4.72+ added a per-user vs all-user install choice for
+    # Windows. All-user silent installs hang on Windows Server runners
+    # (Docker Desktop is not officially supported on Windows Server). Install
+    # per-user with --user instead: no admin needed, target is
+    # %LOCALAPPDATA%\Programs\DockerDesktop, and uninstall info is written to
+    # HKCU. --accept-license suppresses the subscription agreement prompt.
+    Start-Process -FilePath "$exeFilePath" -ArgumentList "install","--user","--accept-license","--quiet" | Out-Null
 
-# Add argument to install silently
-# Argument to make install silent depends on installer,
-# each installer might use different argument (usually it's "/S" or "/s")
-$processOptions = @{
-  FilePath = "$exeFilePath"
-  ArgumentList = "install --quiet"
-  PassThru = $true
-  Wait = $true
-}
-    
-# Start process and track exit code
-$process = Start-Process @processOptions
-$exitCode = $process.ExitCode
-
-# Prints the exit code
-Write-Host "Install exit code: $exitCode"
-Exit $exitCode
+    # The installer process can keep running for several minutes after the
+    # app is registered with Windows. Poll the HKCU uninstall key (osquery's
+    # programs table reads both HKLM and HKU) to detect when the core install
+    # has completed, rather than blocking on Start-Process -Wait.
+    $registryKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop"
+    $deadline = (Get-Date).AddMinutes(4)
+    while ((Get-Date) -lt $deadline) {
+        if (Get-ItemProperty -Path $registryKey -ErrorAction SilentlyContinue) {
+            Write-Host "Docker Desktop registered in HKCU."
+            Exit 0
+        }
+        Start-Sleep -Seconds 10
+    }
 
+    Write-Host "Docker Desktop did not register within timeout."
+    Exit 1
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall // 000be0a3 -> 0b74af50 ===

--- /tmp/old.d3OnU0	2026-05-14 18:13:38.442820295 +0000
+++ /tmp/new.CysNyY	2026-05-14 18:13:38.443820285 +0000
@@ -1,14 +1,29 @@
 # Define acceptable/expected exit codes
 $ExpectedExitCodes = @(0, 19)
 
-# Uninstall Registry Key
-$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+# Docker Desktop can be installed per-user (HKCU, %LOCALAPPDATA%) or
+# all-users (HKLM, C:\Program Files). Check HKCU first, then HKLM.
+$registryPaths = @(
+    'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop',
+    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+)
 
 # Initialize exit code
 $exitCode = 0
 
 try {
-    $key = Get-ItemProperty -Path $machineKey -ErrorAction Stop
+    $key = $null
+    foreach ($path in $registryPaths) {
+        $candidate = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
+        if ($candidate) {
+            Write-Host "Found Docker Desktop registry at: $path"
+            $key = $candidate
+            break
+        }
+    }
+    if (-not $key) {
+        Throw "Docker Desktop registry entry not found in HKCU or HKLM."
+    }
 
     # Get the uninstall command. Some uninstallers do not include 'QuietUninstallString'
     $uninstallCommand = if ($key.QuietUninstallString) {
@@ -17,7 +32,7 @@
         $key.UninstallString
     }
 
-    # The expected uninstall command value is "C:\Program Files\Docker\Docker\Docker Desktop Installer.exe" "uninstall"
+    # The expected uninstall command value is "<install dir>\Docker Desktop Installer.exe" "uninstall"
     $splitArgs = $uninstallCommand.Split('"')
     if ($splitArgs.Length -ne 5) {
       Throw "Unexpected uninstall command. Please update the uninstall script.`nUninstall command: $uninstallCommand"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

Only prepend "20" to Camtasia versions when the version is not already year-prefixed. Add a regex check to preserve versions like "2026.1.0" and keep behavior for two-digit year forms (e.g. "26.1.0"). Include unit tests covering both cases, and correct darwin.json entries/queries (fixing an earlier "202026" typo to "2026"). This ensures consistency with osquery's full-year bundle_short_version reporting.
@allenhouchins
allenhouchins requested a review from a team as a code owner May 14, 2026 18:32
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

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

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

=== Install // f938db79 -> b06042dd ===

--- /tmp/old.USzlcl	2026-05-14 18:35:56.555199227 +0000
+++ /tmp/new.e87VfG	2026-05-14 18:35:56.555199227 +0000
@@ -4,26 +4,31 @@
 $exeFilePath = "${env:INSTALLER_PATH}"
 
 try {
+    # Docker Desktop 4.72+ added a per-user vs all-user install choice for
+    # Windows. All-user silent installs hang on Windows Server runners
+    # (Docker Desktop is not officially supported on Windows Server). Install
+    # per-user with --user instead: no admin needed, target is
+    # %LOCALAPPDATA%\Programs\DockerDesktop, and uninstall info is written to
+    # HKCU. --accept-license suppresses the subscription agreement prompt.
+    Start-Process -FilePath "$exeFilePath" -ArgumentList "install","--user","--accept-license","--quiet" | Out-Null
 
-# Add argument to install silently
-# Argument to make install silent depends on installer,
-# each installer might use different argument (usually it's "/S" or "/s")
-$processOptions = @{
-  FilePath = "$exeFilePath"
-  ArgumentList = "install --quiet"
-  PassThru = $true
-  Wait = $true
-}
-    
-# Start process and track exit code
-$process = Start-Process @processOptions
-$exitCode = $process.ExitCode
-
-# Prints the exit code
-Write-Host "Install exit code: $exitCode"
-Exit $exitCode
+    # The installer process can keep running for several minutes after the
+    # app is registered with Windows. Poll the HKCU uninstall key (osquery's
+    # programs table reads both HKLM and HKU) to detect when the core install
+    # has completed, rather than blocking on Start-Process -Wait.
+    $registryKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop"
+    $deadline = (Get-Date).AddMinutes(4)
+    while ((Get-Date) -lt $deadline) {
+        if (Get-ItemProperty -Path $registryKey -ErrorAction SilentlyContinue) {
+            Write-Host "Docker Desktop registered in HKCU."
+            Exit 0
+        }
+        Start-Sleep -Seconds 10
+    }
 
+    Write-Host "Docker Desktop did not register within timeout."
+    Exit 1
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall // 000be0a3 -> 0b74af50 ===

--- /tmp/old.fOw0bs	2026-05-14 18:35:56.598200123 +0000
+++ /tmp/new.QutySB	2026-05-14 18:35:56.598200123 +0000
@@ -1,14 +1,29 @@
 # Define acceptable/expected exit codes
 $ExpectedExitCodes = @(0, 19)
 
-# Uninstall Registry Key
-$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+# Docker Desktop can be installed per-user (HKCU, %LOCALAPPDATA%) or
+# all-users (HKLM, C:\Program Files). Check HKCU first, then HKLM.
+$registryPaths = @(
+    'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop',
+    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+)
 
 # Initialize exit code
 $exitCode = 0
 
 try {
-    $key = Get-ItemProperty -Path $machineKey -ErrorAction Stop
+    $key = $null
+    foreach ($path in $registryPaths) {
+        $candidate = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
+        if ($candidate) {
+            Write-Host "Found Docker Desktop registry at: $path"
+            $key = $candidate
+            break
+        }
+    }
+    if (-not $key) {
+        Throw "Docker Desktop registry entry not found in HKCU or HKLM."
+    }
 
     # Get the uninstall command. Some uninstallers do not include 'QuietUninstallString'
     $uninstallCommand = if ($key.QuietUninstallString) {
@@ -17,7 +32,7 @@
         $key.UninstallString
     }
 
-    # The expected uninstall command value is "C:\Program Files\Docker\Docker\Docker Desktop Installer.exe" "uninstall"
+    # The expected uninstall command value is "<install dir>\Docker Desktop Installer.exe" "uninstall"
     $splitArgs = $uninstallCommand.Split('"')
     if ($splitArgs.Length -ne 5) {
       Throw "Unexpected uninstall command. Please update the uninstall script.`nUninstall command: $uninstallCommand"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

Add a macOS uninstall script for Camtasia and wire it into the manifests. ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh is added (removes /Applications/Camtasia.app and user/Shared and Library artifacts by moving them to the user's Trash). The input manifest ee/maintained-apps/inputs/homebrew/camtasia.json now references the new uninstall_script_path, and the output ee/maintained-apps/outputs/camtasia/darwin.json is updated to point to the new uninstall_script_ref and include the new script in refs.
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

=== Install Script (no changes) ===
=== Uninstall // 007deada -> a83239bb ===

--- /tmp/old.aUu8nJ	2026-05-14 18:50:33.759701388 +0000
+++ /tmp/new.0YTy4w	2026-05-14 18:50:33.759701388 +0000
@@ -29,6 +29,7 @@
 
 sudo rm -rf "$APPDIR/Camtasia.app"
 trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

=== Install // f938db79 -> b06042dd ===

--- /tmp/old.t67aga	2026-05-14 18:50:33.883702030 +0000
+++ /tmp/new.dwXwLg	2026-05-14 18:50:33.883702030 +0000
@@ -4,26 +4,31 @@
 $exeFilePath = "${env:INSTALLER_PATH}"
 
 try {
+    # Docker Desktop 4.72+ added a per-user vs all-user install choice for
+    # Windows. All-user silent installs hang on Windows Server runners
+    # (Docker Desktop is not officially supported on Windows Server). Install
+    # per-user with --user instead: no admin needed, target is
+    # %LOCALAPPDATA%\Programs\DockerDesktop, and uninstall info is written to
+    # HKCU. --accept-license suppresses the subscription agreement prompt.
+    Start-Process -FilePath "$exeFilePath" -ArgumentList "install","--user","--accept-license","--quiet" | Out-Null
 
-# Add argument to install silently
-# Argument to make install silent depends on installer,
-# each installer might use different argument (usually it's "/S" or "/s")
-$processOptions = @{
-  FilePath = "$exeFilePath"
-  ArgumentList = "install --quiet"
-  PassThru = $true
-  Wait = $true
-}
-    
-# Start process and track exit code
-$process = Start-Process @processOptions
-$exitCode = $process.ExitCode
-
-# Prints the exit code
-Write-Host "Install exit code: $exitCode"
-Exit $exitCode
+    # The installer process can keep running for several minutes after the
+    # app is registered with Windows. Poll the HKCU uninstall key (osquery's
+    # programs table reads both HKLM and HKU) to detect when the core install
+    # has completed, rather than blocking on Start-Process -Wait.
+    $registryKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop"
+    $deadline = (Get-Date).AddMinutes(4)
+    while ((Get-Date) -lt $deadline) {
+        if (Get-ItemProperty -Path $registryKey -ErrorAction SilentlyContinue) {
+            Write-Host "Docker Desktop registered in HKCU."
+            Exit 0
+        }
+        Start-Sleep -Seconds 10
+    }
 
+    Write-Host "Docker Desktop did not register within timeout."
+    Exit 1
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall // 000be0a3 -> 0b74af50 ===

--- /tmp/old.ie39GZ	2026-05-14 18:50:33.901702123 +0000
+++ /tmp/new.q5Dbmo	2026-05-14 18:50:33.901702123 +0000
@@ -1,14 +1,29 @@
 # Define acceptable/expected exit codes
 $ExpectedExitCodes = @(0, 19)
 
-# Uninstall Registry Key
-$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+# Docker Desktop can be installed per-user (HKCU, %LOCALAPPDATA%) or
+# all-users (HKLM, C:\Program Files). Check HKCU first, then HKLM.
+$registryPaths = @(
+    'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop',
+    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+)
 
 # Initialize exit code
 $exitCode = 0
 
 try {
-    $key = Get-ItemProperty -Path $machineKey -ErrorAction Stop
+    $key = $null
+    foreach ($path in $registryPaths) {
+        $candidate = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
+        if ($candidate) {
+            Write-Host "Found Docker Desktop registry at: $path"
+            $key = $candidate
+            break
+        }
+    }
+    if (-not $key) {
+        Throw "Docker Desktop registry entry not found in HKCU or HKLM."
+    }
 
     # Get the uninstall command. Some uninstallers do not include 'QuietUninstallString'
     $uninstallCommand = if ($key.QuietUninstallString) {
@@ -17,7 +32,7 @@
         $key.UninstallString
     }
 
-    # The expected uninstall command value is "C:\Program Files\Docker\Docker\Docker Desktop Installer.exe" "uninstall"
+    # The expected uninstall command value is "<install dir>\Docker Desktop Installer.exe" "uninstall"
     $splitArgs = $uninstallCommand.Split('"')
     if ($splitArgs.Length -ne 5) {
       Throw "Unexpected uninstall command. Please update the uninstall script.`nUninstall command: $uninstallCommand"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

@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: 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 `@ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh`:
- Around line 22-41: The trash() function is treating wildcard patterns as
literal strings because target_file="$2" and later checks [[ -e "$target_file"
]] with quotes, preventing glob/tilde expansion; change the function to iterate
over the glob-expanded results (e.g., for file in $target_file; do ... done) and
perform [[ -e $file ]] (unquoted for the test) then mv -f "$file" "$trash/..."
(keep mv argument quoted to handle spaces). This ensures patterns like
'~/Library/Caches/com.techsmith.camtasia*' expand to matching files and the
cleanup actually moves each match to trash.
🪄 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

Run ID: fe85c461-4fe5-4b21-9756-28f917500048

📥 Commits

Reviewing files that changed from the base of the PR and between 3f7d311 and f36e7ac.

📒 Files selected for processing (3)
  • ee/maintained-apps/inputs/homebrew/camtasia.json
  • ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh
  • ee/maintained-apps/outputs/camtasia/darwin.json

Comment on lines +22 to +41
if [[ -e "$target_file" ]]; then
echo "removing $target_file."
mv -f "$target_file" "$trash/${file_name}_${timestamp}_${rand}"
else
echo "$target_file doesn't exist."
fi
}

sudo rm -rf "$APPDIR/Camtasia.app"
trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'
trash $LOGGED_IN_USER '~/Library/Caches/com.techsmith.camtasia*'
trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.techsmith.camtasia*'
trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.techsmith.camtasia*.binarycookies'
trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.camtasia*.plist'
trash $LOGGED_IN_USER '~/Library/Saved Application State/com.techsmith.camtasia*.savedState'
trash $LOGGED_IN_USER '~/Library/WebKit/com.techsmith.camtasia*'

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant script lines
nl -ba ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh | sed -n '22,41p'

# Demonstrate why literal existence checks fail for wildcard patterns
python - <<'PY'
import os, glob, tempfile, pathlib, shutil
d = tempfile.mkdtemp(prefix="glob-demo-")
pathlib.Path(d, "one.sfl").touch()
pattern = os.path.join(d, "*.sfl")
print("os.path.exists(pattern) =", os.path.exists(pattern))  # literal check
print("glob matches =", glob.glob(pattern))                  # intended behavior
shutil.rmtree(d)
PY

Repository: fleetdm/fleet

Length of output: 100


🏁 Script executed:

#!/bin/bash
# Read the actual file without nl
sed -n '1,50p' ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh | cat -n

Repository: fleetdm/fleet

Length of output: 2118


🏁 Script executed:

#!/bin/bash
# Show lines 22-41 specifically
sed -n '22,41p' ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh

Repository: fleetdm/fleet

Length of output: 1299


🏁 Script executed:

#!/bin/bash
# Check the trash function signature and how it's called
grep -n "^trash" ee/maintained-apps/inputs/homebrew/scripts/camtasia_uninstall.sh | head -5

Repository: fleetdm/fleet

Length of output: 540


🏁 Script executed:

#!/bin/bash
# Demonstrate the bash glob expansion issue with a simple test
python3 << 'PYEOF'
import subprocess
import tempfile
import os
import pathlib

# Create a temp directory with test files
tmpdir = tempfile.mkdtemp(prefix="bash-glob-test-")
pathlib.Path(tmpdir, "file1.sfl").touch()
pathlib.Path(tmpdir, "file2.sfl").touch()
pathlib.Path(tmpdir, "other.txt").touch()

pattern = os.path.join(tmpdir, "*.sfl")

# Test 1: Check literal path existence (simulating what the bash script does)
print("=== Bash behavior with quoted variables ===")
script = f'''
target_file="{pattern}"
if [[ -e "$target_file" ]]; then
  echo "QUOTED: File exists at literal path"
else
  echo "QUOTED: Literal path does not exist (glob not expanded)"
fi

# Unquoted expansion (what should happen)
for f in {pattern}; do
  echo "UNQUOTED: Found file: $f"
done
'''

result = subprocess.run(['bash', '-c', script], capture_output=True, text=True)
print(result.stdout)
if result.stderr:
    print("stderr:", result.stderr)

# Cleanup
import shutil
shutil.rmtree(tmpdir)
PYEOF

Repository: fleetdm/fleet

Length of output: 280


Quoted wildcard patterns prevent glob expansion, so most user artifacts won't be cleaned.

The trash() function receives path patterns as quoted strings (e.g., '~/Library/Caches/com.techsmith.camtasia*' on lines 32–41) and stores them directly in a quoted variable target_file="$2" (line 10). This prevents glob expansion. At line 22, the quoted [[ -e "$target_file" ]] check fails because the literal string containing * does not exist as a file, causing the function to always report "doesn't exist" for patterns that should match multiple files.

Proposed fix
 trash() {
   local logged_in_user="$1"
-  local target_file="$2"
+  local target_pattern="$2"
   local timestamp="$(date +%Y-%m-%d-%s)"
   local rand="$(jot -r 1 0 99999)"

   # replace ~ with /Users/$logged_in_user
-  if [[ "$target_file" == ~* ]]; then
-    target_file="/Users/$logged_in_user${target_file:1}"
+  if [[ "$target_pattern" == ~* ]]; then
+    target_pattern="/Users/$logged_in_user${target_pattern:1}"
   fi

   local trash="/Users/$logged_in_user/.Trash"
-  local file_name="$(basename "${target_file}")"
+  shopt -s nullglob
+  local matches=( $target_pattern )
+  shopt -u nullglob

-  if [[ -e "$target_file" ]]; then
-    echo "removing $target_file."
-    mv -f "$target_file" "$trash/${file_name}_${timestamp}_${rand}"
-  else
-    echo "$target_pattern doesn't exist."
-  fi
+  if (( ${`#matches`[@]} == 0 )); then
+    echo "$target_pattern doesn't exist."
+    return
+  fi
+
+  for target_file in "${matches[@]}"; do
+    local file_name
+    file_name="$(basename "$target_file")"
+    echo "removing $target_file."
+    mv -f "$target_file" "$trash/${file_name}_${timestamp}_${rand}"
+  done
 }
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 31-31: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 32-32: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 32-32: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 33-33: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 33-33: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 34-34: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 34-34: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 35-35: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 35-35: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 36-36: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 37-37: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 37-37: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 38-38: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 38-38: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 39-39: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 40-40: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 40-40: Tilde does not expand in quotes. Use $HOME.

(SC2088)


[info] 41-41: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 41-41: Tilde does not expand in quotes. Use $HOME.

(SC2088)

🤖 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/inputs/homebrew/scripts/camtasia_uninstall.sh` around
lines 22 - 41, The trash() function is treating wildcard patterns as literal
strings because target_file="$2" and later checks [[ -e "$target_file" ]] with
quotes, preventing glob/tilde expansion; change the function to iterate over the
glob-expanded results (e.g., for file in $target_file; do ... done) and perform
[[ -e $file ]] (unquoted for the test) then mv -f "$file" "$trash/..." (keep mv
argument quoted to handle spaces). This ensures patterns like
'~/Library/Caches/com.techsmith.camtasia*' expand to matching files and the
cleanup actually moves each match to trash.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

=== Install Script (no changes) ===
=== Uninstall // 007deada -> a83239bb ===

--- /tmp/old.rCd9po	2026-05-14 19:04:22.864836726 +0000
+++ /tmp/new.MdiEix	2026-05-14 19:04:22.864836726 +0000
@@ -29,6 +29,7 @@
 
 sudo rm -rf "$APPDIR/Camtasia.app"
 trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

=== Install // f938db79 -> b06042dd ===

--- /tmp/old.rVlnhg	2026-05-14 19:04:22.998837818 +0000
+++ /tmp/new.S51Mnx	2026-05-14 19:04:22.998837818 +0000
@@ -4,26 +4,31 @@
 $exeFilePath = "${env:INSTALLER_PATH}"
 
 try {
+    # Docker Desktop 4.72+ added a per-user vs all-user install choice for
+    # Windows. All-user silent installs hang on Windows Server runners
+    # (Docker Desktop is not officially supported on Windows Server). Install
+    # per-user with --user instead: no admin needed, target is
+    # %LOCALAPPDATA%\Programs\DockerDesktop, and uninstall info is written to
+    # HKCU. --accept-license suppresses the subscription agreement prompt.
+    Start-Process -FilePath "$exeFilePath" -ArgumentList "install","--user","--accept-license","--quiet" | Out-Null
 
-# Add argument to install silently
-# Argument to make install silent depends on installer,
-# each installer might use different argument (usually it's "/S" or "/s")
-$processOptions = @{
-  FilePath = "$exeFilePath"
-  ArgumentList = "install --quiet"
-  PassThru = $true
-  Wait = $true
-}
-    
-# Start process and track exit code
-$process = Start-Process @processOptions
-$exitCode = $process.ExitCode
-
-# Prints the exit code
-Write-Host "Install exit code: $exitCode"
-Exit $exitCode
+    # The installer process can keep running for several minutes after the
+    # app is registered with Windows. Poll the HKCU uninstall key (osquery's
+    # programs table reads both HKLM and HKU) to detect when the core install
+    # has completed, rather than blocking on Start-Process -Wait.
+    $registryKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop"
+    $deadline = (Get-Date).AddMinutes(4)
+    while ((Get-Date) -lt $deadline) {
+        if (Get-ItemProperty -Path $registryKey -ErrorAction SilentlyContinue) {
+            Write-Host "Docker Desktop registered in HKCU."
+            Exit 0
+        }
+        Start-Sleep -Seconds 10
+    }
 
+    Write-Host "Docker Desktop did not register within timeout."
+    Exit 1
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall // 000be0a3 -> 0b74af50 ===

--- /tmp/old.ucrhmh	2026-05-14 19:04:23.016837965 +0000
+++ /tmp/new.rPuHU5	2026-05-14 19:04:23.016837965 +0000
@@ -1,14 +1,29 @@
 # Define acceptable/expected exit codes
 $ExpectedExitCodes = @(0, 19)
 
-# Uninstall Registry Key
-$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+# Docker Desktop can be installed per-user (HKCU, %LOCALAPPDATA%) or
+# all-users (HKLM, C:\Program Files). Check HKCU first, then HKLM.
+$registryPaths = @(
+    'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop',
+    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+)
 
 # Initialize exit code
 $exitCode = 0
 
 try {
-    $key = Get-ItemProperty -Path $machineKey -ErrorAction Stop
+    $key = $null
+    foreach ($path in $registryPaths) {
+        $candidate = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
+        if ($candidate) {
+            Write-Host "Found Docker Desktop registry at: $path"
+            $key = $candidate
+            break
+        }
+    }
+    if (-not $key) {
+        Throw "Docker Desktop registry entry not found in HKCU or HKLM."
+    }
 
     # Get the uninstall command. Some uninstallers do not include 'QuietUninstallString'
     $uninstallCommand = if ($key.QuietUninstallString) {
@@ -17,7 +32,7 @@
         $key.UninstallString
     }
 
-    # The expected uninstall command value is "C:\Program Files\Docker\Docker\Docker Desktop Installer.exe" "uninstall"
+    # The expected uninstall command value is "<install dir>\Docker Desktop Installer.exe" "uninstall"
     $splitArgs = $uninstallCommand.Split('"')
     if ($splitArgs.Length -ne 5) {
       Throw "Unexpected uninstall command. Please update the uninstall script.`nUninstall command: $uninstallCommand"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

@github-actions

Copy link
Copy Markdown
Contributor

Closing in favor of #45534.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

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

=== Install Script (no changes) ===
=== Uninstall // 007deada -> a83239bb ===

--- /tmp/old.PorlI5	2026-05-14 20:33:41.800760259 +0000
+++ /tmp/new.EjvDC7	2026-05-14 20:33:41.800760259 +0000
@@ -29,6 +29,7 @@
 
 sudo rm -rf "$APPDIR/Camtasia.app"
 trash $LOGGED_IN_USER '/Users/Shared/TechSmith/Camtasia'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia26.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.camtasia2026.sfl*'
 trash $LOGGED_IN_USER '~/Library/Application Support/TechSmith/Camtasia*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.techsmith.camtasia*'

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

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

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

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

ee/maintained-apps/outputs/docker/windows.json

=== Install // f938db79 -> b06042dd ===

--- /tmp/old.PQD6Uh	2026-05-14 20:33:41.925759214 +0000
+++ /tmp/new.l9lgs2	2026-05-14 20:33:41.925759214 +0000
@@ -4,26 +4,31 @@
 $exeFilePath = "${env:INSTALLER_PATH}"
 
 try {
+    # Docker Desktop 4.72+ added a per-user vs all-user install choice for
+    # Windows. All-user silent installs hang on Windows Server runners
+    # (Docker Desktop is not officially supported on Windows Server). Install
+    # per-user with --user instead: no admin needed, target is
+    # %LOCALAPPDATA%\Programs\DockerDesktop, and uninstall info is written to
+    # HKCU. --accept-license suppresses the subscription agreement prompt.
+    Start-Process -FilePath "$exeFilePath" -ArgumentList "install","--user","--accept-license","--quiet" | Out-Null
 
-# Add argument to install silently
-# Argument to make install silent depends on installer,
-# each installer might use different argument (usually it's "/S" or "/s")
-$processOptions = @{
-  FilePath = "$exeFilePath"
-  ArgumentList = "install --quiet"
-  PassThru = $true
-  Wait = $true
-}
-    
-# Start process and track exit code
-$process = Start-Process @processOptions
-$exitCode = $process.ExitCode
-
-# Prints the exit code
-Write-Host "Install exit code: $exitCode"
-Exit $exitCode
+    # The installer process can keep running for several minutes after the
+    # app is registered with Windows. Poll the HKCU uninstall key (osquery's
+    # programs table reads both HKLM and HKU) to detect when the core install
+    # has completed, rather than blocking on Start-Process -Wait.
+    $registryKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop"
+    $deadline = (Get-Date).AddMinutes(4)
+    while ((Get-Date) -lt $deadline) {
+        if (Get-ItemProperty -Path $registryKey -ErrorAction SilentlyContinue) {
+            Write-Host "Docker Desktop registered in HKCU."
+            Exit 0
+        }
+        Start-Sleep -Seconds 10
+    }
 
+    Write-Host "Docker Desktop did not register within timeout."
+    Exit 1
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall // 000be0a3 -> 0b74af50 ===

--- /tmp/old.rJDOpN	2026-05-14 20:33:41.942759072 +0000
+++ /tmp/new.BZ5MRC	2026-05-14 20:33:41.942759072 +0000
@@ -1,14 +1,29 @@
 # Define acceptable/expected exit codes
 $ExpectedExitCodes = @(0, 19)
 
-# Uninstall Registry Key
-$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+# Docker Desktop can be installed per-user (HKCU, %LOCALAPPDATA%) or
+# all-users (HKLM, C:\Program Files). Check HKCU first, then HKLM.
+$registryPaths = @(
+    'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop',
+    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop'
+)
 
 # Initialize exit code
 $exitCode = 0
 
 try {
-    $key = Get-ItemProperty -Path $machineKey -ErrorAction Stop
+    $key = $null
+    foreach ($path in $registryPaths) {
+        $candidate = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
+        if ($candidate) {
+            Write-Host "Found Docker Desktop registry at: $path"
+            $key = $candidate
+            break
+        }
+    }
+    if (-not $key) {
+        Throw "Docker Desktop registry entry not found in HKCU or HKLM."
+    }
 
     # Get the uninstall command. Some uninstallers do not include 'QuietUninstallString'
     $uninstallCommand = if ($key.QuietUninstallString) {
@@ -17,7 +32,7 @@
         $key.UninstallString
     }
 
-    # The expected uninstall command value is "C:\Program Files\Docker\Docker\Docker Desktop Installer.exe" "uninstall"
+    # The expected uninstall command value is "<install dir>\Docker Desktop Installer.exe" "uninstall"
     $splitArgs = $uninstallCommand.Split('"')
     if ($splitArgs.Length -ne 5) {
       Throw "Unexpected uninstall command. Please update the uninstall script.`nUninstall command: $uninstallCommand"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ee/maintained-apps/outputs/splashtop-business/darwin.json

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

@codecov

codecov Bot commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.23%. Comparing base (71f1567) to head (8408e69).
⚠️ Report is 16 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main   #45503       +/-   ##
===========================================
- Coverage   66.70%   55.23%   -11.47%     
===========================================
  Files        2736     2740        +4     
  Lines      218805   219152      +347     
  Branches    10821    10784       -37     
===========================================
- Hits       145948   121059    -24889     
- Misses      59633    86830    +27197     
+ Partials    13224    11263     -1961     
Flag Coverage Δ
backend 55.02% <100.00%> (-13.53%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 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.

@allenhouchins
allenhouchins merged commit 7d33110 into main May 14, 2026
51 of 97 checks passed
@allenhouchins
allenhouchins deleted the fma-2605141636 branch May 14, 2026 20:56
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.

3 participants