Skip to content

Add migration to prevent deletion of labels referenced by MDM profiles - #46436

Merged
andymFleet merged 8 commits into
mainfrom
45182-cpie-migration-broken-label-prevention
Jun 3, 2026
Merged

Add migration to prevent deletion of labels referenced by MDM profiles#46436
andymFleet merged 8 commits into
mainfrom
45182-cpie-migration-broken-label-prevention

Conversation

@andymFleet

@andymFleet andymFleet commented May 29, 2026

Copy link
Copy Markdown
Contributor

Related issue: Resolves #45182

What this does

Changes the foreign key constraints on mdm_configuration_profile_labels and mdm_declaration_labels from ON DELETE CASCADE (or no restriction) to ON DELETE RESTRICT. This prevents a label from being deleted while it is still referenced by an MDM configuration profile or declaration.

Previously, deleting a label that was targeted by a profile would silently remove the label reference, leaving the profile in a "broken" state in the UI (showing a "Label deleted" warning with no way to recover without re-uploading the profile). With this change, Fleet returns an error when attempting to delete a label that is in use by a profile, prompting the user to remove the profile's label targeting first.

Why

This is part of a broader set of changes (CPIE include/exclude label targeting) that introduces combined include+exclude label targeting on profiles. Allowing silent label deletion would cause ambiguous broken states when both include and exclude labels are in use on a single profile.

Testing

  • Migration tested via the accompanying _test.go file, which covers:
    • Label deletion is blocked when referenced by a configuration profile label row
    • Label deletion is blocked when referenced by a declaration label row
    • Label deletion succeeds when not referenced by any profile or declaration
  • Verified that the ALTER TABLE DDL change does not trigger ON UPDATE CURRENT_TIMESTAMP on mdm_configuration_profile_labels.updated_at (DDL does not fire row-level triggers)

Checklist for submitter

Testing

  • Added/updated automated tests

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.
  • Ensured the correct collation is explicitly set for character columns (COLLATE utf8mb4_unicode_ci).

@andymFleet
andymFleet requested a review from a team as a code owner May 29, 2026 10:36

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

Copilot AI review requested due to automatic review settings May 29, 2026 10:36
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR implements a database migration to enforce referential integrity on label associations. The migration changes the foreign key constraint on mdm_configuration_profile_labels.label_id and mdm_declaration_labels.label_id from ON DELETE SET NULL to ON DELETE RESTRICT, preventing labels from being deleted when referenced by profiles or declarations. The schema is updated to reflect these constraints, and a migration test verifies the new behavior. Existing test scenarios that previously simulated broken labels by deleting referenced labels are updated to use a new simulateBrokenLabel helper that nulls label references instead.

Possibly related PRs

  • fleetdm/fleet#44847: Updates batchSetProfileLabelAssociationsDB and related label association logic to handle existing broken label states using COALESCE and cleanup, which is directly affected by the RESTRICT FK constraint changes.
  • fleetdm/fleet#44983: Modifies the same label association tables and their FK behavior to align with the RESTRICT constraint model for configuration profile and declaration label associations.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main change: adding a migration to prevent label deletion for MDM profiles.
Linked Issues check ✅ Passed The PR fully addresses the coding requirements from issue #45182: migration added with ON DELETE RESTRICT for both tables, schema updated, tests modified to reflect new behavior, and existing broken labels preserved without cleanup.
Out of Scope Changes check ✅ Passed All changes are within scope: migration code, schema updates, and test modifications directly address the foreign key constraint changes required by issue #45182.
Description check ✅ Passed PR description includes related issue, clear what/why sections, testing details, and all relevant database migration checklist items completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 45182-cpie-migration-broken-label-prevention

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 and usage tips.

@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/migrations/tables/20260526192801_RestrictLabelFKOnMDMConfigurationProfileLabels_test.go (1)

23-27: ⚡ Quick win

Split this into per-table assertions.

With both join tables still pointing at the same label on Line 26, this only proves that one FK became RESTRICT. The test would still pass if either mdm_configuration_profile_labels or mdm_declaration_labels were accidentally left on SET NULL. Use separate subtests, or remove one reference before each delete, so each constraint is verified independently.

🤖 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/migrations/tables/20260526192801_RestrictLabelFKOnMDMConfigurationProfileLabels_test.go`
around lines 23 - 27, The test currently deletes the label once and assumes both
FKs are RESTRICT; instead assert each FK independently: create two subtests (or
do two delete attempts) that isolate each join table—e.g., in one subtest delete
the row in mdm_declaration_labels (or remove its reference) and then attempt
DELETE FROM labels WHERE id = labelID to assert an error caused by the
mdm_configuration_profile_labels FK, and in the other subtest remove the
mdm_configuration_profile_labels reference and then assert the DELETE is blocked
by the mdm_declaration_labels FK; keep references to applyNext(t, db), labelID,
db.Exec(...) and the table names mdm_configuration_profile_labels and
mdm_declaration_labels so the assertions verify each constraint independently.
🤖 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/migrations/tables/20260526192801_RestrictLabelFKOnMDMConfigurationProfileLabels_test.go`:
- Around line 23-27: The test currently deletes the label once and assumes both
FKs are RESTRICT; instead assert each FK independently: create two subtests (or
do two delete attempts) that isolate each join table—e.g., in one subtest delete
the row in mdm_declaration_labels (or remove its reference) and then attempt
DELETE FROM labels WHERE id = labelID to assert an error caused by the
mdm_configuration_profile_labels FK, and in the other subtest remove the
mdm_configuration_profile_labels reference and then assert the DELETE is blocked
by the mdm_declaration_labels FK; keep references to applyNext(t, db), labelID,
db.Exec(...) and the table names mdm_configuration_profile_labels and
mdm_declaration_labels so the assertions verify each constraint independently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7081e1f9-ce6e-4f1a-b9ad-db102e857b53

📥 Commits

Reviewing files that changed from the base of the PR and between 157adae and 7f1cf0f.

📒 Files selected for processing (4)
  • server/datastore/mysql/mdm_test.go
  • server/datastore/mysql/migrations/tables/20260526192801_RestrictLabelFKOnMDMConfigurationProfileLabels.go
  • server/datastore/mysql/migrations/tables/20260526192801_RestrictLabelFKOnMDMConfigurationProfileLabels_test.go
  • server/datastore/mysql/schema.sql

@andymFleet
andymFleet marked this pull request as draft May 29, 2026 10:42

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@andymFleet
andymFleet marked this pull request as ready for review May 29, 2026 16:48
@codecov

codecov Bot commented May 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 31.25000% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.89%. Comparing base (d5e0c5d) to head (fd609dc).

Files with missing lines Patch % Lines
..._RestrictLabelFKOnMDMConfigurationProfileLabels.go 31.25% 12 Missing and 10 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #46436      +/-   ##
==========================================
- Coverage   66.89%   66.89%   -0.01%     
==========================================
  Files        2822     2823       +1     
  Lines      224712   224744      +32     
  Branches    11517    11517              
==========================================
+ Hits       150324   150334      +10     
- Misses      60748    60760      +12     
- Partials    13640    13650      +10     
Flag Coverage Δ
backend 68.61% <31.25%> (-0.01%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 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.

@andymFleet
andymFleet marked this pull request as draft May 29, 2026 19:02
@andymFleet
andymFleet marked this pull request as ready for review May 29, 2026 19:47
MagnusHJensen
MagnusHJensen previously approved these changes Jun 1, 2026
@andymFleet
andymFleet force-pushed the 45182-cpie-migration-broken-label-prevention branch from fb0d0bb to 6ad80c3 Compare June 3, 2026 10:04
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test-go (vuln, mysql:8.0.44) / test

Failed stage: Run Go Tests [❌]

Failed test name: TestTranslateCPEToCVE/find_vulns_on_cpes

Failure summary:

The action failed because Go tests in the vuln CI package failed during make test-go:
- Failing
test: TestTranslateCPEToCVE/find_vulns_on_cpes in server/vulnerabilities/nvd/cve_test.go:932.
-
Assertion failure: the returned CVE list for cpe:2.3:a:docker:desktop:4.39.0:::::windows:: did
not include nvd.cve{ID:"CVE-2025-9074", resolvedInVersion:"4.44.3"} (the list only contained
CVE-2025-3224, CVE-2026-2664, and CVE-2025-14740).
- This caused make[1]: *** [Makefile:286:
.run-go-tests] Error 1 and the overall job exited with code 2.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

938:  �[36;1mattempt=1�[0m
939:  �[36;1m�[0m
940:  �[36;1mwhile [ $attempt -le $max_attempts ]; do�[0m
941:  �[36;1m  echo "Attempt $attempt of $max_attempts"�[0m
942:  �[36;1m�[0m
943:  �[36;1m  # Try to connect to MySQL�[0m
944:  �[36;1m  if wait_for_mysql "mysql_test"; then�[0m
945:  �[36;1m    # If MySQL is ready, try to connect to MySQL replica�[0m
946:  �[36;1m    if wait_for_mysql "mysql_replica_test"; then�[0m
947:  �[36;1m      # Both are ready, we're done�[0m
948:  �[36;1m      echo "All MySQL connections successful"�[0m
949:  �[36;1m      exit 0�[0m
950:  �[36;1m    fi�[0m
951:  �[36;1m  fi�[0m
952:  �[36;1m�[0m
953:  �[36;1m  # If we get here, at least one connection failed�[0m
954:  �[36;1m  echo "Failed to connect to MySQL on attempt $attempt"�[0m
955:  �[36;1m�[0m
956:  �[36;1m  if [ $attempt -lt $max_attempts ]; then�[0m
957:  �[36;1m    echo "Restarting containers and trying again..."�[0m
958:  �[36;1m    restart_containers�[0m
959:  �[36;1m  else�[0m
960:  �[36;1m    echo "Maximum attempts reached. Failing the job."�[0m
961:  �[36;1m    exit 1�[0m
...

1092:  �[32m✓�[0m Is server core (0.00s)
1093:  �[32m✓�[0m Matches (0.00s)
1094:  �[32m✓�[0m Matches from differect arch (0.00s)
1095:  �[32m✓�[0m Matches from differect products (0.00s)
1096:  �[32m✓�[0m Matches operating system (0.00s)
1097:  �[32m✓�[0m Matches same product but for different architecture (0.00s)
1098:  �[32m✓�[0m Matches same product one with no architecture (0.00s)
1099:  �[32m✓�[0m Matches same product same arch (0.00s)
1100:  �[32m✓�[0m New product from OS (0.00s)
1101:  �[32m✓�[0m Product has display version (0.00s)
1102:  �[32m✓�[0m Security bulletin (0.00s)
1103:  �[32m✓�[0m Security bulletin # merge (0.00s)
1104:  �[32m✓�[0m Security bulletin # merge . products (0.00s)
1105:  �[32m✓�[0m Security bulletin # merge . vendor fixes (0.00s)
1106:  �[32m✓�[0m Security bulletin # merge . vulnerabilities (0.00s)
1107:  �[32m✓�[0m Security bulletin # merge fails if product names don't match (0.00s)
1108:  �[32m✓�[0m Security bulletin # merge with empty bulletins (0.00s)
1109:  �[32m✓�[0m Security bulletin # unmarshal JSON (0.00s)
1110:  �[32m✓�[0m Security bulletin # unmarshal JSON accepts new vulnerabilities key (0.00s)
1111:  �[32m✓�[0m Security bulletin # unmarshal JSON accepts old misspelled vulnerabities key (0.00s)
1112:  �[32m✓�[0m Security bulletin # unmarshal JSON marshal uses correct spelling (0.00s)
1113:  github.com/fleetdm/fleet/v4/server/vulnerabilities/goval_dictionary:
1114:  �[32m✓�[0m Database (0.00s)
1115:  �[32m✓�[0m Database close releases file handle (0.04s)
1116:  �[32m✓�[0m Database fixed version (0.00s)
1117:  �[32m✓�[0m Database multiple packages, fixed version (0.00s)
1118:  �[32m✓�[0m Database multiple packages, multiple vulnerabilities (0.00s)
1119:  �[32m✓�[0m Database newer than fixed version (0.00s)
1120:  �[32m✓�[0m Database non-matching architecture (0.00s)
1121:  �[32m✓�[0m Database non-matching package name (0.00s)
1122:  �[32m✓�[0m Database older than fixed version (0.00s)
1123:  �[32m✓�[0m Database verify returns no errors (0.00s)
1124:  �[32m✓�[0m Sync (0.00s)
1125:  �[32m✓�[0m Sync #what to download (0.00s)
1126:  �[32m✓�[0m Verify (0.00s)
1127:  �[32m✓�[0m Verify verify alerts of error (0.00s)
1128:  github.com/fleetdm/fleet/v4/server/vulnerabilities/msrc:
...

1159:  �[32m✓�[0m Parser (0.25s)
1160:  �[32m✓�[0m Parser map to security bulletins (0.00s)
1161:  �[32m✓�[0m Parser map to security bulletins each bulletin should have the right products (0.00s)
1162:  �[32m✓�[0m Parser map to security bulletins each bulletin should have the right vulnerabilities (0.00s)
1163:  �[32m✓�[0m Parser map to security bulletins should have one bulletin per product (0.00s)
1164:  �[32m✓�[0m Parser map to security bulletins should map the vendor fixes entries correctly (0.00s)
1165:  �[32m✓�[0m Parser map to security bulletins should map the vulnerability entries correctly (0.00s)
1166:  �[32m✓�[0m Parser parse XML (0.09s)
1167:  �[32m✓�[0m Parser parse XML only CVEs for windows products are included (0.00s)
1168:  �[32m✓�[0m Parser parse XML only windows products are included (0.00s)
1169:  �[32m✓�[0m Parser parse XML scores are parsed correctly (0.00s)
1170:  �[32m✓�[0m Parser parse XML should include windows server 2025 from 202 6- feb feed (0.08s)
1171:  �[32m✓�[0m Parser parse XML the remediations are parsed correctly (0.00s)
1172:  �[32m✓�[0m Parser parse XML the revision history is parsed correctly (0.00s)
1173:  �[32m✓�[0m Parser parse feed (0.00s)
1174:  �[32m✓�[0m Parser parse feed errors out if file does not exists (0.00s)
1175:  �[32m✓�[0m Sync (0.00s)
...

1312:  �[32m✓�[0m Extract ubuntu version future version 2 5.04 (0.00s)
1313:  �[32m✓�[0m Extract ubuntu version interim release 2 3.10 (0.00s)
1314:  �[32m✓�[0m Extract ubuntu version interim release 2 4.10 with patch (0.00s)
1315:  �[32m✓�[0m Extract ubuntu version invalid version - single digit (0.00s)
1316:  �[32m✓�[0m Extract ubuntu version ubuntu 1 6.04 with extra spaces (0.00s)
1317:  �[32m✓�[0m Extract ubuntu version ubuntu 1 8.04 (0.00s)
1318:  �[32m✓�[0m Extract ubuntu version ubuntu 2 0.04 LTS (0.00s)
1319:  �[32m✓�[0m Extract ubuntu version ubuntu 2 2.04 LTS (0.00s)
1320:  �[32m✓�[0m Extract ubuntu version ubuntu 2 4.04 no LTS suffix (0.00s)
1321:  �[32m✓�[0m Extract ubuntu version version with codename suffix (0.00s)
1322:  �[32m✓�[0m Extract ubuntu version very old version 1 4.04 (0.00s)
1323:  �[32m✓�[0m Find latest OSV artifact for version (0.00s)
1324:  �[32m✓�[0m Find latest OSV artifact for version finds latest 1 8.04 artifact (0.00s)
1325:  �[32m✓�[0m Find latest OSV artifact for version finds latest 2 0.04 artifact (0.00s)
1326:  �[32m✓�[0m Find latest OSV artifact for version finds latest 2 2.04 artifact (0.00s)
1327:  �[32m✓�[0m Find latest OSV artifact for version returns error for non-existent version (0.00s)
1328:  �[32m✓�[0m Get needed RHEL versions (0.00s)
...

1400:  �[32m✓�[0m Normalize kernel version generic 6 4k kernel (0.00s)
1401:  �[32m✓�[0m Normalize kernel version generic kernel (0.00s)
1402:  �[32m✓�[0m Normalize kernel version kernel with only one part (0.00s)
1403:  �[32m✓�[0m Normalize kernel version lowlatency kernel (0.00s)
1404:  �[32m✓�[0m OSV filename (0.00s)
1405:  �[32m✓�[0m OSV filename 1804 (0.00s)
1406:  �[32m✓�[0m OSV filename 2004 (0.00s)
1407:  �[32m✓�[0m OSV filename 2204 (0.00s)
1408:  �[32m✓�[0m RHELOSV filename (0.00s)
1409:  �[32m✓�[0m RHELOSV filename 10 (0.00s)
1410:  �[32m✓�[0m RHELOSV filename 8 (0.00s)
1411:  �[32m✓�[0m RHELOSV filename 9 (0.00s)
1412:  �[32m✓�[0m Release date from assets (0.00s)
1413:  �[32m✓�[0m Remove old OSV artifacts (0.00s)
1414:  �[32m✓�[0m Remove old OSV artifacts date boundary race (0.00s)
1415:  �[32m✓�[0m Remove old OSV artifacts preserves failed versions (0.00s)
1416:  �[32m✓�[0m Remove old OSV artifacts with skipped versions (0.01s)
1417:  �[32m✓�[0m Remove old RHELOSV artifacts (0.00s)
1418:  �[32m✓�[0m Sync OSV checksum match (0.00s)
1419:  �[32m✓�[0m Sync OSV fault tolerance (0.00s)
1420:  �[32m✓�[0m Sync OSV partial failure not returned as error (0.00s)
1421:  �[32m✓�[0m Version from asset name (0.00s)
...

1454:  �[32m✓�[0m CVE use existing sync cve-2. 0 .xml.gz (0.01s)
1455:  �[32m✓�[0m CVE use existing sync cve-2. 0 .xml.zip (0.01s)
1456:  �[33m∅�[0m End to end (0.00s)
1457:  �[32m✓�[0m Response not OK (0.00s)
1458:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval/input:
1459:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval/parsed:
1460:  �[32m✓�[0m Dpkg info test eval no host list (0.00s)
1461:  �[32m✓�[0m Dpkg info test eval no host list # eval (0.00s)
1462:  �[32m✓�[0m Dpkg info test eval no host list # eval test matches n objects (0.00s)
1463:  �[32m✓�[0m Dpkg info test eval no host list # eval test matches n states (0.00s)
1464:  �[32m✓�[0m Dpkg info test eval no host list # eval with no packages (0.00s)
1465:  �[32m✓�[0m Eval (0.00s)
1466:  �[32m✓�[0m Eval alt pattern match (0.00s)
1467:  �[32m✓�[0m Eval equal (0.00s)
1468:  �[32m✓�[0m Eval greater than (0.00s)
1469:  �[32m✓�[0m Eval higher version fails pattern match (0.00s)
1470:  �[32m✓�[0m Eval kernel (0.00s)
1471:  �[32m✓�[0m Eval less than (0.00s)
1472:  �[32m✓�[0m Eval lower version fails pattern match (0.00s)
1473:  �[32m✓�[0m Eval suffix doesn't match (0.00s)
...

1485:  �[32m✓�[0m Object info state # eval OS version name (0.00s)
1486:  �[32m✓�[0m Object info state # eval OS version version (0.00s)
1487:  �[32m✓�[0m Object info state # eval software (0.00s)
1488:  �[32m✓�[0m Object info state # eval software arch (0.00s)
1489:  �[32m✓�[0m Object info state # eval software evr (0.00s)
1490:  �[32m✓�[0m Object info state # eval software name (0.00s)
1491:  �[32m✓�[0m Object info state # eval software release (0.00s)
1492:  �[32m✓�[0m Object info state # eval software signature key id (0.00s)
1493:  �[32m✓�[0m Object info state # eval software version (0.00s)
1494:  �[32m✓�[0m Object match type (0.00s)
1495:  �[32m✓�[0m Object match type # eval (0.00s)
1496:  �[32m✓�[0m Object match type new object match type (0.00s)
1497:  �[32m✓�[0m Object state evr string (0.00s)
1498:  �[32m✓�[0m Object state evr string # eval (0.00s)
1499:  �[32m✓�[0m Object state evr string # eval evaluates an evr string (0.00s)
1500:  �[32m✓�[0m Object state evr string # eval it errors out if operation can not be computed (0.00s)
1501:  �[32m✓�[0m Object state simple value (0.01s)
1502:  �[32m✓�[0m Object state simple value # eval (0.01s)
1503:  �[32m✓�[0m Object state simple value # eval compares simple data types (0.01s)
1504:  �[32m✓�[0m Object state simple value # eval compares simple data types booleans (0.00s)
1505:  �[32m✓�[0m Object state simple value # eval compares simple data types floats (0.00s)
1506:  �[32m✓�[0m Object state simple value # eval compares simple data types ints (0.00s)
1507:  �[32m✓�[0m Object state simple value # eval compares simple data types strings (0.01s)
1508:  �[32m✓�[0m Object state simple value # eval it errors out if complex type used (0.00s)
1509:  �[32m✓�[0m Object state simple value #unpack (0.00s)
1510:  �[32m✓�[0m Object state simple value new object state simple value (0.00s)
1511:  �[32m✓�[0m Object state string (0.00s)
1512:  �[32m✓�[0m Object state string # eval (0.00s)
1513:  �[32m✓�[0m Object state string # eval it errors out if operation can not be computed (0.00s)
1514:  �[32m✓�[0m Object state string # eval it errors out if regexp can not be parsed (0.00s)
1515:  �[32m✓�[0m Object state string # eval it evaluates string values (0.00s)
...

1546:  �[32m✓�[0m Vulns delta existing differ from found (0.00s)
1547:  �[32m✓�[0m Vulns delta existing match found (0.00s)
1548:  �[32m✓�[0m Vulns delta no existing vulnerabilities (0.00s)
1549:  �[32m✓�[0m Vulns delta nothing found but vulns exist (0.00s)
1550:  github.com/fleetdm/fleet/v4/server/vulnerabilities/nvd/tools/providers/lib/rate:
1551:  github.com/fleetdm/fleet/v4/server/vulnerabilities/nvd/tools/providers/lib/client:
1552:  github.com/fleetdm/fleet/v4/server/vulnerabilities/macoffice:
1553:  �[32m✓�[0m Analyzer (0.00s)
1554:  �[32m✓�[0m Analyzer analyze (0.00s)
1555:  �[32m✓�[0m Analyzer analyze when no release notes on path (0.00s)
1556:  �[32m✓�[0m Analyzer analyze when release notes contain no valid security updates (0.00s)
1557:  �[32m✓�[0m Analyzer analyze when using wrong path (0.00s)
1558:  �[32m✓�[0m Analyzer collect vulnerabilities (0.00s)
1559:  �[32m✓�[0m Analyzer collect vulnerabilities no release notes (0.00s)
1560:  �[32m✓�[0m Analyzer get stored vulnerabilities (0.00s)
1561:  �[32m✓�[0m Analyzer get stored vulnerabilities on error (0.00s)
1562:  �[32m✓�[0m Analyzer latest release notes (0.00s)
1563:  �[32m✓�[0m Analyzer latest release notes returns release notes in order (0.00s)
1564:  �[32m✓�[0m Analyzer latest release notes when the JSON file is invalid (0.00s)
1565:  �[32m✓�[0m Analyzer latest release notes when vuln path does not exists (0.00s)
1566:  �[32m✓�[0m Analyzer latest release notes when vuln path exists (0.00s)
1567:  �[32m✓�[0m Analyzer update vulns in DB (0.00s)
1568:  �[32m✓�[0m Analyzer update vulns in DB on error when deleting vulns (0.00s)
1569:  �[32m✓�[0m Analyzer update vulns in DB on error when inserting vulns (0.00s)
1570:  �[32m✓�[0m Build number (0.00s)
...

1576:  �[32m✓�[0m Integrations parse release HTML (0.23s)
1577:  �[32m✓�[0m Integrations parse release HTML should parse dates (0.01s)
1578:  �[32m✓�[0m Integrations parse release HTML should parse release versions (0.00s)
1579:  �[32m✓�[0m Integrations parse release HTML should parse security updates (0.00s)
1580:  �[32m✓�[0m Integrations sync (0.56s)
1581:  �[32m✓�[0m Release note (0.00s)
1582:  �[32m✓�[0m Release note # cmp version (0.00s)
1583:  �[32m✓�[0m Release note # cmp version when release version is newer than (0.00s)
1584:  �[32m✓�[0m Release note # cmp version when release version is older than (0.00s)
1585:  �[32m✓�[0m Release note # cmp version when the same (0.00s)
1586:  �[32m✓�[0m Release note # collect vulnerabilities (0.00s)
1587:  �[32m✓�[0m Release note # office product from bundle id (0.00s)
1588:  �[32m✓�[0m Short version format (0.00s)
1589:  �[32m✓�[0m Sync (0.00s)
1590:  �[32m✓�[0m Sync #sync (0.00s)
1591:  �[32m✓�[0m Sync #sync on FS error (0.00s)
1592:  �[32m✓�[0m Sync #sync on GH error (0.00s)
1593:  �[32m✓�[0m Sync #sync on error when deleting (0.00s)
1594:  �[32m✓�[0m Sync #sync on error when downloading GH asset (0.00s)
1595:  �[32m✓�[0m Sync #sync removes multiple out of date copies (0.00s)
...

1598:  �[32m✓�[0m Sync #sync when nothing published on GH (0.00s)
1599:  �[32m✓�[0m Sync #sync when there are no local files (0.00s)
1600:  �[32m✓�[0m Sync #sync when there are no remote rel notes (0.00s)
1601:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval:
1602:  �[32m✓�[0m Oval analyzer (0.00s)
1603:  �[32m✓�[0m Oval analyzer #load (0.00s)
1604:  �[32m✓�[0m Oval analyzer #load invalid vuln path (0.00s)
1605:  �[32m✓�[0m Oval analyzer #load rejects empty definition file (0.00s)
1606:  �[32m✓�[0m Oval analyzer analyzing RHEL software (11.56s)
1607:  �[32m✓�[0m Oval analyzer analyzing ubuntu software (7.35s)
1608:  �[32m✓�[0m Oval download definitions matching host info (0.00s)
1609:  �[32m✓�[0m Oval download definitions platform not found (0.00s)
1610:  �[32m✓�[0m Oval mapper (0.00s)
1611:  �[32m✓�[0m Oval mapper #extract id (0.00s)
1612:  �[32m✓�[0m Oval mapper #map criteria (0.00s)
1613:  �[32m✓�[0m Oval mapper #map criteria errors out if id can not be parsed on any criterion (0.00s)
1614:  �[32m✓�[0m Oval mapper #map criteria errors out if no criteriums or nested criterias (0.00s)
1615:  �[32m✓�[0m Oval mapper #map criteria maps criteriums (0.00s)
1616:  �[32m✓�[0m Oval mapper #map criteria maps nested criterias (0.00s)
1617:  �[32m✓�[0m Oval mapper #map definition (0.00s)
1618:  �[32m✓�[0m Oval mapper #map definition errors out if no vulnerabilities (0.00s)
1619:  �[32m✓�[0m Oval mapper #map dpkg info state (0.00s)
1620:  �[32m✓�[0m Oval mapper #map dpkg info state errors out if one of non-supported state information is provided (0.00s)
1621:  �[32m✓�[0m Oval mapper #map dpkg info test (0.00s)
1622:  �[32m✓�[0m Oval mapper #map dpkg info test errors out if id can not be parsed (0.00s)
1623:  �[32m✓�[0m Oval mapper #map dpkg info test maps a dpkg info test XML (0.00s)
1624:  �[32m✓�[0m Oval mapper #map package info test object (0.00s)
1625:  �[32m✓�[0m Oval mapper #map package info test object name defined in var ref (0.00s)
1626:  �[32m✓�[0m Oval mapper #map package info test object name defined inline (0.00s)
1627:  �[32m✓�[0m Oval mapper #map package info test object name not defined inline nor using a variable ref (0.00s)
1628:  �[32m✓�[0m Oval mapper #map rpm info state (0.00s)
1629:  �[32m✓�[0m Oval mapper #map rpm info state errors out if not supported state is provided (0.00s)
1630:  �[32m✓�[0m Oval mapper #map rpm info state maps a rpm info state XML (0.00s)
1631:  �[32m✓�[0m Oval mapper #map rpm info state maps the operator, if any (0.00s)
1632:  �[32m✓�[0m Oval mapper #map rpm info test (0.00s)
1633:  �[32m✓�[0m Oval mapper #map rpm info test errors out if id can not be parsed (0.00s)
1634:  �[32m✓�[0m Oval mapper #map rpm info test maps a rpm info test XML (0.00s)
1635:  �[32m✓�[0m Oval mapper #map rpm verify file object (0.00s)
1636:  �[32m✓�[0m Oval mapper #map rpm verify file object errors out if invalid children provided (0.00s)
1637:  �[32m✓�[0m Oval mapper #map rpm verify file object maps to a filepath (0.00s)
1638:  �[32m✓�[0m Oval mapper #map rpm verify file state (0.00s)
1639:  �[32m✓�[0m Oval mapper #map rpm verify file state errors out if not supported state is provided (0.00s)
1640:  �[32m✓�[0m Oval mapper #map rpm verify file state maps a rpm verify file state XML (0.00s)
...

1722:  �[32m✓�[0m Integration check version unknown version returns no vulnerabilities (0.00s)
1723:  �[32m✓�[0m Integration check version version not in bulletin returns empty (0.00s)
1724:  �[32m✓�[0m Parse office version (0.00s)
1725:  �[32m✓�[0m Parse office version invalid version - no prefix (0.00s)
1726:  �[32m✓�[0m Parse office version invalid version - too few parts (0.00s)
1727:  �[32m✓�[0m Parse office version invalid version - wrong prefix (0.00s)
1728:  �[32m✓�[0m Parse office version valid version (0.00s)
1729:  �[32m✓�[0m Parse security markdown (0.00s)
1730:  �[32m✓�[0m Parse security markdown keeps minimum build suffix for same version (0.00s)
1731:  �[32m✓�[0m Parse security markdown parses LTSC versions (0.00s)
1732:  �[32m✓�[0m Parse security markdown parses multiple releases (0.00s)
1733:  �[32m✓�[0m Parse security markdown parses single release with multiple versions (0.00s)
1734:  �[32m✓�[0m Parse security markdown skips releases without CVEs (0.00s)
1735:  �[32m✓�[0m Parse security markdown skips retail versions (0.00s)
1736:  �[32m✓�[0m Sync bulletin (0.00s)
1737:  �[32m✓�[0m Sync bulletin on FS error (0.00s)
1738:  �[32m✓�[0m Sync bulletin on GH error (0.00s)
1739:  �[32m✓�[0m Sync bulletin on error when deleting (0.00s)
1740:  �[32m✓�[0m Sync bulletin on error when downloading GH asset (0.00s)
1741:  �[32m✓�[0m Sync bulletin removes multiple out of date copies (0.00s)
...

1868:  �[32m✓�[0m FS client (0.00s)
1869:  �[32m✓�[0m FS client #MSRC bulletins (0.00s)
1870:  �[32m✓�[0m FS client #MSRC bulletins directory does not exists (0.00s)
1871:  �[32m✓�[0m FS client #MSRC bulletins returns a list of file matching the MSRC file prefix (0.00s)
1872:  �[32m✓�[0m FS client delete (0.00s)
1873:  �[32m✓�[0m FS client delete file does not exists (0.00s)
1874:  �[32m✓�[0m FS client mac office release notes (0.00s)
1875:  �[32m✓�[0m FS client mac office release notes directory does not exists (0.00s)
1876:  �[32m✓�[0m FS client mac office release notes returns a list of file matching the mac office file prefix (0.00s)
1877:  �[32m✓�[0m FS client mac office release notes when files contain the wrong date format (0.00s)
1878:  �[32m✓�[0m Integrations github client (294.05s)
1879:  �[32m✓�[0m Integrations github client # download (294.05s)
1880:  �[32m✓�[0m Integrations github client # download with invalid URL (294.04s)
1881:  �[32m✓�[0m Integrations github client #MSRC bulletins (0.00s)
1882:  �[32m✓�[0m Integrations github client mac office release notes (0.00s)
1883:  �[32m✓�[0m Integrations github client mac office release notes on error (0.00s)
1884:  �[32m✓�[0m Integrations github client mac office release notes with HTTP error code (0.00s)
1885:  �[32m✓�[0m Integrations github client mac office release notes with a single release note asset (0.00s)
...

1892:  �[32m✓�[0m Security bulletin name # before when b is empty (0.00s)
1893:  �[32m✓�[0m Security bulletin name # product name (0.00s)
1894:  �[32m✓�[0m Security bulletin name #date (0.00s)
1895:  �[32m✓�[0m Security bulletin name MSRC file name (0.00s)
1896:  �[32m✓�[0m Security bulletin name date not included in filename (0.00s)
1897:  �[32m✓�[0m Security bulletin name mac office rel notes file name (0.00s)
1898:  �[32m✓�[0m Security bulletin name product name not included in filename (0.00s)
1899:  �[32m✓�[0m Security bulletin name string (0.00s)
1900:  �[32m✓�[0m Security bulletin name validates timestamp on filename at construction time (0.00s)
1901:  �[32m✓�[0m Security bulletin name win office file name (0.00s)
1902:  === �[33mSkipped�[0m
1903:  === �[33mSKIP�[0m: server/vulnerabilities/nvd/tools/providers/nvd TestEndToEnd (0.00s)
1904:  e2e_test.go:45: e2e tests not enabled
1905:  === �[33mSKIP�[0m: server/vulnerabilities/vulntest TestGenerateVulnFixtures (0.00s)
1906:  gen_fixture_test.go:123: set GENERATE_FIXTURES=1 to run this test
1907:  === �[31mFailed�[0m
1908:  === �[31mFAIL�[0m: server/vulnerabilities/nvd TestTranslateCPEToCVE/find_vulns_on_cpes (33.20s)
1909:  cve_test.go:932: 
1910:  Error Trace:	/home/runner/work/fleet/fleet/server/vulnerabilities/nvd/cve_test.go:932
1911:  Error:      	[]nvd.cve{nvd.cve{ID:"CVE-2025-3224", resolvedInVersion:"4.41.0"}, nvd.cve{ID:"CVE-2026-2664", resolvedInVersion:"4.62.0"}, nvd.cve{ID:"CVE-2025-14740", resolvedInVersion:""}} does not contain nvd.cve{ID:"CVE-2025-9074", resolvedInVersion:"4.44.3"}
1912:  Test:       	TestTranslateCPEToCVE/find_vulns_on_cpes
1913:  Messages:   	cpe:2.3:a:docker:desktop:4.39.0:*:*:*:*:windows:*:* does not contain CVE nvd.cve{ID:"CVE-2025-9074", resolvedInVersion:"4.44.3"}
1914:  --- FAIL: TestTranslateCPEToCVE/find_vulns_on_cpes (33.20s)
1915:  === �[31mFAIL�[0m: server/vulnerabilities/nvd TestTranslateCPEToCVE (7.86s)
1916:  DONE 832 tests, 2 skipped, 2 failures in 295.459s
1917:  make[1]: *** [Makefile:286: .run-go-tests] Error 1
1918:  make[1]: Leaving directory '/home/runner/work/fleet/fleet'
1919:  make: *** [Makefile:401: test-go] Error 2
1920:  ##[error]Process completed with exit code 2.
1921:  ##[group]Run actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
1922:  with:
1923:  name: vuln-mysql8.0.44-coverage
1924:  path: ./coverage.txt
1925:  if-no-files-found: error
1926:  compression-level: 6
...

1938:  With the provided path, there will be 1 file uploaded
1939:  Artifact name is valid!
1940:  Root directory input is valid!
1941:  Beginning upload of artifact content to blob storage
1942:  Uploaded bytes 1995740
1943:  Finished uploading artifact content to blob storage!
1944:  SHA256 hash of uploaded artifact zip is af79a866c490019f32e349cf90ec3253dad1c23b0a0e24f85d09e4a422bfd70e
1945:  Finalizing artifact upload
1946:  Artifact vuln-mysql8.0.44-coverage.zip successfully finalized. Artifact ID 7383499389
1947:  Artifact vuln-mysql8.0.44-coverage has been successfully uploaded! Final size is 1995740 bytes. Artifact ID is 7383499389
1948:  Artifact download URL: https://github.com/fleetdm/fleet/actions/runs/26881875493/artifacts/7383499389
1949:  ##[group]Run c1grep() { grep "$@" || test $? = 1; }
1950:  �[36;1mc1grep() { grep "$@" || test $? = 1; }�[0m
1951:  �[36;1mc1grep -oP 'FAIL: .*$' /tmp/gotest.log > /tmp/summary.txt�[0m
1952:  �[36;1mc1grep 'test timed out after' /tmp/gotest.log >> /tmp/summary.txt�[0m
1953:  �[36;1mc1grep 'fatal error:' /tmp/gotest.log >> /tmp/summary.txt�[0m
1954:  �[36;1mc1grep -A 10 'panic: runtime error: ' /tmp/gotest.log >> /tmp/summary.txt�[0m
1955:  �[36;1mc1grep ' FAIL\t' /tmp/gotest.log >> /tmp/summary.txt�[0m
1956:  �[36;1mGO_FAIL_SUMMARY=$(head -n 5 /tmp/summary.txt | sed ':a;N;$!ba;s/\n/\\n/g')�[0m
1957:  �[36;1mecho "GO_FAIL_SUMMARY=$GO_FAIL_SUMMARY"�[0m
1958:  �[36;1mif [[ -z "$GO_FAIL_SUMMARY" ]]; then�[0m
1959:  �[36;1m  GO_FAIL_SUMMARY="unknown, please check the build URL"�[0m
1960:  �[36;1mfi�[0m
1961:  �[36;1mGO_FAIL_SUMMARY=$GO_FAIL_SUMMARY envsubst < .github/workflows/config/slack_payload_template.json > ./payload.json�[0m
1962:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
1963:  env:
1964:  RACE_ENABLED: false
1965:  GO_TEST_TIMEOUT: 20m
1966:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
1967:  RUN_TESTS_ARG: 
1968:  CI_TEST_PKG: vuln
1969:  NEED_DOCKER: 1
1970:  ARTIFACT_PREFIX: vuln-mysql8.0.44
1971:  GOTOOLCHAIN: local
1972:  ##[endgroup]
1973:  GO_FAIL_SUMMARY=FAIL: TestTranslateCPEToCVE/find_vulns_on_cpes (33.20s)
1974:  ##[group]Run actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
1975:  with:
1976:  name: vuln-mysql8.0.44-test-log
1977:  path: /tmp/gotest.log
1978:  if-no-files-found: error
1979:  compression-level: 6

@andymFleet
andymFleet merged commit 995d366 into main Jun 3, 2026
40 of 42 checks passed
@andymFleet
andymFleet deleted the 45182-cpie-migration-broken-label-prevention branch June 3, 2026 12:41
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.

CPIE: Migration for broken label prevention

4 participants