Skip to content

fix(kubernetes): single-file GitOps delivery and Kustomize metadata.name exemption - #2874

Open
Erik Osterman (Cloud Posse) (osterman) wants to merge 5 commits into
mainfrom
osterman/fix-kustomize-yaml-bug
Open

fix(kubernetes): single-file GitOps delivery and Kustomize metadata.name exemption#2874
Erik Osterman (Cloud Posse) (osterman) wants to merge 5 commits into
mainfrom
osterman/fix-kustomize-yaml-bug

Conversation

@osterman

@osterman Erik Osterman (Cloud Posse) (osterman) commented Aug 5, 2026

Copy link
Copy Markdown
Member

what

  • kubernetes.gitops.provision.targets.<name> (kind: git) now supports a split tri-state: split: false writes path as a single merged multi-document YAML file instead of always treating path as a directory of auto-named files; unset infers the mode from whether path's last segment looks like a manifest filename (.yaml/.yml/.json).
  • Atmos's structural manifest validator no longer requires metadata.name on Kustomize's own Kustomization/Component objects (matched against sigs.k8s.io/kustomize/api/types's own kind/version constants), since Kustomize's own schema and field-enforcement never require one.
  • A new validate: false component-level flag opts a component out of both the apply/deploy structural auto-gate and the standalone atmos kubernetes validate command.
  • Docs: new "Generating a Kustomize component for GitOps" walkthrough, split documented on kubernetes-deploy.mdx, and the Kustomize exemption / validate: false documented on kubernetes-validate.mdx.
  • Changelog post and a new shipped roadmap milestone (with a corrected progress percentage) for the Extensibility initiative.

why

  • A git provision target's path was always treated as a directory, so configuring path: ".../kustomization.yaml" created a directory by that name containing an auto-generated file inside it, instead of the exact file Kustomize's remote-include mechanism requires.
  • The validator required metadata.name unconditionally, forcing users to add a meaningless name to Kustomize Component/Kustomization objects just to satisfy Atmos, even though Kustomize's own tooling never requires one.
  • Together these blocked a real GitOps pattern: rendering a Kustomize patch/component with Terraform-derived values (e.g. via !terraform.state) and committing it to a deployment repo as a proper kustomization.yaml for Argo CD/Flux to consume.

references

  • N/A

Summary by CodeRabbit

  • New Features

    • Git delivery supports single-file or directory output via split, with automatic mode selection based on the destination path.
    • Kustomize Kustomization and Component objects no longer require metadata.name.
    • Added an optional Kubernetes validate setting to bypass offline structural validation.
  • Bug Fixes

    • Validation-disabled deployments now proceed correctly, while validation commands report skipped results; explicit server validation remains available.
  • Documentation

    • Added configuration guidance and GitOps examples for single-file delivery and Kustomize workflows.

…e objects from metadata.name

The `git` provision target always treated its configured `path` as a
directory, fanning out one auto-named file per manifest even when the path
named an exact file (e.g. `kustomization.yaml`) — creating a directory by
that name instead. Kustomize's own `Kustomization`/`Component` objects were
also rejected by Atmos's structural validator for lacking `metadata.name`,
even though Kustomize's own schema (and its own field-enforcement checks)
never requires one.

- Add a `split` tri-state on git provision targets: explicit `true`/`false`
  wins, otherwise inferred from whether `path`'s last segment looks like a
  manifest filename. `split: false` merges rendered manifests into a single
  file at the exact path instead of a directory.
- Exempt Kustomize's own `Kustomization`/`Component` kinds (matched against
  their own vendored `sigs.k8s.io/kustomize/api/types` constants) from the
  `metadata.name` presence check; add an explicit `validate: false` component
  flag as a general override for the apply/deploy auto-gate and the standalone
  `validate` command.
- Document the new `split` and `validate` fields, and add a full walkthrough
  for generating a Kustomize component/patch for GitOps delivery.
Required release docs for the split/validate provision-target fix: a
problem-first blog post walking through the Kustomize component/GitOps
pattern, and a new shipped milestone on the Extensibility roadmap
initiative (with a corrected progress percentage).
@atmos-pro

atmos-pro Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@osterman Erik Osterman (Cloud Posse) (osterman) added the minor New features that do not break anything label Aug 5, 2026
@github-actions github-actions Bot added size/m Medium size PR labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bb54a063-1494-4568-aa7b-b89e401b4357

📥 Commits

Reviewing files that changed from the base of the PR and between 9ae0b31 and a051e6f.

📒 Files selected for processing (4)
  • pkg/provisioner/target/git/git_test.go
  • website/blog/2026-08-05-kustomize-gitops-delivery.mdx
  • website/docs/cli/commands/kubernetes/kubernetes-validate.mdx
  • website/docs/stacks/components/kubernetes.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • website/docs/cli/commands/kubernetes/kubernetes-validate.mdx
  • website/docs/stacks/components/kubernetes.mdx
  • pkg/provisioner/target/git/git_test.go
  • website/blog/2026-08-05-kustomize-gitops-delivery.mdx

📝 Walkthrough

Walkthrough

This change adds Kustomize-aware Kubernetes validation controls and optional validation bypass. Git targets now support inferred or explicit split mode, including deterministic single-file multi-document YAML output. Schemas, tests, and GitOps documentation describe the new options.

Changes

Kubernetes validation controls

Layer / File(s) Summary
Validation rules and execution gates
pkg/component/kubernetes/validate.go, pkg/component/kubernetes/executor.go, pkg/datafetcher/schema/stacks/stack-config/1.0.json
Kustomization and Component objects may omit metadata.name. Component-level validate defaults to enabled and controls structural validation during apply and validate operations.
Validation coverage
pkg/component/kubernetes/validate_test.go, pkg/component/kubernetes/executor_test.go
Tests cover Kustomize object recognition, validation defaults and overrides, apply bypass behavior, skipped validate results, and server validation.

Manifest delivery

Layer / File(s) Summary
Shared multi-document YAML merging
pkg/provisioner/target/manifest.go, pkg/provisioner/target/manifest_test.go, pkg/component/kubernetes/render.go
Rendered documents use MergeYAMLDocuments, which inserts separators and normalizes trailing newlines.
Git target split mode
pkg/provisioner/target/git/git.go, pkg/provisioner/target/git/git_test.go, pkg/datafetcher/schema/stacks/stack-config/1.0.json
Git targets honor explicit split values and infer single-file output for manifest filename paths. Single-file output sorts artifacts and writes one multi-document YAML file.

GitOps workflow documentation

Layer / File(s) Summary
Deployment and validation documentation
website/docs/cli/commands/kubernetes/*, website/docs/stacks/components/kubernetes.mdx, website/blog/2026-08-05-kustomize-gitops-delivery.mdx, website/src/data/roadmap.js
Documentation describes split behavior, Kustomize validation rules, validate: false, and a Terraform-backed GitOps workflow.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant KubernetesRender
  participant GitProvisionTarget
  participant writeArtifact
  participant MergeYAMLDocuments
  participant GitRepository
  KubernetesRender->>GitProvisionTarget: rendered artifacts
  GitProvisionTarget->>writeArtifact: resolved split mode
  writeArtifact->>MergeYAMLDocuments: sorted documents
  MergeYAMLDocuments-->>writeArtifact: multi-document YAML
  writeArtifact->>GitRepository: write target file or directory
Loading

Possibly related PRs

  • cloudposse/atmos#2685: Both changes modify Kubernetes executor behavior, but address separate validation and CI-mode behavior.

Suggested labels: patch

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two primary changes: single-file GitOps delivery and the Kustomize metadata.name exemption.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch osterman/fix-kustomize-yaml-bug

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.

@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

🤖 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 `@pkg/component/kubernetes/executor.go`:
- Around line 261-265: Update the validation flow around
resolveComponentValidateEnabled, resolveValidateOptions, and runValidate so
validation options are resolved before the validate:false check and --server
requests still call runValidate against the live cluster. Restrict the skip
result to offline structural validation only, preserving existing behavior
otherwise, and add a regression test covering validate:false with --server.

In `@website/blog/2026-08-05-kustomize-gitops-delivery.mdx`:
- Around line 8-10: Update the Kustomize filename explanation in the blog
content to say that a remote base or component must contain a recognized
reserved kustomization file name, not only kustomization.yaml. Use Kustomize as
the context and mention the supported filenames kustomization.yaml,
kustomization.yml, and Kustomization, while keeping kustomization.yaml as the
example. Preserve the existing point that the name is fixed by Kustomize and not
configurable.

In `@website/docs/stacks/components/kubernetes.mdx`:
- Around line 239-244: Update the Kubernetes delivery-mode documentation near
the `path` and `split` explanation to state that an unset `split` infers
single-file delivery when `path` ends in `.yaml`, `.yml`, or `.json`; otherwise
it defaults to directory delivery. Clarify that users should set `split`
explicitly when they need to override this path-based inference.
🪄 Autofix

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: 07caf576-d657-4dff-a351-701802edd092

📥 Commits

Reviewing files that changed from the base of the PR and between d2b8e81 and 91afe44.

📒 Files selected for processing (15)
  • pkg/component/kubernetes/executor.go
  • pkg/component/kubernetes/executor_test.go
  • pkg/component/kubernetes/render.go
  • pkg/component/kubernetes/validate.go
  • pkg/component/kubernetes/validate_test.go
  • pkg/datafetcher/schema/stacks/stack-config/1.0.json
  • pkg/provisioner/target/git/git.go
  • pkg/provisioner/target/git/git_test.go
  • pkg/provisioner/target/manifest.go
  • pkg/provisioner/target/manifest_test.go
  • website/blog/2026-08-05-kustomize-gitops-delivery.mdx
  • website/docs/cli/commands/kubernetes/kubernetes-deploy.mdx
  • website/docs/cli/commands/kubernetes/kubernetes-validate.mdx
  • website/docs/stacks/components/kubernetes.mdx
  • website/src/data/roadmap.js

Comment thread pkg/component/kubernetes/executor.go Outdated
Comment thread website/blog/2026-08-05-kustomize-gitops-delivery.mdx Outdated
Comment thread website/docs/stacks/components/kubernetes.mdx Outdated
Address CodeRabbit review on #2874:
- The validate:false short-circuit returned before resolving --server,
  so `atmos kubernetes validate --server` never reached the live cluster
  for a component with validate:false. Resolve validate options first
  and only skip the offline structural check; --server still runs
  runServerValidate. Adds a regression test.
- Blog post overclaimed kustomization.yaml as the only recognized
  filename; Kustomize also accepts kustomization.yml and Kustomization
  (confirmed against the vendored dependency).
- Applied CodeRabbit's suggested wording clarifying the split-unset
  path-extension inference in the stack config docs.
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.08197% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.77%. Comparing base (13bce50) to head (a051e6f).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/provisioner/target/git/git.go 85.71% 1 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2874      +/-   ##
==========================================
+ Coverage   82.75%   82.77%   +0.02%     
==========================================
  Files        1860     1862       +2     
  Lines      180337   180485     +148     
==========================================
+ Hits       149240   149402     +162     
+ Misses      23309    23295      -14     
  Partials     7788     7788              
Flag Coverage Δ
unittests 82.77% <95.08%> (+0.02%) ⬆️

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

Files with missing lines Coverage Δ
pkg/component/kubernetes/executor.go 83.95% <100.00%> (+0.80%) ⬆️
pkg/component/kubernetes/render.go 90.90% <100.00%> (+1.43%) ⬆️
pkg/component/kubernetes/validate.go 100.00% <100.00%> (+4.08%) ⬆️
pkg/provisioner/target/manifest.go 100.00% <100.00%> (ø)
pkg/provisioner/target/git/git.go 82.65% <85.71%> (+0.73%) ⬆️

... and 17 files with indirect coverage changes

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

@osterman

Copy link
Copy Markdown
Member Author

CodeRabbit (@coderabbitai) full review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@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: 1

🧹 Nitpick comments (1)
pkg/component/kubernetes/validate_test.go (1)

107-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a table-driven test for validation-option resolution.

These assertions test five input scenarios. Put them in one table to follow the repository test convention.

As per coding guidelines, “Use table-driven tests for testing multiple scenarios in Go.”

Proposed refactor.
 func TestResolveComponentValidateEnabled(t *testing.T) {
-	assert.True(t, resolveComponentValidateEnabled(nil), "unset defaults to enabled")
-	assert.True(t, resolveComponentValidateEnabled(map[string]any{}), "unset defaults to enabled")
-	assert.True(t, resolveComponentValidateEnabled(map[string]any{"validate": true}))
-	assert.False(t, resolveComponentValidateEnabled(map[string]any{"validate": false}))
-	assert.True(t, resolveComponentValidateEnabled(map[string]any{"validate": "false"}), "non-bool values are ignored, defaulting to enabled")
+	tests := []struct {
+		name             string
+		componentSection map[string]any
+		want             bool
+	}{
+		{"nil defaults to enabled", nil, true},
+		{"empty defaults to enabled", map[string]any{}, true},
+		{"true enables validation", map[string]any{"validate": true}, true},
+		{"false disables validation", map[string]any{"validate": false}, false},
+		{"non-boolean defaults to enabled", map[string]any{"validate": "false"}, true},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equal(t, tt.want, resolveComponentValidateEnabled(tt.componentSection))
+		})
+	}
 }
🤖 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/component/kubernetes/validate_test.go` around lines 107 - 113, Refactor
TestResolveComponentValidateEnabled into a table-driven test covering the
existing five inputs and expected results, including descriptive case names and
messages where useful. Iterate over the cases with the repository’s standard
subtest pattern while preserving the current validation-option behavior
assertions.

Source: Coding guidelines

🤖 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 `@website/blog/2026-08-05-kustomize-gitops-delivery.mdx`:
- Around line 57-58: Update
website/blog/2026-08-05-kustomize-gitops-delivery.mdx:57-58,
website/docs/stacks/components/kubernetes.mdx:270-271, and
pkg/provisioner/target/git/git_test.go:250-252 to use
kustomize.config.k8s.io/v1alpha1 for Component fixtures. Update
website/docs/cli/commands/kubernetes/kubernetes-validate.mdx:106-113 to document
Kustomization as v1beta1 and Component as v1alpha1 separately, removing the
wildcard API-version description.

---

Nitpick comments:
In `@pkg/component/kubernetes/validate_test.go`:
- Around line 107-113: Refactor TestResolveComponentValidateEnabled into a
table-driven test covering the existing five inputs and expected results,
including descriptive case names and messages where useful. Iterate over the
cases with the repository’s standard subtest pattern while preserving the
current validation-option behavior assertions.
🪄 Autofix

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: 98b624ea-72ff-4b64-addf-5fbc73840f88

📥 Commits

Reviewing files that changed from the base of the PR and between d2b8e81 and 9ae0b31.

📒 Files selected for processing (15)
  • pkg/component/kubernetes/executor.go
  • pkg/component/kubernetes/executor_test.go
  • pkg/component/kubernetes/render.go
  • pkg/component/kubernetes/validate.go
  • pkg/component/kubernetes/validate_test.go
  • pkg/datafetcher/schema/stacks/stack-config/1.0.json
  • pkg/provisioner/target/git/git.go
  • pkg/provisioner/target/git/git_test.go
  • pkg/provisioner/target/manifest.go
  • pkg/provisioner/target/manifest_test.go
  • website/blog/2026-08-05-kustomize-gitops-delivery.mdx
  • website/docs/cli/commands/kubernetes/kubernetes-deploy.mdx
  • website/docs/cli/commands/kubernetes/kubernetes-validate.mdx
  • website/docs/stacks/components/kubernetes.mdx
  • website/src/data/roadmap.js

Comment thread website/blog/2026-08-05-kustomize-gitops-delivery.mdx Outdated
… gap

Address CodeRabbit full-review findings on #2874:
- All Component examples/fixtures used kustomize.config.k8s.io/v1beta1,
  which is Kustomization's version, not Component's (v1alpha1). Since
  isKustomizeConfigObject matches exact (apiVersion, kind) pairs, the
  examples never actually got the metadata.name exemption they claimed.
  Fixed in the blog post, the kubernetes.mdx walkthrough, and test
  fixtures; kubernetes-validate.mdx now documents both exact pairs
  instead of a kustomize.config.k8s.io/* wildcard.
- Added TestWriteArtifactSingleFileModeWriteFailure, closing the patch
  coverage gap Codecov flagged on writeSingleArtifactFile's two new
  error branches (MkdirAll/WriteFile failure), mirroring the existing
  split=true failure test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/m Medium size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant