Skip to content

Fix Docker Desktop macOS FMA not reporting an installed version - #50885

Merged
allenhouchins merged 2 commits into
mainfrom
fix-docker-desktop-bundle-id
Aug 10, 2026
Merged

Fix Docker Desktop macOS FMA not reporting an installed version#50885
allenhouchins merged 2 commits into
mainfrom
fix-docker-desktop-bundle-id

Conversation

@allenhouchins

@allenhouchins allenhouchins commented Aug 10, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #50875

Docker Desktop on macOS never reported an installed version or "Installed" status, and offered "Install" on hosts that already had it.

Root cause

The FMA's unique_identifier was com.electron.dockerdesktop, which belongs to the embedded Electron bundle. The installed app reports a different identifier:

Path CFBundleIdentifier
/Applications/Docker.app com.docker.docker
/Applications/Docker.app/Contents/MacOS/Docker Desktop.app com.electron.dockerdesktop

The identifier was changed from com.docker.dockercom.electron.dockerdesktop in #37670 (Jan 5) as "the new bundle identifier … reflecting the current packaging". The top-level bundle never changed.

That was latent until #47831 (#44199, Jul 9) added an embedded-bundle filter to the macOS software inventory query in server/service/osquery_utils/queries.go:

FROM apps
WHERE path NOT LIKE '%.app/Contents/%'

/Applications/Docker.app/Contents/MacOS/Docker Desktop.app matches that pattern, so the only row carrying the embedded identifier is filtered out and inventory keeps just /Applications/Docker.appcom.docker.docker. Since FMA↔inventory matching is by bundle identifier (addSoftwareTitleToMatchingSoftware), the title the FMA owns had zero installed versions.

Patch policies kept passing, because they run the FMA's exists/patched SQL directly against the host's unfiltered apps table. That's also why #50041 needed a .back path exclusion, and why patch status and the software UI have disagreed since July.

What changed

Catalogunique_identifier is now com.docker.docker, with docker-desktop/darwin.json regenerated. outputs/apps.json needed a hand-edit because updateAppsListFile (cmd/maintained-apps/main.go) only appends new apps and never updates an existing entry's identifier — filed separately.

The remaining com.electron.dockerdesktop references are intentional and untouched: the install script's quit/relaunch targets (the Electron bundle is what responds to AppleScript) and the cask's zap paths. The .back exclusion in the patched query also stays — /Applications/Docker.app.back is a top-level bundle reporting com.docker.docker at a path the nested-bundle filter does not match, so a stale .back would otherwise show a false "Update available".

Migration (20260810152924_FixDockerDesktopBundleIdentifier) — fleet_maintained_apps self-heals on catalog sync (UpsertMaintainedApp updates unique_identifier on duplicate slug) and ReconcileMaintainedAppSoftwareNames renames the existing "Docker" title, but an already-added installer's software_installers.title_id binding does not:

  • No com.docker.docker title yet → relabel the stale title in place, so everything already pointing at it stays correct.
  • Title already exists (the normal case — any host with Docker creates it) → merge the stale title into it: installer, install history, queued installs, patch policy, software.title_id, and per-team settings (icons, display names, pins, update schedules), then drop the stale title.

Notes for reviewers

  • Teams that already have an installer on the target title are skipped rather than ending up with two installers on one title. dedup_token is the version for FMAs and the storage_id otherwise, so idx_software_installers_dedup would not have caught that collision. Those teams keep the pre-migration state instead of having data silently reshaped.
  • The stale title is only deleted once nothing depends on it. fk_software_installers_title is ON DELETE SET NULL, so deleting it while an installer still pointed at it would orphan that installer. Note also that fk_patch_software_title_id is ON DELETE CASCADE — re-pointing the patch policy is what keeps it from being deleted outright.
  • Dangling-reference check: the only title-referencing columns without an FK to software_titles are software.title_id (re-pointed), software_titles_host_counts (deleted; the cron recomputes), and kernel_host_counts / in_house_app_install_tokens, neither of which can hold a macOS app title.
  • Naming lags briefly. The existing title is named "Docker" (from osquery); ReconcileMaintainedAppSoftwareNames renames it to "Docker Desktop" on the next catalog sync, so there is a window after upgrade where the name is still "Docker". I left that to the sync rather than duplicating the rename logic in the migration.
  • This fixes one app, not the class. Any other macOS FMA keyed on a nested bundle fails the same silent way, and a green patch policy will not reveal it. An audit is filed separately.

Checklist for submitter

  • Changes file added for user-visible changes in changes/.
  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements). Table/column names in the migration's generated SQL come from hardcoded struct literals, never from data; all values are placeholders.

Testing

  • Added/updated automated tests

Five migration tests cover: relabel-in-place, merge-into-inventory-title, duplicate per-team settings dropped, teams with an existing installer skipped (and the stale title consequently retained), and no-op when the FMA was never added. The merge test also asserts updated_at is not restamped. Updated the homebrew ingester test expectations for the new identifier.

Verified: full server/datastore/mysql/migrations/tables suite passes (201s), ee/maintained-apps/..., cmd/maintained-apps/..., and the FMA datastore tests pass, make lint-go-incremental clean.

Root cause was confirmed against real bundles rather than inferred — PlistBuddy on both Docker bundles for the identifiers above, and lsregister -dump to confirm LaunchServices registers the nested bundles (which is why the raw apps table sees them and patch policies pass).

  • QA'd all new/changed functionality manually

Needs QA on a real instance: add the Docker Desktop FMA, confirm the installed version and "Installed" status appear on a host that already has it, and confirm an upgrade over an instance that already had the FMA added re-points the existing installer.

For unreleased bug fixes in a release candidate, one of:

  • Confirmed that the fix is not expected to adversely impact load test results

The migration touches only rows tied to a single software title, and is a no-op on instances that never added the Docker Desktop FMA.

Database migrations

  • Checked schema for all modified table for columns that will auto-update timestamps during migration.
  • Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects.

Five of the written tables have updated_at as ON UPDATE CURRENT_TIMESTAMP: software_installers, host_software_installs, software_install_upcoming_activities, policies, and software_title_team_pins. Since this re-points a foreign key rather than modifying the records, each statement assigns updated_at = updated_at so MySQL leaves them alone, with a test asserting it. (Bumping them would have been cosmetic — none of these columns drives ordering, scheduling, or invalidation; policy membership uses policy_membership.updated_at and hosts.policy_updated_at, and the activity feed orders by the activities table — but preserving them is more faithful to what the migration actually does.)

  • Ensured the correct collation is explicitly set for character columns (COLLATE utf8mb4_unicode_ci). No columns added or altered; this is a data-only migration.

Summary by CodeRabbit

  • Bug Fixes
    • Improved macOS Docker Desktop detection so installed versions and “Installed” status are reported accurately.
    • Ensured existing Docker Desktop installations and upgrade history remain correctly associated after detection updates.
    • Improved handling of stale application bundles during patch evaluation.
  • Maintenance
    • Updated detection data and migration coverage to support the corrected Docker Desktop identification.

The Docker Desktop macOS Fleet-maintained app matched on
"com.electron.dockerdesktop", which belongs to the embedded Electron bundle at
/Applications/Docker.app/Contents/MacOS/Docker Desktop.app. The installed app is
/Applications/Docker.app, which reports "com.docker.docker".

That was harmless until #47831 added `path NOT LIKE '%.app/Contents/%'` to the
macOS software inventory query, which drops embedded bundles. Since then nothing
in inventory carries the embedded identifier, so the FMA's software title had no
installed versions: no installed version, no "Installed" status, and "Install"
offered on hosts that already had Docker Desktop. Patch policies kept working
because they run the FMA's SQL against the host's unfiltered apps table.

Point the app at "com.docker.docker" and add a migration that re-points
already-added Docker Desktop installers to the correct software title, since
fleet_maintained_apps self-heals on catalog sync but installer bindings do not.

Fixes #50875
The migration re-points a foreign key rather than modifying these records, so
assign updated_at to itself on the five tables whose updated_at is
ON UPDATE CURRENT_TIMESTAMP (software_installers, host_software_installs,
software_install_upcoming_activities, policies, software_title_team_pins).
@allenhouchins
allenhouchins marked this pull request as ready for review August 10, 2026 17:36
@allenhouchins
allenhouchins requested a review from a team as a code owner August 10, 2026 17:36
Copilot AI lite review requested due to automatic review settings August 10, 2026 17:36
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e1c268f3-eb23-4cbe-9ab3-23ec874cf9f5

📥 Commits

Reviewing files that changed from the base of the PR and between 24e9c07 and 2b3760b.

📒 Files selected for processing (9)
  • changes/50875-docker-desktop-installed-version
  • ee/maintained-apps/ingesters/homebrew/ingester.go
  • ee/maintained-apps/ingesters/homebrew/ingester_test.go
  • ee/maintained-apps/inputs/homebrew/docker-desktop.json
  • ee/maintained-apps/outputs/apps.json
  • ee/maintained-apps/outputs/docker-desktop/darwin.json
  • server/datastore/mysql/migrations/tables/20260810152924_FixDockerDesktopBundleIdentifier.go
  • server/datastore/mysql/migrations/tables/20260810152924_FixDockerDesktopBundleIdentifier_test.go
  • server/datastore/mysql/schema.sql

Walkthrough

Docker Desktop macOS detection now uses com.docker.docker for maintained-app metadata, version detection, patch status, and process checks. Homebrew tests and patch-policy documentation reflect the updated identifier. A MySQL migration reconciles stale and corrected software titles, moves eligible installers and related records, handles duplicate settings and installer conflicts, and removes stale data when possible. Migration tests cover relabeling, merging, conflicts, cleanup, and no-op behavior. Migration status metadata registers version 20260810152924.

Possibly related PRs

  • fleetdm/fleet#50041: Updates Docker Desktop macOS detection and .back path filtering in related ingester and output files.
  • fleetdm/fleet#49849: Modifies MySQL migration registration and schema.sql migration metadata.
  • fleetdm/fleet#50438: Modifies the Docker Desktop maintained-app definition and release metadata.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that the PR fixes Docker Desktop macOS installed-version reporting.
Description check ✅ Passed The description identifies the issue, root cause, implementation, migration behavior, tests, and remaining manual QA work.
Linked Issues check ✅ Passed The changes address [#50875] by correcting bundle matching and migrating existing titles and installer references.
Out of Scope Changes check ✅ Passed The catalog updates, migration, tests, and documentation comments are directly related to the Docker Desktop detection fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-docker-desktop-bundle-id

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

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

Pull request overview

This PR fixes a macOS Fleet-maintained app (FMA) mismatch for Docker Desktop where the catalog’s unique_identifier pointed at a nested Electron bundle, but software inventory filtering retains only the top-level /Applications/Docker.app bundle identifier—causing Docker Desktop to appear not installed and not report a version.

Changes:

  • Update Docker Desktop FMA identifiers and generated outputs to use com.docker.docker (top-level bundle) for matching against inventory.
  • Add a MySQL data migration to rebind existing installer/title references from the stale title to the inventory title (or relabel in place when inventory title doesn’t exist).
  • Update Homebrew ingester behavior/tests to reflect the new identifier and keep .back path handling for patch status.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
server/datastore/mysql/schema.sql Bumps migration status seed/auto-increment to include the new migration.
server/datastore/mysql/migrations/tables/20260810152924_FixDockerDesktopBundleIdentifier.go Adds migration to relabel/merge stale Docker Desktop software title and re-point related references.
server/datastore/mysql/migrations/tables/20260810152924_FixDockerDesktopBundleIdentifier_test.go Adds migration test coverage for relabel/merge/skip scenarios and timestamp preservation.
ee/maintained-apps/outputs/docker-desktop/darwin.json Regenerates Docker Desktop output queries to use com.docker.docker.
ee/maintained-apps/outputs/apps.json Updates Docker Desktop entry’s unique_identifier to com.docker.docker.
ee/maintained-apps/inputs/homebrew/docker-desktop.json Updates Docker Desktop input unique_identifier to com.docker.docker.
ee/maintained-apps/ingesters/homebrew/ingester.go Clarifies .back handling comment for Docker Desktop patch query generation.
ee/maintained-apps/ingesters/homebrew/ingester_test.go Updates expectations for Docker Desktop identifier and generated queries.
changes/50875-docker-desktop-installed-version Release note entry (content excluded from review).
Files excluded by content exclusion policy (1)
  • changes/50875-docker-desktop-installed-version

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +79 to +103
for _, si := range staleInstallers {
if _, blocked := blockedTeams[si.teamID]; blocked {
continue
}
if _, err := tx.Exec(
`UPDATE software_installers SET title_id = ?, updated_at = updated_at WHERE id = ?`,
targetTitleID, si.id,
); err != nil {
return fmt.Errorf("re-pointing Docker Desktop installer %d: %w", si.id, err)
}
}

// Install history and queued installs have no title-scoped unique key, so they move
// wholesale.
for _, t := range []titleRefColumn{
{"host_software_installs", "software_title_id", true},
{"software_install_upcoming_activities", "software_title_id", true},
{"software", "title_id", false},
{"policies", "patch_software_title_id", true},
} {
if _, err := tx.Exec(
fmt.Sprintf(`UPDATE %s SET %s = ?%s WHERE %s = ?`,
t.table, t.column, t.preserveUpdatedAt(), t.column),
targetTitleID, staleTitleID,
); err != nil {
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.00000% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.53%. Comparing base (841cc42) to head (2b3760b).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...20260810152924_FixDockerDesktopBundleIdentifier.go 70.00% 20 Missing and 16 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #50885      +/-   ##
==========================================
- Coverage   68.53%   68.53%   -0.01%     
==========================================
  Files        3977     3978       +1     
  Lines      256148   256274     +126     
  Branches    13627    13627              
==========================================
+ Hits       175557   175630      +73     
- Misses      64977    65010      +33     
- Partials    15614    15634      +20     
Flag Coverage Δ
backend 69.63% <70.00%> (-0.01%) ⬇️

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

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@allenhouchins
allenhouchins merged commit 79305ea into main Aug 10, 2026
55 checks passed
@allenhouchins
allenhouchins deleted the fix-docker-desktop-bundle-id branch August 10, 2026 18:00
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.

Docker Desktop for macOS is not reporting installed version or status

3 participants