Skip to content

Multiple packages: install-time precedence and setup experience#48708

Merged
cdcme merged 3 commits into
feat/28108-multiple-custom-packagesfrom
feat/48398-install-precedence
Jul 6, 2026
Merged

Multiple packages: install-time precedence and setup experience#48708
cdcme merged 3 commits into
feat/28108-multiple-custom-packagesfrom
feat/48398-install-precedence

Conversation

@cdcme

@cdcme cdcme commented Jul 3, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #48398

Applies first-added-wins install precedence everywhere a host can match more than one package of a software title: manual install, self-service, policy auto-install, setup experience, and the host-software read all resolve the first-added package the host is in label scope for. Policy automations can now target a specific package (defaulting to first-added), and deleting a package re-points its automations to the first-added surviving package.

Checklist for submitter

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements).

Testing

@cdcme cdcme changed the base branch from main to feat/28108-multiple-custom-packages July 3, 2026 21:01
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.58333% with 35 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feat/28108-multiple-custom-packages@2dd989c). Learn more about missing BASE report.

Files with missing lines Patch % Lines
server/datastore/mysql/software.go 93.88% 8 Missing and 6 partials ⚠️
server/service/team_policies.go 62.96% 7 Missing and 3 partials ⚠️
ee/server/service/software_installers.go 83.33% 4 Missing and 3 partials ⚠️
server/datastore/mysql/software_installers.go 80.95% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@                          Coverage Diff                           @@
##             feat/28108-multiple-custom-packages   #48708   +/-   ##
======================================================================
  Coverage                                       ?   68.04%           
======================================================================
  Files                                          ?     3680           
  Lines                                          ?   234292           
  Branches                                       ?    12454           
======================================================================
  Hits                                           ?   159427           
  Misses                                         ?    60512           
  Partials                                       ?    14353           
Flag Coverage Δ
backend 69.70% <89.58%> (?)

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.

@cdcme

cdcme commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@claude review once.

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

Not approving auto — this touches install precedence, setup experience queuing, policy automation, and multi-package software display across service and datastore layers with new SQL (CTEs, window functions, subquery MIN() collapses), and it changes API surface (new software_installer_id field). Bug hunter found no issues, but the scope + criticality warrants a human eye.

Extended reasoning...

Overview

The PR implements the runtime side of Fleet's multi-package feature on top of the feat/28108-multiple-custom-packages branch. Roughly four behavior changes:

  1. Install precedence (ee/server/service/software_installers.go): New resolveFirstAddedInScopeInstaller picks the first-added (smallest installer_id) in-scope, platform-compatible package. Rewires InstallSoftwareTitle and SelfServiceInstallSoftwareTitle to use it. Preserves the two distinct error messages (not-in-scope vs not-self-service).
  2. Setup experience (server/datastore/mysql/setup_experience.go): Adds ROW_NUMBER() OVER (PARTITION BY software_title_id ...) around the combined installer/VPP UNION so a multi-package title queues only its first-added package.
  3. Policy automation (server/datastore/mysql/policies.go, server/service/team_policies.go, server/fleet/*policies.go): GitOps ApplyPolicySpecs now ORDER BY si_id IS NULL, si_id ASC LIMIT 1 to pin to the first-added package. Adds a new software_installer_id field on TeamPolicyRequest/ModifyPolicyPayload to override the default. DeleteSoftwareInstaller re-points policies to the first-added surviving package before deleting, or lets the FK 409 fire when there is no survivor.
  4. Host software listing (server/datastore/mysql/software.go): filterSoftwareInstallersByLabel returns a resolved package map instead of a filter; a new resolveFirstAddedInstallersForHost runs the four label-scope CTEs across every active package of the titles. ListHostSoftware pins the display join to those resolved installer IDs, and hostSoftwareInstalls/hostSoftwareUninstalls add MIN(id) subqueries to collapse historical rows.

Security risks

No authn/authz code changes. The user-facing surface additions (software_installer_id on policy create/modify) route through the existing authz.ActionWrite check on policies, and the new field is validated against GetSoftwarePackagesByTeamAndTitleID for the same team, which rejects cross-team installer IDs with a 400. The new SQL uses sqlx.Named+sqlx.In with parameterized args (no interpolation), so no injection surface.

Level of scrutiny

High. This is production-critical multi-tenant code: (a) install execution path (chooses which package to install on a host), (b) policy automation on failure (which package a failing policy triggers), (c) setup experience queuing (what runs on new-host bootstrap), (d) inventory display for tens of thousands of hosts. A precedence bug here can queue the wrong package for enrollments-in-flight or leak availability across labels. The four candidate tiers (both/inScopeAny/compatAny/any) in resolveFirstAddedInstallersForHost are new and subtle — the fallback-any tier means a title is never hidden but the installed package can be non-compatible on the display side. Worth a human verifying that matches product intent.

Other factors

  • Base branch is feat/28108-multiple-custom-packages, not main. This is a first-pass PR onto a feature branch, and the merge into main will presumably be reviewed again downstream — but this PR still lands on that feature branch and merits scrutiny now.
  • Test coverage is decent (integration tests for install precedence, policy default/override/reject, delete re-point; datastore tests for first-added policy resolution, setup-experience dedupe, list-host-software display). Codecov flags ~35 uncovered lines, mostly in fallback branches of the resolver and the modify-policy validation.
  • PR title says "first pass" — the author signals more iteration to come.
  • No prior human reviews on the timeline other than the request-for-review comment.

@cdcme cdcme marked this pull request as ready for review July 6, 2026 13:58
@cdcme cdcme requested a review from a team as a code owner July 6, 2026 13:58

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

Comment thread server/datastore/mysql/software.go Outdated
Comment thread server/datastore/mysql/software.go Outdated
@cdcme cdcme linked an issue Jul 6, 2026 that may be closed by this pull request
@cdcme cdcme merged commit a5c85af into feat/28108-multiple-custom-packages Jul 6, 2026
34 of 36 checks passed
@cdcme cdcme deleted the feat/48398-install-precedence branch July 6, 2026 21:04
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.

Multiple packages: install-time precedence and setup experience

2 participants