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
georgekarrv added a commit that referenced this pull request Jul 15, 2026
**Related issue:** Resolves #28108

Adds support for uploading multiple custom packages (up to 10) for the
same software title on a team — so IT admins can deploy different
versions or architectures (for example, Arm vs. Intel builds or staged
rollouts) to label-scoped hosts instead of splitting them across teams.
The software title keeps a single first-added `software_package` for
backwards compatibility, and first-added-wins resolves overlaps
consistently across self-service, manual install, policy automation, and
setup experience.

Feature branch combining the sub-PRs: migration (#48596), packages[] API
and add/edit/delete-package endpoints (#48607), install-time precedence
and setup experience (#48708), GitOps (#48710), Library and
Add/Edit/Delete modals (#48520), secondary UI — policy automation, setup
experience, and install-details hash (#49079), and the host
install-result `hash_sha256` field (#49085).

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Support up to 10 custom packages per software title, with
package-scoped deploy/install settings and package-specific edit/delete.
  * Policy automation can pin “Install software” to a specific package.
* GitOps generation now outputs repeatable multi-package YAML per title.
* Software install details now display the package SHA-256 hash (when
available) with a copy-to-clipboard action.
* **Bug Fixes**
* Improved deterministic “first-added” precedence for installs,
listings, setup experience, and policy dispatch when multiple packages
match.
* Fixed installer targeting and per-package metadata persistence
(including installer-specific activity details).
* **Accessibility/UX**
  * Added optional `aria-label` support for dropdowns.
  * Info banners can now render a leading icon with configurable color.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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