Update Fleet-maintained apps - #46375
Conversation
Generated automatically with cmd/maintained-apps.
There was a problem hiding this comment.
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.
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.1qqZ1Y 2026-05-28 18:35:46.117942375 +0000
+++ /tmp/new.SwNgwr 2026-05-28 18:35:46.117942375 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install // ee068356 -> 4be62464 ===
--- /tmp/old.B9893X 2026-05-28 18:35:46.293944930 +0000
+++ /tmp/new.E7vAMP 2026-05-28 18:35:46.293944930 +0000
@@ -1,12 +1,8 @@
-# Learn more about .exe install scripts:
-# http://fleetdm.com/learn-more-about/exe-install-scripts
-
$exeFilePath = "${env:INSTALLER_PATH}"
try {
# Add argument to install silently
-# Asana uses --silent for silent installation
$processOptions = @{
FilePath = "$exeFilePath"
ArgumentList = "/silent", "/norestart", "ACCEPT_EULA=1"
=== Uninstall // fa3b8ea6 -> 201475bb ===
--- /tmp/old.1KNqL7 2026-05-28 18:35:46.311945191 +0000
+++ /tmp/new.tU79Ti 2026-05-28 18:35:46.312945206 +0000
@@ -8,13 +8,16 @@
# Removing the MSI directly orphans the bundle: its uninstall then no-ops
# (returns 0) and leaves the "Microsoft PowerBI Desktop (x64)" registration
# behind, which is what Fleet's osquery-based validator keeps detecting.
-# Correct approach: uninstall via the BUNDLE first; it removes the MSI and its
-# own registration. Burn relaunches a cached copy of itself + spawns msiexec
-# asynchronously, so wait for those to finish.
+#
+# Correct approach: uninstall via the BUNDLE first. It removes both the MSI and
+# its own registration. Burn relaunches a cached copy of itself and spawns
+# msiexec asynchronously, so wait for those to finish.
$ExpectedExitCodes = @(0, 1605, 1641, 3010)
$exitCode = 0
+# Power BI's default install folder; used as a safety check before deleting any
+# stale registration that survives a successful uninstall.
$installDirs = @(
(Join-Path $env:ProgramFiles 'Microsoft Power BI Desktop'),
(Join-Path ${env:ProgramFiles(x86)} 'Microsoft Power BI Desktop')
@@ -58,6 +61,8 @@
}
try {
+
+ # Uninstall roots across all hives (matches osquery's "programs" table).
$roots = [System.Collections.Generic.List[string]]::new()
$roots.Add('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall')
$roots.Add('HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
@@ -77,20 +82,23 @@
Stop-Process -Name $proc -Force -ErrorAction SilentlyContinue
}
- # Phase 1: uninstall via the Burn bundle bootstrapper(s) FIRST.
+ # --- Phase 1: uninstall via the Burn bundle bootstrapper(s) FIRST. ---
foreach ($e in ($entries | Where-Object { $_.Command -match "(?i)PBIDesktopSetup.*\.exe" })) {
$exe = Get-ExePath $e.Command
if (-not $exe) { Write-Host "Could not parse bundle exe from: $($e.Command)"; continue }
if (-not (Test-Path -LiteralPath $exe)) { Write-Host "Bundle exe missing: $exe"; continue }
Write-Host "Uninstalling bundle: '$($e.DisplayName)'"
+ Write-Host " Command: $exe"
+ Write-Host " Args: /uninstall /quiet /norestart"
$p = Start-Process -FilePath $exe -ArgumentList "/uninstall /quiet /norestart" -PassThru -Wait
Write-Host " Exit code: $($p.ExitCode)"
if (($ExpectedExitCodes -notcontains $p.ExitCode) -and ($exitCode -eq 0)) { $exitCode = $p.ExitCode }
+
Wait-ForProcessExit -Names @("PBIDesktopSetup_x64", "PBIDesktopSetup", "msiexec") -TimeoutSeconds 240
}
- # Phase 2: remove any MSI entries the bundle didn't clean up.
+ # --- Phase 2: remove any MSI entries the bundle didn't clean up. ---
foreach ($e in (Get-PowerBIEntries -Roots $roots)) {
$msiCode = $null
if ($e.Command -match "(?i)MsiExec\.exe\s+/[IX]\s*(\{[A-F0-9-]+\})") { $msiCode = $Matches[1] }
@@ -104,16 +112,22 @@
if (($ExpectedExitCodes -notcontains $p.ExitCode) -and ($exitCode -eq 0)) { $exitCode = $p.ExitCode }
}
- # Phase 3: safety net for stale registration when product files are gone.
+ # --- Phase 3: safety net. If the product files are gone but a stale ARP
+ # registration lingers, remove the orphaned key so detection clears. Gated
+ # on the install folder being absent so we never hide a real install. ---
$productGone = -not ($installDirs | Where-Object { $_ -and (Test-Path -LiteralPath $_) })
foreach ($e in (Get-PowerBIEntries -Roots $roots)) {
- if ($productGone) {
+ $isMachineKey = $e.KeyPath -like 'Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\*'
+ if ($productGone -and $isMachineKey) {
Write-Host "Removing orphaned registration: '$($e.DisplayName)' ($($e.KeyPath))"
Remove-Item -Path $e.KeyPath -Recurse -Force -ErrorAction SilentlyContinue
} else {
Write-Host "WARNING: entry still present and product files remain: '$($e.DisplayName)'"
if ($exitCode -eq 0) { $exitCode = 1 }
}
+ Write-Host "WARNING: entry still present and product files remain: '$($e.DisplayName)'"
+ if ($exitCode -eq 0) { $exitCode = 1 }
+ }
}
} catch { |
WalkthroughThis PR updates version metadata, installer URLs, and SHA256 checksums across multiple maintained-app JSON manifests (Arc, Claude, Grammarly Desktop, Granola macOS and Windows). It replaces the Canva Windows uninstall script with a modified regex for unquoted executable paths. Power BI Windows receives a version bump and new install/uninstall script refs; the uninstall script tightens its ARP/registry cleanup by only deleting orphaned machine-hive entries and otherwise emits a WARNING and may return a non-zero exit code. Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ee/maintained-apps/outputs/power-bi/windows.json`:
- Line 19: In the Phase 3 cleanup foreach (the loop iterating Get-PowerBIEntries
after computing $productGone) there is a duplicated warning block and an extra
closing brace that breaks parsing; edit the loop that checks $isMachineKey so
that only the single else branch remains (keep the Write-Host "WARNING: entry
still present..." and the if ($exitCode -eq 0) { $exitCode = 1 } inside that
else) and remove the duplicate Write-Host/if lines and the stray closing brace
so the foreach and try/catch blocks are properly balanced.
🪄 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: 32ff33e8-f7ff-4749-b99f-2827d6587e25
📒 Files selected for processing (7)
ee/maintained-apps/outputs/arc/darwin.jsonee/maintained-apps/outputs/canva/windows.jsonee/maintained-apps/outputs/claude/darwin.jsonee/maintained-apps/outputs/grammarly-desktop/darwin.jsonee/maintained-apps/outputs/granola/darwin.jsonee/maintained-apps/outputs/granola/windows.jsonee/maintained-apps/outputs/power-bi/windows.json
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.e8MI5X 2026-05-28 19:40:39.126520315 +0000
+++ /tmp/new.SPaMbz 2026-05-28 19:40:39.127520312 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.3j5UYy 2026-05-28 19:41:46.348066162 +0000
+++ /tmp/new.4GdQBT 2026-05-28 19:41:46.349066163 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
|
Actionable comments posted: 0 |
1 similar comment
|
Actionable comments posted: 0 |
Replace /silent with /quiet for the Power BI EXE installer in the winget install script and the windows.json output snippet. Aligns the installer arguments with the bundle's uninstall usage (/uninstall /quiet /norestart) to ensure consistent silent install/uninstall behavior.
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.P4jagl 2026-05-28 20:44:05.790983601 +0000
+++ /tmp/new.fu4gDM 2026-05-28 20:44:05.790983601 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
|
Actionable comments posted: 0 |
|
Closing in favor of #46386. |
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.JM3bkT 2026-05-28 20:56:22.949934299 +0000
+++ /tmp/new.3SwEQS 2026-05-28 20:56:22.949934299 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
|
Closing in favor of #46389. |
Script Diff Resultsee/maintained-apps/outputs/arc/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/canva/windows.json=== Install Script (no changes) ===
=== Uninstall // 58022dd8 -> f683286d ===
--- /tmp/old.q9Q4yF 2026-05-28 21:18:36.533991692 +0000
+++ /tmp/new.D2sDNO 2026-05-28 21:18:36.533991692 +0000
@@ -32,7 +32,7 @@
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
-} elseif ($uninstallString -match '^([^\s]+)(.*)') {
+} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"ee/maintained-apps/outputs/claude/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/grammarly-desktop/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/granola/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/power-bi/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Automated ingestion of latest Fleet-maintained app data.
Summary by CodeRabbit