Update Fleet-maintained apps - #50438
Conversation
Generated automatically with cmd/maintained-apps.
|
Closing in favor of #50439. |
WalkthroughUpdated maintained-app metadata for 23 macOS and 5 Windows applications. Changes include release versions, patch queries, installer URLs, and SHA-256 checksums. Updated Elgato Camera Hub’s installer package reference. Updated CrystalDiskMark script references and PowerShell behavior for registry detection and uninstaller timeouts. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ee/maintained-apps/outputs/antigravity/darwin.json`:
- Around line 9-12: Update the manifest generation for Antigravity, Hubstaff,
OrbStack, and Wavebox so Intel and Apple Silicon hosts receive
architecture-specific installer URLs with matching checksums instead of exposing
only ARM64 artifacts. Apply the required changes in
ee/maintained-apps/outputs/antigravity/darwin.json (lines 9-12),
ee/maintained-apps/outputs/hubstaff/darwin.json (lines 9-12),
ee/maintained-apps/outputs/orbstack/darwin.json (lines 9-12), and
ee/maintained-apps/outputs/wavebox/darwin.json (lines 9-12), or explicitly mark
any accurately Apple Silicon-only app accordingly.
In `@ee/maintained-apps/outputs/crystaldiskmark/windows.json`:
- Line 20: Update Get-CrystalDiskMarkEntry and the post-install verification to
require the expected installer version, derived from the installed package
metadata, in DisplayVersion. Ensure stale or mismatched CrystalDiskMark registry
entries do not satisfy verification; fail when the expected version is absent
while preserving the existing publisher and product-name checks.
🪄 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: 47ba77a0-3be1-4d9a-9463-90938c0d348b
📒 Files selected for processing (28)
ee/maintained-apps/outputs/adlock/darwin.jsonee/maintained-apps/outputs/aldente/darwin.jsonee/maintained-apps/outputs/antigravity/darwin.jsonee/maintained-apps/outputs/badgeify/darwin.jsonee/maintained-apps/outputs/camo-studio/darwin.jsonee/maintained-apps/outputs/cherry-studio/darwin.jsonee/maintained-apps/outputs/cmux/darwin.jsonee/maintained-apps/outputs/creative-force-kelvin/windows.jsonee/maintained-apps/outputs/crystaldiskmark/windows.jsonee/maintained-apps/outputs/docker-desktop/darwin.jsonee/maintained-apps/outputs/duckduckgo/darwin.jsonee/maintained-apps/outputs/elgato-camera-hub/darwin.jsonee/maintained-apps/outputs/ente-auth/darwin.jsonee/maintained-apps/outputs/exifcleaner/darwin.jsonee/maintained-apps/outputs/firefox@nightly/darwin.jsonee/maintained-apps/outputs/free-download-manager/darwin.jsonee/maintained-apps/outputs/galaxy-modeler/windows.jsonee/maintained-apps/outputs/granola/darwin.jsonee/maintained-apps/outputs/hubstaff/darwin.jsonee/maintained-apps/outputs/lulu/darwin.jsonee/maintained-apps/outputs/nordvpn/darwin.jsonee/maintained-apps/outputs/ocenaudio/windows.jsonee/maintained-apps/outputs/orbstack/darwin.jsonee/maintained-apps/outputs/postman/darwin.jsonee/maintained-apps/outputs/postman/windows.jsonee/maintained-apps/outputs/vpn-tracker-365/darwin.jsonee/maintained-apps/outputs/wavebox/darwin.jsonee/maintained-apps/outputs/zoom-rooms/windows.json
| "installer_url": "https://storage.googleapis.com/antigravity-public/antigravity-hub/2.5.0-5471848641724416/darwin-arm/Antigravity.dmg", | ||
| "install_script_ref": "b60a046d", | ||
| "uninstall_script_ref": "5e1a08b9", | ||
| "sha256": "ba5ea61b6915acccc5e6e2165e18949f05f2e725fab89e780aa6b36e37132ded", | ||
| "sha256": "18b6e837d1fef34456d22296b2def3ee90a0a14a539a0c1d83c3eaaf5029811f", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files relevant to maintained apps =="
git ls-files | rg '(^|/)ee/maintained-apps/outputs/(antigravity|hubstaff|orbstack|wavebox|postman)/darwin\.json$|maintained-apps|Fleet|homebrew|ingest' | sed -n '1,200p'
echo
echo "== current target darwin.json snippets =="
for f in ee/maintained-apps/outputs/antigravity/darwin.json ee/maintained-apps/outputs/hubstaff/darwin.json ee/maintained-apps/outputs/orbstack/darvin.json ee/maintained-apps/outputs/wavebox/darwin.json ee/maintained-apps/outputs/postman/darwin.json; do
if [ -f "$f" ]; then
echo "--- $f"
sed -n '1,80p' "$f"
else
echo "MISSING $f"
fi
done
echo
echo "== search for architecture selection in maintained-apps code =="
rg -n --hidden -S 'architecture|arch|arm64|amd64|Intel|intel|CPU|FMAManifestApp|installer_url|checksum|sha256|sha' ee/maintained-apps README.md . | sed -n '1,240p'Repository: fleetdm/fleet
Length of output: 50370
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files relevant to maintained apps =="
git ls-files | rg '(^|/)ee/maintained-apps/outputs/(antigravity|hubstaff|orbstack|wavebox|postman)/darwin\.json$|maintained-apps|Fleet|homebrew|ingest' | sed -n '1,200p'
echo
echo "== current target darwin.json snippets =="
for f in ee/maintained-apps/outputs/antigravity/darwin.json ee/maintained-apps/outputs/hubstaff/darwin.json ee/maintained-apps/outputs/wavebox/darwin.json ee/maintained-apps/outputs/postman/darwin.json; do
if [ -f "$f" ]; then
echo "--- $f"
sed -n '1,80p' "$f"
else
echo "MISSING $f"
fi
done
echo
echo "== search for architecture selection in maintained-apps code =="
rg -n --hidden -S 'architecture|arch|arm64|amd64|Intel|intel|CPU|FMAManifestApp|installer_url|checksum|sha256|sha' ee/maintained-apps README.md . | sed -n '1,240p'
echo
echo "== Homebrew cask upstream content =="
python3 - <<'PY'
import requests
urls = {
"antigravity": "https://raw.githubusercontent.com/Homebrew/homebrew-cask/7ff60c261592579a18d69bb6afc4f8771b78cebd/Casks/a/antigravity.rb",
"hubstaff": "https://raw.githubusercontent.com/Homebrew/homebrew-cask/7ff60c261592579a18d69bb6afc4f8771b78cebd/Casks/hubstaff.rb",
"orbstack": "https://raw.githubusercontent.com/Homebrew/homebrew-cask/7ff60c261592579a18d69bb6afc4f8771b78cebd/Casks/o/orbstack.rb",
"wavebox": "https://raw.githubusercontent.com/Homebrew/homebrew-cask/7ff60c261592579a18d69bb6afc4f8771b78cebd/Casks/wavebox.rb",
}
for name, url in urls.items():
r = requests.get(url, timeout=20)
print(f"\n--- {name} {r.status_code} {url}")
if r.ok:
lines = r.text.splitlines()
for i, line in enumerate(lines, 1):
if any(tok in line for tok in ["url ", "checksum ", "sha256", "arch:"]):
print(f"{i}: {line}")
PYRepository: fleetdm/fleet
Length of output: 50369
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== ee/maintained-apps/outputs/orbstack files =="
git ls-files | rg '(^|/)ee/maintained-apps/outputs/orbstack/' | sed -n '1,120p'
[ -f ee/maintained-apps/outputs/orbstack/darwin.json ] && {
echo "--- ee/maintained-apps/outputs/orbstack/darwin.json top"
jq '.versions[] | {version, installer_url, sha256}' ee/maintained-apps/outputs/orbstack/darwin.json
}
echo "== FMAManifestApp shape and arch-related output fields =="
sed -n '1,110p' ee/maintained-apps/maintained_apps.go
echo "== homebrew ingester outputs for target apps =="
rg -n --hidden -S 'FMAManifestApp|installer_url|SHA256|SHA|Arch|arch|darwin|arm|intel|x86_64' ee/maintained-apps/ingesters/homebrew/ingester.go ee/maintained-apps/validate/darwin.go ee/maintained-apps/validate/main.go | sed -n '1,220p'
echo "== target input files if present =="
for f in ee/maintained-apps/inputs/homebrew/antigravity.json ee/maintained-apps/inputs/homebrew/hubstaff.json ee/maintained-apps/inputs/homebrew/orbstack.json ee/maintained-apps/inputs/homebrew/wavebox.json ee/maintained-apps/inputs/homebrew/postman.json; do
if [ -f "$f" ]; then
echo "--- $f"
jq '{name, unique_identifier, token, slug, sources}' "$f"
else
echo "MISSING $f"
fi
doneRepository: fleetdm/fleet
Length of output: 4386
🌐 Web query:
Homebrew homebrew-cask antigravity.rb url checksum arch x86_64 url
💡 Result:
The Homebrew cask for antigravity uses architecture-specific URLs and SHA-256 checksums, which are dynamically handled within the antigravity.rb file [1][2]. Because Homebrew formulae and casks are updated frequently, the specific url and sha256 values change with every new release [1][2]. As of August 3, 2026, the antigravity.rb cask defines these values using conditional logic based on the user's processor architecture [1][2]. Key details regarding the antigravity.rb cask configuration: Architecture Handling: The cask uses an arch variable to differentiate between arm (Apple Silicon) and intel (x86_64) architectures [1][2]. URL Pattern: The download URL follows a structured pattern: https://storage.googleapis.com/antigravity-public/antigravity-hub/#{version.csv.first}-#{version.csv.second}/darwin-#{arch}/Antigravity.dmg [1][2] Checksums: The sha256 block provides separate, verified hash values for both arm and intel builds to ensure integrity during installation [1][2]. To obtain the current, authoritative URL and checksum for the x86_64 (intel) architecture, you should view the latest version of the antigravity.rb file directly in the official Homebrew GitHub repository [1][2]. You can access this by navigating to the file at: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/a/antigravity.rb [1]
Citations:
- 1: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/a/antigravity.rb
- 2: https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks/a/antigravity.rb
🌐 Web query:
Homebrew homebrew-cask hubstaff.rb url checksum arch x86_64 arm64
💡 Result:
As of August 3, 2026, the Homebrew Cask formula for Hubstaff (hubstaff.rb) specifies separate SHA-256 checksums for the arm64 (Apple Silicon) and x86_64 (Intel) architectures [1]. The current configuration in the formula is [1]: Version: 1.9.2,12156 Architecture-specific SHA-256 checksums: - arm64: c47c1fd6250770844cf9a85437861a5e17967a279e90de21f5c5bdb9085c0c8e - x86_64 (intel): 4554bbba0da2d5ab1a9f61148fa3b8424c247be4e16ef3beec575dfa4c0c020b The formula dynamically determines the download URL based on the architecture using the following pattern [1]: https://app.hubstaff.com/download/#{version.csv.second}-standard-mac-os-x-#{version.csv.first.dots_to_hyphens}-release/dmg?architecture=#{arch} Where #{arch} resolves to either "arm64" or "x86_64" depending on the user's system [1]. This ensures that Homebrew downloads the correct installer for the detected architecture and verifies it against the corresponding checksum [1].
Citations:
🌐 Web query:
Homebrew homebrew-cask orbstack.rb url checksum arch x86_64 arm64
💡 Result:
The Homebrew cask for OrbStack uses an architecture-aware configuration to handle both Apple Silicon (arm64) and Intel (x86_64) Macs [1][2]. The cask file (orbstack.rb) dynamically determines the appropriate download URL and checksum based on the architecture of the host machine [1][3]. In the Homebrew cask definition, the architecture mapping is defined as: arch arm: "arm64", intel: "amd64" [1][4] The URL and checksum are then specified using these architecture-specific keys: URL structure: "https://cdn-updates.orbstack.dev/#{arch}/OrbStack_v#{version.csv.first}_#{version.csv.second}_#{arch}.dmg" [1][5] Checksum structure (example from version 2.2.1): sha256 arm: "5bc1719c3c987c4c60c65be9fdd65b4730990e1697ec1cb1c33e6bba31bf92b5", intel: "f30a15811104a494fe206695b1ab21fcfaee12ec9efbcba129a0034ebb68319b" [1][2] When a user runs brew install --cask orbstack, Homebrew automatically selects the version corresponding to the user's hardware [6][7]. Note that while the cask uses "amd64" in the URL and internal variable names to target Intel-based Macs, this correctly installs the x86_64 compatible version of the application [1][5].
Citations:
- 1: https://github.com/Homebrew/homebrew-cask/blob/9efa780ef820b03de4f9dfac48abcfa1f423bc56/Casks/o/orbstack.rb
- 2: https://github.com/Homebrew/homebrew-cask/blob/14e7175d9af61bb8e96175aa41a704102abc1b70/Casks/o/orbstack.rb
- 3: https://github.com/Homebrew/homebrew-cask/blob/6b8b53ea77c4f3d61527cfa1ff0709a7453f91ea/Casks/o/orbstack.rb
- 4: https://github.com/Homebrew/homebrew-cask/blob/05d5e8f151ab84bd0feeca1fbd9a7d202c73ceac/Casks/o/orbstack.rb
- 5: https://github.com/Homebrew/homebrew-cask/blob/4b088ba39cb3eb56568b27905d3e30fb102c4bdc/Casks/o/orbstack.rb
- 6: https://formulae.brew.sh/cask/orbstack
- 7: https://orbstack.dev/docs/quick-start
🌐 Web query:
Homebrew homebrew-cask wavebox.rb url checksum arch x86_64 arm64
💡 Result:
The Homebrew Cask configuration for Wavebox (wavebox.rb) utilizes a dynamic URL and architecture-specific checksums to support both x86_64 (intel) and arm64 (arm) macOS installations [1][2]. As of the latest available version information, the configuration structure is defined as follows: URL Template The URL is constructed dynamically based on the architecture to point to the correct release artifact: url "https://download.wavebox.app/stable/mac#{arch}/Wavebox_#{version}.zip" [1][2] In this template, #{arch} resolves to "arm64" for Apple Silicon and "intel" for x86_64, as defined by the arch mapping: arch arm: "arm64" [1][2] Checksums (sha256) The sha256 checksums are mapped explicitly to the processor architecture: sha256 arm: "9da85e2d3e4d79500353da206492374750c61ef1e80aab0b8b8f61236d4e1ce5", intel: "4947651c1e75b83555ad96e81e7841f77bdda103c9cdb391712108e7b4d86657" [2][3] Note: Because Homebrew Casks are frequently updated to track the latest software releases, the version number and associated sha256 checksums change over time [2][4][5]. You can view the current, live definition of the file in the official Homebrew Cask repository to obtain the most recent values [1][6].
Citations:
- 1: https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks/w/wavebox.rb
- 2: https://github.com/Homebrew/homebrew-cask/blob/4d2180e22ab7908c0ab7ff9c398b1fbefcbe577d/Casks/w/wavebox.rb
- 3: https://github.com/Homebrew/homebrew-cask/blob/34ab5b3a55e77346ad743bbbd02be1ab331cf220/Casks/w/wavebox.rb
- 4: https://github.com/Homebrew/homebrew-cask/blob/47817d96ba845ccedf309ed3f1e820076cecd0ba/Casks/w/wavebox.rb
- 5: https://github.com/Homebrew/homebrew-cask/blob/0c531ccd4f56034c8e06b935c798014428e7f020/Casks/w/wavebox.rb
- 6: https://formulae.brew.sh/cask/wavebox
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json, requests
names = ["antigravity", "hubstaff", "orbstack", "wavebox", "postman"]
repo_base = "https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks"
for name in names:
r = requests.get(f"{repo_base}/{name[0]}/{name}.rb", timeout=20)
print(f"\n=== {name} ===")
if r.status_code != 200:
print(r.status_code)
continue
text = r.text
print("has arch selection:", "arch :" in text or "archarm" in text)
for i,line in enumerate(text.splitlines(), 1):
if "url" in line or "sha256" in line or "arch" in line:
print(f"{i}: {line}")
PY
echo
jq -r '.versions[0] | `@json`' ee/maintained-apps/outputs/wavebox/darwin.json
jq -r '.versions[0] | `@json`' ee/maintained-apps/outputs/antigravity/darwin.json
jq -r '.versions[0] | `@json`' ee/maintained-apps/outputs/hubstaff/darwin.json
jq -r '.versions[0] | `@json`' ee/maintained-apps/outputs/postman/darwin.json
jq -r `@json` ee/maintained-apps/outputs/orbstack/darwin.jsonRepository: fleetdm/fleet
Length of output: 272
🌐 Web query:
GitHub Homebrew Casks wavebox.rb shasum sha256 sha512 url arch x86_64
💡 Result:
The Homebrew cask for Wavebox (wavebox.rb) is a dynamically managed file in the Homebrew-cask repository that uses variable architecture paths to support both Apple Silicon and Intel processors [1][2]. Key components of the wavebox.rb file include: Architecture Handling: The file defines an arch variable, typically set to "arm64" for Apple Silicon and defaulting to an empty string (or omitted) for Intel processors, which is then used to construct the download URL [1][2]. Download URL: The URL is constructed dynamically using the version and architecture variables: url "https://download.wavebox.app/stable/mac#{arch}/Wavebox_#{version}.zip" This structure ensures that the correct binary for the user's processor architecture is fetched [1][2]. SHA Checksums (sha256): Because the download links differ by architecture, the cask specifies separate sha256 checksums for each to ensure security [1][2]: sha256 arm: "9da85e2d3e4d79500353da206492374750c61ef1e80aab0b8b8f61236d4e1ce5", intel: "4947651c1e75b83555ad96e81e7841f77bdda103c9cdb391712108e7b4d86657" (Note: These specific values represent the version 150.2.131.2; checksums change whenever the application version is updated) [2][3]. The cask does not use sha512 for verification; it relies exclusively on sha256 as is standard for Homebrew casks [1][2]. Users should always reference the latest version of the file directly from the Homebrew-cask GitHub repository to obtain current checksums [2][4].
Citations:
- 1: https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks/w/wavebox.rb
- 2: https://github.com/Homebrew/homebrew-cask/blob/34ab5b3a55e77346ad743bbbd02be1ab331cf220/Casks/w/wavebox.rb
- 3: https://github.com/Homebrew/homebrew-cask/blob/4d2180e22ab7908c0ab7ff9c398b1fbefcbe577d/Casks/w/wavebox.rb
- 4: https://formulae.brew.sh/cask/wavebox
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Homebrew cask snippets =="
for app in antigravity hubstaff orbstack wavebox postman; do
url="https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks/${app:0:1}/${app}.rb"
echo "--- $app $url"
curl -fsSL "$url" | sed -n '1,120p'
done
echo
echo "== current Fleet manifest entries =="
for f in ee/maintained-apps/outputs/antigravity/darwin.json ee/maintained-apps/outputs/hubstaff/darwin.json ee/maintained-apps/outputs/orbstack/darwin.json ee/maintained-apps/outputs/wavebox/darwin.json ee/maintained-apps/outputs/postman/darwin.json; do
[ -f "$f" ] || continue
jq -r '.versions[0] | {version, installer_url, sha256}' "$f"
done
echo
echo "== Homebrew ingester key sections =="
sed -n '1,190p' ee/maintained-apps/ingesters/homebrew/ingester.go
sed -n '220,310p' ee/maintained-apps/ingesters/homebrew/ingester.go
sed -n '550,640p' ee/maintained-apps/ingesters/homebrew/ingester.goRepository: fleetdm/fleet
Length of output: 23838
🌐 Web query:
GitHub Homebrew Casks postman.rb arch arm osx_arm64 intel osx64
💡 Result:
The Homebrew Cask file for Postman (postman.rb) utilizes conditional architecture logic to provide the correct binary for different macOS hardware [1][2]. In the cask definition, the architecture mapping is defined as follows: arch arm: "osx_arm64", intel: "osx64" This configuration allows Homebrew to automatically detect whether the user is on an Apple Silicon (ARM) or Intel-based Mac and download the appropriate version from Postman's servers [1][2]. The URL for the download is dynamically constructed using the #{arch} variable, ensuring the correct package is fetched: url "https://dl.pstmn.io/download/version/#{version}/#{arch}" [1][2] Users do not need to manually specify the architecture; running the standard installation command automatically selects the correct file for the host system: brew install --cask postman [3][4] The cask also defines separate SHA-256 checksums for each architecture to ensure integrity [1][2]. The system handles this seamlessly, and users can update their installation using standard Homebrew commands [5].
Citations:
- 1: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/p/postman.rb
- 2: https://github.com/Homebrew/homebrew-cask/blob/5d07ccb2f350504bac1242cb460b65580345f1a9/Casks/p/postman.rb
- 3: https://formulae.brew.sh/cask/postman
- 4: https://learning.postman.com/docs/getting-started/installation/install-app
- 5: https://www.devzery.com/post/postman-download-mac
Preserve architecture-specific installer URLs and checksums.
The manifest schema keeps one installer_url and one sha256 per app/version, but the casks for Antigravity, Hubstaff, OrbStack, and Wavebox define separate architecture-specific artifacts. Current entries all expose only the ARM64 artifact, so Intel installers can fetch the wrong checksum. Generate architecture-specific manifest variants, or mark these apps Apple Silicon-only where that is accurate.
ee/maintained-apps/outputs/antigravity/darwin.json: select the Intel URL and checksum for Intel hosts.ee/maintained-apps/outputs/hubstaff/darwin.json: preserve the Intel download variant and checksum.ee/maintained-apps/outputs/orbstack/darwin.json: preserve theamd64download variant and checksum.ee/maintained-apps/outputs/wavebox/darwin.json: preserve the Intel download variant and checksum.
🧰 Tools
🪛 OpenGrep (1.26.0)
[ERROR] 9-9: Possible credit card number (PAN) detected in source code. Credit card numbers should never be hardcoded or stored in source files. Use a secrets manager or tokenization service instead.
(coderabbit.pii.credit-card-number)
📍 Affects 4 files
ee/maintained-apps/outputs/antigravity/darwin.json#L9-L12(this comment)ee/maintained-apps/outputs/hubstaff/darwin.json#L9-L12ee/maintained-apps/outputs/orbstack/darwin.json#L9-L12ee/maintained-apps/outputs/wavebox/darwin.json#L9-L12
🤖 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/antigravity/darwin.json` around lines 9 - 12,
Update the manifest generation for Antigravity, Hubstaff, OrbStack, and Wavebox
so Intel and Apple Silicon hosts receive architecture-specific installer URLs
with matching checksums instead of exposing only ARM64 artifacts. Apply the
required changes in ee/maintained-apps/outputs/antigravity/darwin.json (lines
9-12), ee/maintained-apps/outputs/hubstaff/darwin.json (lines 9-12),
ee/maintained-apps/outputs/orbstack/darwin.json (lines 9-12), and
ee/maintained-apps/outputs/wavebox/darwin.json (lines 9-12), or explicitly mark
any accurately Apple Silicon-only app accordingly.
| "49f32d49": "# Locates CrystalDiskMark's Inno Setup uninstaller in the registry and runs it silently.\n\n$softwareNameLike = \"CrystalDiskMark *\"\n$publisher = \"Crystal Dew World\"\n$uninstallArgs = \"/VERYSILENT /SUPPRESSMSGBOXES /NORESTART\"\n$removalTimeoutSeconds = 180\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$exitCode = 0\n\nfunction Get-CrystalDiskMarkEntry {\n Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n Where-Object { $_.DisplayName -like $softwareNameLike -and $_.Publisher -like \"$publisher*\" } |\n Select-Object -First 1\n}\n\ntry {\n $key = Get-CrystalDiskMarkEntry\n if (-not $key -or -not $key.UninstallString) {\n Write-Host \"Uninstall entry not found for '$softwareNameLike'.\"\n Exit 0\n }\n\n # The uninstaller refuses to run while the benchmark holds its mutex.\n foreach ($name in @(\"DiskMark32\", \"DiskMark32A\", \"DiskMark32M\", \"DiskMark32S\",\n \"DiskMark64\", \"DiskMark64A\", \"DiskMark64M\", \"DiskMark64S\",\n \"DiskMarkA64\", \"DiskMarkA64A\", \"DiskMarkA64M\", \"DiskMarkA64S\")) {\n Stop-Process -Name $name -Force -ErrorAction SilentlyContinue\n }\n\n $uninstallCommand = $key.UninstallString\n # Inno quotes the path, but parse the unquoted and bare forms defensively too.\n if ($uninstallCommand -match '^\\s*\"([^\"]+)\"\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '(?i)^\\s*(.+?\\.exe)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '^\\s*(\\S+)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n }\n\n Write-Host \"Uninstall command: $uninstallCommand\"\n Write-Host \"Uninstall args: $uninstallArgs\"\n\n $process = Start-Process -FilePath $uninstallCommand -ArgumentList $uninstallArgs -NoNewWindow -PassThru\n $null = $process.Handle\n $null = $process.WaitForExit($removalTimeoutSeconds * 1000)\n if ($process.HasExited) {\n $exitCode = $process.ExitCode\n Write-Host \"Uninstall exit code: $exitCode\"\n }\n\n # The Inno uninstaller relaunches itself from a temp copy and returns early,\n # so the registry entry disappearing is the real completion signal.\n $elapsed = 0\n while ((Get-CrystalDiskMarkEntry) -and ($elapsed -lt $removalTimeoutSeconds)) {\n Start-Sleep -Seconds 5\n $elapsed += 5\n }\n\n if (Get-CrystalDiskMarkEntry) {\n Write-Host \"CrystalDiskMark is still registered after ${removalTimeoutSeconds}s.\"\n Exit 1\n }\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n\nExit $exitCode\n", | ||
| "665ef39e": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n#\n# CrystalDiskMark ships as an Inno Setup installer (AppId \"CrystalDiskMark9\"),\n# which registers as \"CrystalDiskMark <version>\" in Add/Remove Programs.\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\n$installTimeoutSeconds = 300\n$registrationTimeoutSeconds = 60\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n\nfunction Get-CrystalDiskMarkEntry {\n Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n Where-Object { $_.DisplayName -like \"CrystalDiskMark *\" } |\n Select-Object -First 1\n}\n\ntry {\n if (-not (Test-Path $exeFilePath)) {\n Write-Host \"Error: Installer file not found at: $exeFilePath\"\n Exit 1\n }\n\n # -Wait also waits on descendants, so wait on the installer process alone.\n $processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"/VERYSILENT /SUPPRESSMSGBOXES /NORESTART\"\n PassThru = $true\n NoNewWindow = $true\n }\n $process = Start-Process @processOptions\n # Keeps .ExitCode readable after the process ends.\n $null = $process.Handle\n\n $killed = $false\n if (-not $process.WaitForExit($installTimeoutSeconds * 1000)) {\n Write-Host \"Installer process did not exit within ${installTimeoutSeconds}s, stopping it.\"\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n $null = $process.WaitForExit(30 * 1000)\n $killed = $true\n }\n\n $exitCode = $null\n if ($process.HasExited) {\n $exitCode = $process.ExitCode\n Write-Host \"Install exit code: $exitCode\"\n }\n\n # The installer can return before the ARP entry is written.\n $elapsed = 0\n while (-not (Get-CrystalDiskMarkEntry) -and ($elapsed -lt $registrationTimeoutSeconds)) {\n Start-Sleep -Seconds 5\n $elapsed += 5\n Write-Host \"Waiting for CrystalDiskMark to register... ($elapsed seconds)\"\n }\n\n $entry = Get-CrystalDiskMarkEntry\n if (-not $entry) {\n Write-Host \"CrystalDiskMark did not register in Add/Remove Programs.\"\n Exit 1\n }\n Write-Host \"Registered '$($entry.DisplayName)', version $($entry.DisplayVersion).\"\n\n # Registration above is the success signal; a killed process's code means nothing.\n if ($killed -or $null -eq $exitCode) { Exit 0 }\n\n # 3010 (reboot required) and 1641 (reboot initiated) are successful installs.\n if ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }\n\n Exit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n" | ||
| "021e806e": "# Locates CrystalDiskMark's Inno Setup uninstaller in the registry and runs it silently.\n\n$softwareNameLike = \"CrystalDiskMark *\"\n$publisher = \"Crystal Dew World\"\n$uninstallArgs = \"/VERYSILENT /SUPPRESSMSGBOXES /NORESTART\"\n$removalTimeoutSeconds = 180\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$exitCode = 0\n\nfunction Get-CrystalDiskMarkEntry {\n Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n Where-Object { $_.DisplayName -like $softwareNameLike -and $_.Publisher -like \"$publisher*\" } |\n Select-Object -First 1\n}\n\ntry {\n $key = Get-CrystalDiskMarkEntry\n if (-not $key -or -not $key.UninstallString) {\n Write-Host \"Uninstall entry not found for '$softwareNameLike'.\"\n Exit 0\n }\n\n # The uninstaller refuses to run while the benchmark holds its mutex.\n foreach ($name in @(\"DiskMark32\", \"DiskMark32A\", \"DiskMark32M\", \"DiskMark32S\",\n \"DiskMark64\", \"DiskMark64A\", \"DiskMark64M\", \"DiskMark64S\",\n \"DiskMarkA64\", \"DiskMarkA64A\", \"DiskMarkA64M\", \"DiskMarkA64S\")) {\n Stop-Process -Name $name -Force -ErrorAction SilentlyContinue\n }\n\n $uninstallCommand = $key.UninstallString\n # Inno quotes the path, but parse the unquoted and bare forms defensively too.\n if ($uninstallCommand -match '^\\s*\"([^\"]+)\"\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '(?i)^\\s*(.+?\\.exe)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '^\\s*(\\S+)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]; if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n }\n\n Write-Host \"Uninstall command: $uninstallCommand\"\n Write-Host \"Uninstall args: $uninstallArgs\"\n\n $process = Start-Process -FilePath $uninstallCommand -ArgumentList $uninstallArgs -NoNewWindow -PassThru\n $null = $process.Handle\n if (-not $process.WaitForExit($removalTimeoutSeconds * 1000)) {\n Write-Host \"Uninstaller process did not exit within ${removalTimeoutSeconds}s, stopping it.\"\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n }\n if ($process.HasExited) {\n $exitCode = $process.ExitCode\n Write-Host \"Uninstall exit code: $exitCode\"\n }\n\n # The Inno uninstaller relaunches itself from a temp copy and returns early,\n # so the registry entry disappearing is the real completion signal.\n $elapsed = 0\n while ((Get-CrystalDiskMarkEntry) -and ($elapsed -lt $removalTimeoutSeconds)) {\n Start-Sleep -Seconds 5\n $elapsed += 5\n }\n\n if (Get-CrystalDiskMarkEntry) {\n Write-Host \"CrystalDiskMark is still registered after ${removalTimeoutSeconds}s.\"\n Exit 1\n }\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n\nExit $exitCode\n", | ||
| "e39ecf9f": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n#\n# CrystalDiskMark ships as an Inno Setup installer (AppId \"CrystalDiskMark9\"),\n# which registers as \"CrystalDiskMark <version>\" in Add/Remove Programs.\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\n$installTimeoutSeconds = 300\n$registrationTimeoutSeconds = 60\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n\n$publisher = \"Crystal Dew World\"\n\nfunction Get-CrystalDiskMarkEntry {\n Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n Where-Object { $_.DisplayName -like \"CrystalDiskMark *\" -and $_.Publisher -like \"$publisher*\" } |\n Select-Object -First 1\n}\n\ntry {\n if (-not (Test-Path $exeFilePath)) {\n Write-Host \"Error: Installer file not found at: $exeFilePath\"\n Exit 1\n }\n\n # -Wait also waits on descendants, so wait on the installer process alone.\n $processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"/VERYSILENT /SUPPRESSMSGBOXES /NORESTART\"\n PassThru = $true\n NoNewWindow = $true\n }\n $process = Start-Process @processOptions\n # Keeps .ExitCode readable after the process ends.\n $null = $process.Handle\n\n $killed = $false\n if (-not $process.WaitForExit($installTimeoutSeconds * 1000)) {\n Write-Host \"Installer process did not exit within ${installTimeoutSeconds}s, stopping it.\"\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n $null = $process.WaitForExit(30 * 1000)\n $killed = $true\n }\n\n $exitCode = $null\n if ($process.HasExited) {\n $exitCode = $process.ExitCode\n Write-Host \"Install exit code: $exitCode\"\n }\n\n # The installer can return before the ARP entry is written.\n $elapsed = 0\n while (-not (Get-CrystalDiskMarkEntry) -and ($elapsed -lt $registrationTimeoutSeconds)) {\n Start-Sleep -Seconds 5\n $elapsed += 5\n Write-Host \"Waiting for CrystalDiskMark to register... ($elapsed seconds)\"\n }\n\n $entry = Get-CrystalDiskMarkEntry\n if (-not $entry) {\n Write-Host \"CrystalDiskMark did not register in Add/Remove Programs.\"\n Exit 1\n }\n Write-Host \"Registered '$($entry.DisplayName)', version $($entry.DisplayVersion).\"\n\n # Registration above is the success signal; a killed process's code means nothing.\n if ($killed -or $null -eq $exitCode) { Exit 0 }\n\n # 3010 (reboot required) and 1641 (reboot initiated) are successful installs.\n if ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }\n\n Exit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
file="ee/maintained-apps/outputs/crystaldiskmark/windows.json"
target="$(jq -r '.versions[0].version' "$file")"
ref="$(jq -r '.versions[0].install_script_ref' "$file")"
script="$(jq -r --arg ref "$ref" '.refs[$ref]' "$file")"
if ! printf '%s\n' "$script" | grep -Eq \
'Where-Object.*DisplayVersion|if .*DisplayVersion|expectedVersion'; then
echo "FAIL: install verification does not require target version $target" >&2
exit 1
fiRepository: fleetdm/fleet
Length of output: 216
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
file="ee/maintained-apps/outputs/crystaldiskmark/windows.json"
echo "== file excerpt =="
sed -n '1,80p' "$file"
echo
echo "== install script keys =="
jq -r --arg ref "$(jq -r '.versions[0].install_script_ref' "$file")" \
'.refs[$ref]' "$file"
echo
echo "== related test files =="
find ee/maintained-apps -path '*crystaldiskmark*' -type f -print | sort
for f in $(find ee/maintained-apps -path '*crystaldiskmark*' -type f -print); do
echo "--- $f"
wc -l "$f"
doneRepository: fleetdm/fleet
Length of output: 10986
Require DisplayVersion during install verification.
The installer script exits successfully when any CrystalDiskMark registry entry remains after install, so an older registration can make an upgrade to 9.0.3 pass. Filter the post-install lookup by the expected DisplayVersion, or fail when a newer install does not replace the expected version.
🤖 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/crystaldiskmark/windows.json` at line 20, Update
Get-CrystalDiskMarkEntry and the post-install verification to require the
expected installer version, derived from the installed package metadata, in
DisplayVersion. Ensure stale or mismatched CrystalDiskMark registry entries do
not satisfy verification; fail when the expected version is absent while
preserving the existing publisher and product-name checks.
Script Diff Resultsee/maintained-apps/outputs/adlock/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/aldente/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/cherry-studio/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/docker-desktop/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/elgato-camera-hub/darwin.json=== Install // af00dc29 -> 5d2ba4c9 ===
--- /tmp/old.b7BhFK 2026-08-03 15:10:17.139435374 +0000
+++ /tmp/new.IjH7Ab 2026-08-03 15:10:17.139435374 +0000
@@ -96,5 +96,5 @@
# install pkg files
quit_and_track_application 'com.elgato.CameraHub'
-sudo installer -pkg "$TMPDIR/CameraHub_2.3.0.7278.pkg" -target / || exit $?
+sudo installer -pkg "$TMPDIR/CameraHub_2.3.0.7286.pkg" -target / || exit $?
relaunch_application 'com.elgato.CameraHub'
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/firefox@nightly/darwin.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/hubstaff/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Automated ingestion of latest Fleet-maintained app data.
Summary by CodeRabbit