Skip to content

fix: Baseline subtraction for --git mode diffs#27

Merged
TsekNet merged 12 commits intomainfrom
baseline-subtraction
Mar 21, 2026
Merged

fix: Baseline subtraction for --git mode diffs#27
TsekNet merged 12 commits intomainfrom
baseline-subtraction

Conversation

@TsekNet
Copy link
Copy Markdown
Owner

@TsekNet TsekNet commented Mar 20, 2026

Summary

In --git mode, fleet-plan now subtracts changes already merged to main but not yet deployed. Only the incremental changes from the current MR are reported. Applies to both per-team and global diffs.

Changes

File Change
internal/git/baseline.go CheckoutBaseline() extracts base-branch files via git show, collectBaselineFiles() resolves path refs
internal/git/baseline_test.go Tests for path extraction, file checkout, baseline collection
internal/git/scope.go Include base.yml/default.yml in changedFiles
internal/diff/differ.go WithBaseline(), WithVerbose(), WithIncludeGlobal() options, subtractResourceDiff(), subtractConfigChanges(), verbose logging
internal/diff/differ_test.go TestSubtractResourceDiff, TestDiffWithBaselineSubtraction
cmd/fleet-plan/main.go Baseline checkout/parsing, merged default in repo dir, includeGlobal passthrough

Bugs fixed

  • Baseline subtraction for per-team diffs (policies, queries, software, profiles, scripts)
  • Baseline subtraction for global diffs (config, policies, queries)
  • resolveDefaultFile placed merged file in /tmp, breaking path: resolution for global queries
  • ResolveScope didn't add base.yml/default.yml to changedFiles
  • buildSourceMap didn't register team source file for all resource types
  • Global diff skipped when both global and team files changed in the same MR

Test plan

  • Unit tests: TestSubtractResourceDiff (5 subtests), TestDiffWithBaselineSubtraction
  • Git integration tests: TestCheckoutBaseline_ExtractsFiles, TestCollectBaselineFiles_OnlyIncludesChangedFiles
  • CI validation: tested with MRs covering every change type (ADDED/MODIFIED/REMOVED x Policy/Query/Software/Profile/Script/Config across team and global scope)

Ref #23

TsekNet and others added 12 commits March 20, 2026 08:34
When using --git in CI with staged/delayed deployments, fleet-plan
reported changes already merged to main but not yet deployed. This
trained users to ignore fleet-plan comments.

Now in --git mode, fleet-plan extracts the base branch YAML via
git show, diffs it against live Fleet, and subtracts those pre-existing
deltas. Only the incremental changes from the current MR are reported.

Ref #23
The baseline diff was using raw API software state without fleet-maintained
app script enrichment, causing fleet-maintained app diffs (e.g. blender
uninstall_script) to not be subtracted properly.
When an MR adds a path: reference to teams/foo.yml, the referenced
resource's SourceFile (e.g. queries/windows/hardware.yml) isn't in
the MR's changed files list. The filter dropped these resources
because it only checked the individual SourceFile, not the team
file that includes them.

Now buildSourceMap registers the team's SourceFile for all resource
types (policies, queries, software, profiles, scripts), matching
the existing behavior for fleet-maintained apps.
Global config changes (default.yml/base.yml) were not subtracted,
causing MRs touching global config to show all pending undeployed
changes. Now applies subtractConfigChanges and subtractResourceDiff
to the global diff block.

Also merges base branch base.yml with env overlay for baseline
global parsing.

Ref #25
collectBaselineFiles only scanned team files for path: references.
Global config files (base.yml, default.yml) also have path: refs
to queries and policies that need to be in the baseline temp dir
for the parser to resolve them.
The merged base.yml+env overlay was written to /tmp, causing path:
references (./queries/...) to resolve against /tmp instead of the
baseline temp dir where the query files live.
ParseRepo bails early if teams/ doesn't exist, preventing global
config parsing. For global-only baselines (MR touches base.yml but
no team files), the teams/ dir must exist as an empty directory.
…l config

Two changes:
1. --verbose (-v) now logs baseline subtraction details to stderr:
   proposed/fleet counts, MR diff, baseline diff, after subtraction,
   and changedFiles filter results for each team and global scope.

2. collectBaselineFiles no longer unconditionally extracts base.yml
   and default.yml. Only files in the MR's changedFiles (plus their
   path: references) are extracted. This fixes over-subtraction for
   MRs that don't touch global config.

Ref #25
Two pre-existing bugs found via --verbose:

1. resolveDefaultFile placed the merged base.yml+env overlay in /tmp.
   The parser resolves path: refs relative to the file's directory,
   so refs like ./queries/... resolved to /tmp/queries/... which
   doesn't exist. Now places the merged file inside the repo dir.

2. ResolveScope set IncludeGlobal for base.yml changes but didn't
   add base.yml to scope.ChangedFiles. The baseline extraction and
   changedFiles filter couldn't see it.

Ref #25
When --git mode detects both global (base.yml) and team changes,
the auto-detected team filter suppressed the global diff block.
Now WithIncludeGlobal overrides the teamFilters check.
@TsekNet TsekNet merged commit 1d36188 into main Mar 21, 2026
3 checks passed
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.

1 participant