Skip to content

feat: add SortOptions support for kustomize resource ordering#189

Merged
yxxhero merged 3 commits into
masterfrom
feat/sort-options
May 15, 2026
Merged

feat: add SortOptions support for kustomize resource ordering#189
yxxhero merged 3 commits into
masterfrom
feat/sort-options

Conversation

@yxxhero
Copy link
Copy Markdown
Member

@yxxhero yxxhero commented May 14, 2026

Summary

  • Adds SortOptions type with Order field to control kustomize's resource sorting order (accepted values: "legacy", "fifo")
  • Validates SortOptions.Order early in Chartify() to reject invalid values with a clear error
  • Wires SortOptions through ChartifyOptsKustomizeBuildOpts (kustomize-based apps) and PatchOpts (patch-based builds)
  • Writes sortOptions to the generated kustomization.yaml in both code paths (byte append, since kustomize has no edit set sortoptions command)
  • Fixes a pre-existing nilness lint warning (tautological condition: non-nil != nil)

Usage

opts := &chartify.ChartifyOpts{
    SortOptions: &chartify.SortOptions{Order: "fifo"},
}
chartDir, err := runner.Chartify("myrelease", "./mychart", opts)

This generates:

sortOptions:
  order: fifo

Closes #188

Add ability to set kustomize's sortOptions.order (e.g. "fifo") to control
resource ordering. This reduces diff noise when applying patches by preserving
the original resource order instead of using kustomize's default "legacy"
sorting.

Adds SortOptions to ChartifyOpts, KustomizeBuildOpts, KustomizeOpts, and
PatchOpts. The sortOptions is written to the generated kustomization.yaml
in both kustomize-based and patch-based code paths.

Also fixes a pre-existing nilness lint warning (tautological condition).

Closes #188

Signed-off-by: yxxhero <aiopsclub@163.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new SortOptions type (with Order) and threads it from ChartifyOpts through KustomizeBuildOpts and PatchOpts so users can control kustomize's sortOptions.order (e.g. fifo) in the generated kustomization.yaml. Resolves issue #188 to reduce diff noise from kustomize's default legacy resource ordering. Also includes a small drive-by lint fix in chartify.go and updates hardcoded hash expectations in tempdir_test.go (necessary because adding a field to ChartifyOpts changes the spew-based hash).

Changes:

  • Introduce SortOptions struct and add it to ChartifyOpts, KustomizeBuildOpts, KustomizeOpts, and PatchOpts.
  • Append sortOptions: to the generated kustomization.yaml in both KustomizeBuild and Patch code paths when set.
  • Remove tautological err != nil check in createDirForFile and refresh expected hashes in TestGenerateID.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
chartify.go Adds SortOptions field on ChartifyOpts and forwards it into KustomizeBuildOpts / PatchOpts; cleans up tautological nil check.
kustomize.go Defines SortOptions, adds it to KustomizeOpts and KustomizeBuildOpts, and appends serialized sortOptions to kustomization.yaml after kustomize edits.
patch.go Adds SortOptions to PatchOpts and appends it to the inline kustomization.yaml content.
tempdir_test.go Updates expected GenerateID hashes to reflect the new ChartifyOpts.SortOptions field affecting the spew-based hash.

Comment thread kustomize.go Outdated
if err != nil {
return "", fmt.Errorf("marshaling sortOptions: %w", err)
}
f, err := os.ReadFile(kustomizationPath)
Comment thread chartify.go
Comment on lines +111 to +114
// SortOptions configures kustomize's sortOptions for resource ordering.
// Use &SortOptions{Order: "fifo"} to preserve resource order and minimize diff noise.
// See https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/sortoptions/
SortOptions *SortOptions
Comment thread patch.go
Comment on lines +179 to +185
if u.SortOptions != nil {
sortOptsBytes, err := yaml.Marshal(map[string]*SortOptions{"sortOptions": u.SortOptions})
if err != nil {
return fmt.Errorf("marshaling sortOptions: %w", err)
}
kustomizationYamlContent += string(sortOptsBytes)
}
- Extract duplicated sortOptions marshaling into marshalSortOptions helper
  used by both KustomizeBuild and Patch (review comment)
- Use r.ReadFile instead of os.ReadFile for consistency with the Runner
  abstraction (review comment)
- Add unit tests for marshalSortOptions and SortOptions behavior in
  generated kustomization.yaml (review comment)

Signed-off-by: yxxhero <aiopsclub@163.com>
@yxxhero
Copy link
Copy Markdown
Member Author

yxxhero commented May 14, 2026

Addressed all three review comments in b78952e:

  1. r.ReadFile consistency — Replaced os.ReadFile with r.ReadFile in kustomize.go to stay consistent with the Runner abstraction.
  2. Test coverage — Added kustomize_test.go with tests for marshalSortOptions (nil, fifo, legacy) and TestKustomizationYamlWithSortOptions verifying sortOptions appears/disappears in generated kustomization.yaml.
  3. Deduplicated marshaling — Extracted marshalSortOptions helper shared by both KustomizeBuild and Patch.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

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

Comment thread kustomize_test.go Outdated
Comment on lines +11 to +16
t.Run("nil returns no sortOptions content", func(t *testing.T) {
got, err := marshalSortOptions(nil)
require.NoError(t, err)
result := string(got)
require.Contains(t, result, "sortOptions: null\n")
})
Comment thread kustomize_test.go Outdated
Comment on lines +35 to +64
func TestKustomizationYamlWithSortOptions(t *testing.T) {
t.Run("Patch generates sortOptions in kustomization.yaml", func(t *testing.T) {
opts := &SortOptions{Order: "fifo"}
sortOptsBytes, err := marshalSortOptions(opts)
require.NoError(t, err)

kustomizationYamlContent := `kind: ""
apiversion: ""
resources:
- templates/deployment.yaml
patches:
- path: strategicmergepatches/patch.0.yaml
`
kustomizationYamlContent += string(sortOptsBytes)

require.True(t, strings.Contains(kustomizationYamlContent, "sortOptions:"))
require.True(t, strings.Contains(kustomizationYamlContent, "order: fifo"))
})

t.Run("Patch without SortOptions has no sortOptions in kustomization.yaml", func(t *testing.T) {
kustomizationYamlContent := `kind: ""
apiversion: ""
resources:
- templates/deployment.yaml
patches:
- path: strategicmergepatches/patch.0.yaml
`

require.False(t, strings.Contains(kustomizationYamlContent, "sortOptions:"))
})
Comment thread kustomize_test.go
Comment on lines +65 to +85

t.Run("KustomizeBuild merges SortOptions from KustomizeBuildOpts", func(t *testing.T) {
u := &KustomizeBuildOpts{
SortOptions: &SortOptions{Order: "fifo"},
}
kustomizeOpts := KustomizeOpts{}
if u.SortOptions != nil {
kustomizeOpts.SortOptions = u.SortOptions
}
require.NotNil(t, kustomizeOpts.SortOptions)
require.Equal(t, "fifo", kustomizeOpts.SortOptions.Order)
})

t.Run("KustomizeBuild without SortOptions leaves kustomizeOpts.SortOptions nil", func(t *testing.T) {
u := &KustomizeBuildOpts{}
kustomizeOpts := KustomizeOpts{}
if u.SortOptions != nil {
kustomizeOpts.SortOptions = u.SortOptions
}
require.Nil(t, kustomizeOpts.SortOptions)
})
Comment thread kustomize.go
Comment on lines +160 to +172
if kustomizeOpts.SortOptions != nil {
sortOptsBytes, err := marshalSortOptions(kustomizeOpts.SortOptions)
if err != nil {
return "", err
}
f, err := r.ReadFile(kustomizationPath)
if err != nil {
return "", fmt.Errorf("reading kustomization.yaml for sortOptions: %w", err)
}
if err := r.WriteFile(kustomizationPath, append(f, sortOptsBytes...), 0644); err != nil {
return "", err
}
}
Comment thread kustomize.go
Comment on lines +13 to +15
type SortOptions struct {
Order string `yaml:"order"`
}
- Guard marshalSortOptions(nil) to return nil/empty instead of
  'sortOptions: null' (review comment)
- Add validate() on SortOptions.Order to reject invalid values early,
  accepted values: legacy, fifo (review comment)
- Call validation from Chartify() before any kustomize operations
- Rewrite tests to exercise real Runner.Patch code path via WriteFile
  capture, instead of inline string assertions (review comment)
- Add comment explaining sortOptions uses byte append because kustomize
  has no 'edit set sortoptions' command (review comment)
- Fix PR description to only list accepted values: legacy, fifo

Signed-off-by: yxxhero <aiopsclub@163.com>
@yxxhero
Copy link
Copy Markdown
Member Author

yxxhero commented May 14, 2026

Addressed all second-round review comments in 65d008a:

  1. marshalSortOptions(nil) now returns nil, nil instead of sortOptions: null\n. Updated test to assert empty bytes.

  2. Added SortOptions.validate() that checks Order is one of legacy or fifo, returning a clear error with accepted values. Called early in Chartify() and inside marshalSortOptions().

  3. Rewrote tests to exercise real Runner.Patch — both TestPatch_SortOptions subtests now create temp directories with real manifest files, call r.Patch() with a WriteFile wrapper that captures the generated kustomization.yaml, and assert on the captured content.

  4. Added comment explaining that sortOptions is appended directly because kustomize has no edit set sortoptions command.

  5. Fixed PR description to only list accepted values: legacy, fifo.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

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

@yxxhero yxxhero merged commit 9afce58 into master May 15, 2026
5 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.

Feature Request: add the ability to set sortOptions.order

2 participants