Skip to content

Fix fleetctl apply ignoring spec.fleet - #44894

Merged
sgress454 merged 3 commits into
mainfrom
fleetctl-apply-fleet
May 29, 2026
Merged

Fix fleetctl apply ignoring spec.fleet#44894
sgress454 merged 3 commits into
mainfrom
fleetctl-apply-fleet

Conversation

@spalmesano0

@spalmesano0 spalmesano0 commented May 6, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #44892

Claude also added tests, since this wasn't covered before, but I've kept them in a separate commit in case they're not needed.

Checklist for submitter

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • Bug Fixes

    • Improved spec parsing to correctly accept resources declared as either team or fleet, handling nested spec keys consistently and preserving backward-compatible behavior.
  • Tests

    • Added and updated tests and fixtures to validate parsing across both team/fleet variants and to assert specific conflict/reporting behavior when both keys are present.

Review Change Stack

@spalmesano0 spalmesano0 self-assigned this May 6, 2026
Copilot AI review requested due to automatic review settings May 6, 2026 22:24
@spalmesano0
spalmesano0 requested a review from a team as a code owner May 6, 2026 22:24

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

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 pkg/spec/spec.go Outdated
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af22796b-a3dd-43c3-8395-8588fec26b40

📥 Commits

Reviewing files that changed from the base of the PR and between 22c9ad4 and 91768b2.

📒 Files selected for processing (3)
  • cmd/fleetctl/fleetctl/apply_test.go
  • pkg/spec/spec.go
  • pkg/spec/spec_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/spec/spec_test.go

Walkthrough

GroupFromBytes now prefers the nested "fleet" key when parsing resources with kind set to fleet or team, falling back to "team" if "fleet" is absent. The selected nested payload is passed through rewriteNewToOldKeys and appended to specs.Teams. Unit tests were added/adjusted to assert correct parsing for both kind: team and kind: fleet and to tighten alias-conflict error fields. Test YAML fixtures in fleetctl apply tests were updated to use spec.fleet for kind: fleet scenarios.

Possibly related PRs

  • fleetdm/fleet#40586: Directly overlaps with changes to GroupFromBytes for handling team and fleet kind specifications.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes the related issue number (#44892), notes that tests were added, and marks automated tests as completed. However, it lacks most template sections including changes files, validation details, database migration checks, and other required items. Fill out the complete PR description template with sections for changes files, security validation, testing approach, and other applicable checklist items to ensure proper review context.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix fleetctl apply ignoring spec.fleet' directly describes the main issue being resolved and matches the primary objective of making the apply command accept the spec.fleet key format.
Linked Issues check ✅ Passed The code changes align with the linked issue requirements: they enable backward-compatible parsing of spec.fleet in the YAML parsing logic, add test coverage for both spec.team and spec.fleet formats, and update test fixtures to validate the fixed behavior.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving issue #44892: updating the parsing logic in spec.go, adding corresponding test coverage in spec_test.go, and updating existing test fixtures in apply_test.go to validate the new functionality.

✏️ 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 fleetctl-apply-fleet

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/spec/spec.go (1)

237-243: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a nil guard for teamRaw after the map lookup.

If the YAML spec body contains neither a team: nor a fleet: key that matches kind (e.g. kind: fleet with a spec.team: body), rawTeam[kind] returns a nil json.RawMessage. That nil is passed to rewriteNewToOldKeys and then appended to specs.Teams, which causes a confusing unmarshal failure downstream rather than an actionable error here.

🛡️ Proposed fix
 teamRaw := rawTeam[kind]
+if teamRaw == nil {
+    return nil, fmt.Errorf("spec.%s is missing or empty for kind %q", kind, s.Kind)
+}
 var err error
🤖 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 `@pkg/spec/spec.go` around lines 237 - 243, After fetching teamRaw :=
rawTeam[kind] add a nil-check and return a clear error if teamRaw == nil instead
of passing it to rewriteNewToOldKeys or appending it to specs.Teams;
specifically, in the block that uses rawTeam[kind], validate teamRaw is non-nil
(use kind in the error message), then call rewriteNewToOldKeys(teamRaw,
fleet.TeamSpec{}) and only append the returned teamRaw to specs.Teams when
non-nil — this prevents passing nil json.RawMessage into rewriteNewToOldKeys and
avoids appending a nil entry to specs.Teams.
🧹 Nitpick comments (1)
pkg/spec/spec_test.go (1)

464-505: 💤 Low value

Consider adding a mismatch test case to TestGroupFromBytesTeamKinds.

The new test covers kind: team / spec.team and kind: fleet / spec.fleet (the happy paths), but not the cross-key mismatch (kind: fleet with a spec.team body, or vice versa). That path currently produces a nil entry in specs.Teams without an error. Adding a table entry for the mismatch would both document the expected behaviour and serve as a regression guard if the nil-guard fix above is applied.

➕ Suggested additional test case
 	{
 		"kind: fleet with fleet: key",
 		[]byte(`
 apiVersion: v1
 kind: fleet
 spec:
   fleet:
     name: macOS
 `),
 	},
+	// Mismatch: kind says "fleet" but spec key is "team".
+	// With a proper nil guard this should return an error.
+	// Uncomment / adjust expected behaviour once the nil guard is in place.
 }
🤖 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 `@pkg/spec/spec_test.go` around lines 464 - 505, Add a negative table case to
TestGroupFromBytesTeamKinds that exercises the cross-key mismatch (e.g. kind:
fleet but spec: team) by adding a test input byte block with "kind: fleet" and a
"spec: team: name: macOS" body and then in the t.Run assert the current observed
behavior: GroupFromBytes returns no error, g.Teams has length 1 and g.Teams[0]
is nil (use require.NoError(t, err); require.Len(t, g.Teams, 1); require.Nil(t,
g.Teams[0])). This documents the mismatch behavior and will catch regressions in
GroupFromBytes or specs.Teams handling.
🤖 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.

Outside diff comments:
In `@pkg/spec/spec.go`:
- Around line 237-243: After fetching teamRaw := rawTeam[kind] add a nil-check
and return a clear error if teamRaw == nil instead of passing it to
rewriteNewToOldKeys or appending it to specs.Teams; specifically, in the block
that uses rawTeam[kind], validate teamRaw is non-nil (use kind in the error
message), then call rewriteNewToOldKeys(teamRaw, fleet.TeamSpec{}) and only
append the returned teamRaw to specs.Teams when non-nil — this prevents passing
nil json.RawMessage into rewriteNewToOldKeys and avoids appending a nil entry to
specs.Teams.

---

Nitpick comments:
In `@pkg/spec/spec_test.go`:
- Around line 464-505: Add a negative table case to TestGroupFromBytesTeamKinds
that exercises the cross-key mismatch (e.g. kind: fleet but spec: team) by
adding a test input byte block with "kind: fleet" and a "spec: team: name:
macOS" body and then in the t.Run assert the current observed behavior:
GroupFromBytes returns no error, g.Teams has length 1 and g.Teams[0] is nil (use
require.NoError(t, err); require.Len(t, g.Teams, 1); require.Nil(t,
g.Teams[0])). This documents the mismatch behavior and will catch regressions in
GroupFromBytes or specs.Teams handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 82188624-74e2-4b0b-a0bc-634f188ccf80

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd0753 and 22c9ad4.

📒 Files selected for processing (2)
  • pkg/spec/spec.go
  • pkg/spec/spec_test.go

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.

Pull request overview

This PR fixes fleetctl apply failing to apply team/fleet specs when YAML uses the newer spec.fleet wrapper (as produced by fleetctl get ... --yaml --remove-deprecated-keys), bringing get and apply back into compatibility.

Changes:

  • Update GroupFromBytes to select the team/fleet spec wrapper key dynamically based on kind (so kind: fleet reads spec.fleet).
  • Add a regression test covering both kind: team + spec.team and kind: fleet + spec.fleet.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
pkg/spec/spec.go Fixes wrapper key selection for team/fleet specs during YAML parsing in GroupFromBytes.
pkg/spec/spec_test.go Adds regression coverage ensuring both deprecated and current team/fleet wrapper formats parse into g.Teams.
Comments suppressed due to low confidence (1)

pkg/spec/spec.go:243

  • GroupFromBytes still silently appends a null team/fleet spec if the expected wrapper key is missing (e.g. kind: fleet but spec lacks a fleet: key). Since teamRaw := rawTeam[kind] can be nil, this can recreate the original failure mode (sending {specs:[null]}) without an error. Consider validating that rawTeam[kind] is present (and possibly that only one of team/fleet wrappers is set) and returning a clear error when it isn’t.
			rawTeam := make(map[string]json.RawMessage)
			if err := yaml.Unmarshal(s.Spec, &rawTeam); err != nil {
				return nil, fmt.Errorf("unmarshaling %s spec: %w", kind, err)
			}
			teamRaw := rawTeam[kind]
			var err error
			teamRaw, deprecatedKeysMap, err = rewriteNewToOldKeys(teamRaw, fleet.TeamSpec{})
			if err != nil {
				return nil, fmt.Errorf("in %s spec: %w", kind, err)
			}
			specs.Teams = append(specs.Teams, teamRaw)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov

codecov Bot commented May 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.74%. Comparing base (9a345f3) to head (91768b2).
⚠️ Report is 766 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #44894      +/-   ##
==========================================
+ Coverage   66.68%   66.74%   +0.06%     
==========================================
  Files        2664     2686      +22     
  Lines      214697   216884    +2187     
  Branches     9841     9841              
==========================================
+ Hits       143160   144761    +1601     
- Misses      58509    58871     +362     
- Partials    13028    13252     +224     
Flag Coverage Δ
backend 68.61% <100.00%> (+0.05%) ⬆️

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.

@spalmesano0 spalmesano0 changed the title Fix fleetctl apply ignoring spec.fleet Fix fleetctl apply ignoring spec.fleet May 7, 2026
sgress454
sgress454 previously approved these changes May 19, 2026
Comment thread pkg/spec/spec.go Outdated
@sgress454
sgress454 self-requested a review May 19, 2026 20:32

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.

These are supposed to mainly test the preferred config; we have apply_deprecated_test.go for testing the deprecated config.

@lukeheath
lukeheath marked this pull request as draft May 20, 2026 15:23
@lukeheath

Copy link
Copy Markdown
Member

@spalmesano0 Converting to draft while @sgress454 is out. Feel free to update, we'll take out of draft next week.

@spalmesano0

Copy link
Copy Markdown
Member Author

Thanks for the update! No additional changes from my end, I was just trying to get the ball rolling on this one.

@lucasmrod
lucasmrod marked this pull request as ready for review May 29, 2026 14:30

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

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.

@lucasmrod

Copy link
Copy Markdown
Member

LGTM. Tested that the fix correctly uses fleet: when available, and resorts to the legacy team:.

@sgress454
sgress454 merged commit 64f6018 into main May 29, 2026
45 checks passed
@sgress454
sgress454 deleted the fleetctl-apply-fleet branch May 29, 2026 16:23
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.

fleetctl apply silently ignores YAML with spec.fleet

5 participants