Skip to content

Fix duplicate software inventory entries from v4.76.0 checksum change - #50427

Open
juan-fdz-hawa wants to merge 6 commits into
mainfrom
36365-duplicate-software-checksum-dedup
Open

Fix duplicate software inventory entries from v4.76.0 checksum change#50427
juan-fdz-hawa wants to merge 6 commits into
mainfrom
36365-duplicate-software-checksum-dedup

Conversation

@juan-fdz-hawa

@juan-fdz-hawa juan-fdz-hawa commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Resolves #36365

The v4.76.0 checksum change (#34097) reordered the fields hashed into Software.ComputeRawChecksum for non-apps sources, so software rows created before the upgrade no longer matched re-ingested rows and got duplicated (same name/version/source, split host counts).

  • Make ComputeRawChecksum the sole source of truth and delete the drifted parallel SQL checksum formula that caused the mismatch.
  • Add ReconcileSoftwareChecksums, a one-shot migration that merges existing duplicates onto the canonical row (batched host_software repointing) and logs each merge. Runs once after startup; re-run with
    fleetctl trigger --name software_checksum_migration

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

  • 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

Summary by CodeRabbit

  • Bug Fixes

    • Automatically merges duplicate software inventory records after upgrading to Fleet v4.76.0 or later.
    • Preserves associated hosts and installed paths while removing duplicate entries.
    • Corrects legacy checksum inconsistencies, including null and empty identifiers.
    • Keeps distinct software records separate when their identifying details differ.
  • Documentation

    • Added instructions for manually rerunning the software checksum migration with fleetctl trigger --name software_checksum_migration.

Comment thread server/datastore/mysql/software.go Fixed
@juan-fdz-hawa

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change adds ReconcileSoftwareChecksums to merge duplicate software rows created by legacy checksum ordering. The workflow computes canonical checksums, repairs rows, repoints host and installed-path references, removes stale data, and processes records in bounded batches. A manual cron schedule invokes the migration, with support for retriggering. Tests cover merging, idempotence, batching, in-place repair, parsing, and identity normalization.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the fix for duplicate software inventory entries caused by the v4.76.0 checksum change.
Description check ✅ Passed The description includes the issue, change summary, required change file, validation, automated testing, and host-isolation checks; manual QA remains unchecked.
Linked Issues check ✅ Passed The changes directly address issue #36365 by reconciling duplicate software records and preventing checksum mismatches that caused duplicate CVE entries.
Out of Scope Changes check ✅ Passed The code, migration, cron trigger, documentation, mocks, and tests all support the linked issue and stated checksum reconciliation objectives.
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 36365-duplicate-software-checksum-dedup

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.

@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.65789% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.21%. Comparing base (1dc1a51) to head (0f89b21).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
server/datastore/mysql/software.go 75.00% 19 Missing and 15 partials ⚠️
cmd/fleet/cron.go 76.92% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main   #50427    +/-   ##
========================================
  Coverage   68.20%   68.21%            
========================================
  Files        3943     3944     +1     
  Lines      251273   251625   +352     
  Branches    13406    13406            
========================================
+ Hits       171390   171645   +255     
- Misses      64532    64597    +65     
- Partials    15351    15383    +32     
Flag Coverage Δ
backend 69.50% <75.65%> (+<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.

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
server/datastore/mysql/software_test.go (1)

14111-14121: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add t.Helper() so failures point at the calling test line.

legacyNameFirstChecksum calls require.NoError internally. Without t.Helper(), a failure reports this helper's line instead of the call site.

♻️ Proposed change
 func legacyNameFirstChecksum(t *testing.T, s fleet.Software) []byte {
+	t.Helper()
 	h := md5.New() //nolint:gosec // matches the (non-security) software checksum hash
🤖 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 `@server/datastore/mysql/software_test.go` around lines 14111 - 14121, Add
t.Helper() at the start of legacyNameFirstChecksum, before the require.NoError
call, so test failures report the calling test location.
🤖 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 `@cmd/fleet/cron.go`:
- Around line 2334-2339: The run-once software checksum reconciliation must
remain eligible after a failed execution. Update the startup cron flow around
the job registered with schedule.WithRunOnce and ds.ReconcileSoftwareChecksums
so failed reconciliation is not recorded as completed, allowing Start to retry
it on the next restart; preserve one-time completion after success and add a
test covering failure followed by restart and successful retry.
- Around line 2325-2339: Update the schedule created for
CronSoftwareChecksumMigration around schedule.WithRunOnce and the job callback
so the scheduler stops processing future ticker events after the first
successful scheduled ReconcileSoftwareChecksums run, while preserving
Trigger-based manual reruns. Add coverage that advances two intervals and
verifies ReconcileSoftwareChecksums is called only once by the schedule.

In `@server/datastore/mysql/software.go`:
- Around line 3397-3413: Update the duplicate-group query in the reconciliation
loop to use ds.writer(ctx) instead of ds.reader(ctx) when calling
sqlx.SelectContext, while preserving the existing batch processing,
reconciliation, and termination logic.

---

Nitpick comments:
In `@server/datastore/mysql/software_test.go`:
- Around line 14111-14121: Add t.Helper() at the start of
legacyNameFirstChecksum, before the require.NoError call, so test failures
report the calling test location.
🪄 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: b8ca0cb4-5337-4b3f-b595-4a408f7c49f5

📥 Commits

Reviewing files that changed from the base of the PR and between e83c268 and 6b01776.

📒 Files selected for processing (10)
  • changes/36365-duplicate-software-checksum
  • cmd/fleet/cron.go
  • cmd/fleet/cron_registration.go
  • server/datastore/mysql/migrations/tables/20231212094238_AddUniqueHashToSoftware.go
  • server/datastore/mysql/software.go
  • server/datastore/mysql/software_test.go
  • server/fleet/cron_schedules.go
  • server/fleet/datastore.go
  • server/fleet/software.go
  • server/mock/datastore_mock.go

Comment thread cmd/fleet/cron.go
Comment thread cmd/fleet/cron.go Outdated
Comment thread server/datastore/mysql/software.go
…#36365)

Resolves #36365

The v4.76.0 checksum change (#34097) reordered the fields hashed into
`Software.ComputeRawChecksum` for non-`apps` sources, so software rows created
before the upgrade no longer matched re-ingested rows and got duplicated (same
name/version/source, split host counts).

- Make `ComputeRawChecksum` the sole source of truth and delete the drifted
parallel SQL checksum formula that caused the mismatch.
- Add `ReconcileSoftwareChecksums`, a one-shot migration that merges existing
duplicates onto the canonical row (batched host_software repointing) and logs
each merge. Runs once after startup; re-run with
`fleetctl trigger --name software_checksum_migration`
@juan-fdz-hawa
juan-fdz-hawa force-pushed the 36365-duplicate-software-checksum-dedup branch from 6b01776 to b77a0c1 Compare August 3, 2026 12:58
@juan-fdz-hawa
juan-fdz-hawa marked this pull request as ready for review August 3, 2026 15:33
@juan-fdz-hawa
juan-fdz-hawa requested a review from a team as a code owner August 3, 2026 15:33

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

🧹 Nitpick comments (1)
server/datastore/mysql/software_test.go (1)

14212-14227: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the repointed host links for group 0.

The test forces the repoint loop with 8 host links on the stale row, but it only asserts software row counts. Add an assertion that the surviving pkg0 row carries all 8 host links. This confirms the batched repoint moved every link instead of only the first batch.

♻️ Proposed additional assertion
 	require.Equal(t, groupCount, countDeb())
+	// group 0's 8 host links (> reconcileRepointBatch) all moved onto the survivor.
+	var pkg0Hosts int
+	require.NoError(t, sqlx.GetContext(ctx, ds.reader(ctx), &pkg0Hosts,
+		`SELECT COUNT(*) FROM host_software hs
+		 JOIN software s ON s.id = hs.software_id
+		 WHERE s.name = 'pkg0' AND s.source = 'deb_packages'`))
+	require.Equal(t, len(hosts), pkg0Hosts)
 	var maxPerName int
🤖 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 `@server/datastore/mysql/software_test.go` around lines 14212 - 14227, Extend
the ReconcileSoftwareChecksums test after the existing count assertions to query
the surviving software row for group 0 (pkg0) and assert it has all 8 associated
host links. Use the test’s existing datastore/query helpers and verify the
repoint result specifically for pkg0, confirming every link from the stale row
was moved.
🤖 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.

Nitpick comments:
In `@server/datastore/mysql/software_test.go`:
- Around line 14212-14227: Extend the ReconcileSoftwareChecksums test after the
existing count assertions to query the surviving software row for group 0 (pkg0)
and assert it has all 8 associated host links. Use the test’s existing
datastore/query helpers and verify the repoint result specifically for pkg0,
confirming every link from the stale row was moved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1a210e05-877a-4d9e-99d4-e35befd168c3

📥 Commits

Reviewing files that changed from the base of the PR and between 6b01776 and 0f89b21.

📒 Files selected for processing (11)
  • changes/36365-duplicate-software-checksum
  • cmd/fleet/cron.go
  • cmd/fleet/cron_registration.go
  • server/datastore/mysql/migrations/tables/20231212094238_AddUniqueHashToSoftware.go
  • server/datastore/mysql/software.go
  • server/datastore/mysql/software_test.go
  • server/fleet/cron_schedules.go
  • server/fleet/datastore.go
  • server/fleet/software.go
  • server/mock/datastore_mock.go
  • server/service/integration_core_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • server/fleet/datastore.go
  • cmd/fleet/cron_registration.go
  • changes/36365-duplicate-software-checksum
  • server/fleet/cron_schedules.go
  • server/mock/datastore_mock.go
  • server/datastore/mysql/migrations/tables/20231212094238_AddUniqueHashToSoftware.go
  • server/fleet/software.go
  • server/datastore/mysql/software.go

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.

Duplicate CVE entries for giflib 5.2.2

3 participants