Skip to content

feat: preserve formatting and comments when updating Helm values file #1039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kirgene
Copy link

@kirgene kirgene commented Feb 13, 2025

Description

This PR enhances the Helm values file update functionality by preserving the original formatting and comments. Previously, updating the file would overwrite manual formatting and comments, which could be problematic for users who rely on these customizations for clarity and maintenance. By retaining inline comments and specific formatting, this change improves the user experience and reduces potential confusion after automated updates.

Additionally, this update refines how image-name and image-tag keys are handled:

  • By default, key path in image-name and image-tag creates a nested structure. For example:

    argocd-image-updater.argoproj.io/nginx.helm.image-name: image.name
    argocd-image-updater.argoproj.io/nginx.helm.image-tag: image.tag

    Produces:

    image:
      name: app-name
      tag: v1.0.0
  • If a user wants to update Helm values that contain dots, the key path must be quoted (either with double or single quotes):

    argocd-image-updater.argoproj.io/nginx.helm.image-name: '"image.name"'
    argocd-image-updater.argoproj.io/nginx.helm.image-tag: '"image.tag"'

    This will correctly produce:

    image.name: app-name
    image.tag: v1.0.0

These changes ensure greater flexibility and correctness in handling Helm values updates while maintaining user-defined formatting.

@codecov-commenter
Copy link

codecov-commenter commented Feb 13, 2025

Codecov Report

Attention: Patch coverage is 82.41758% with 16 lines in your changes missing coverage. Please review.

Project coverage is 62.49%. Comparing base (add409e) to head (7f81de7).
Report is 15 commits behind head on master.

Files with missing lines Patch % Lines
pkg/argocd/update.go 82.22% 9 Missing and 7 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1039      +/-   ##
==========================================
- Coverage   62.59%   62.49%   -0.10%     
==========================================
  Files          15       15              
  Lines        2259     2293      +34     
==========================================
+ Hits         1414     1433      +19     
- Misses        755      764       +9     
- Partials       90       96       +6     

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

Signed-off-by: Yevhen Kyriukha <kirgene@gmail.com>
yaml, err = marshalParamsOverride(&app, originalData)
require.NoError(t, err)
assert.NotEmpty(t, yaml)
assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Any reason this part of the test is removed? I think we should keep any existing test as much as we can, and add new tests for introduced new features.

The above test verifies that

  • the updater can infer the correct param name (whether to interpret dotted names as nested or flat ones) based on the existing format in use.
  • any added new parameters will not corrupt or interfere with any existing parameters.

yaml, err = marshalParamsOverride(&app, originalData)
require.NoError(t, err)
assert.NotEmpty(t, yaml)
assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Any reason this part of the test is removed? I think we should keep any existing test as much as we can, and add new tests for introduced new features.

The above test verifies that

  • the updater can infer the correct param name (whether to interpret dotted names as nested or flat ones) based on the existing format in use.
  • any added new parameters will not corrupt or interfere with any existing parameters.

// Check if the full key exists
if idx, found := findHelmValuesKey(*currentValues, key); found {
(*currentValues)[idx].Value = value
return nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

the current behaviro is, if the full key (e.g., images.nginx.name) already exists in the target helm file, take this existing key and update its value. Otherwise, assume the users want nested parameter names. I think this should be perserved when the annotation value helm.image-name and helm.image-tag are not explicitly quoted.

Even when the 2 annotation values are explicitly quoted, it's still worth considering whether we should honor the existing key format (flat dotted or nested) over the application annotation.

@bazzargh
Copy link

bazzargh commented Mar 2, 2025

FYI, I was just doing a similar thing because we need it for work, then noticed this PR. https://github.com/bazzargh/argocd-image-updater/tree/bazzargh/yamlv3 - my approach was a bit different; I switched from yamlv2 to yamlv3, and yaml.MapSlice to yaml.Node, which will preserve the various scalar types and comments (to an extent. it does not guarantee the same indentation, blank lines between comments may go, etc). One thing I do that this PR doesn't is support Aliases (from reading this, I think this PR supports leaving aliases alone if they're not part of the update path, but will not follow aliases to update a value, for example; our developers have expressed frustration with the way they can't use aliases with this tool)

Your PR does a couple of things I didn't - I also wanted to build the expected/input structures by parsing yaml instead of inlining the very verbose code, but held off to stick with the original style. I also didn't change the odd handling of top level dotted keys and prefer what you did (tho clearly it's a breaking change)

I only just coded this up, some co-workers were interested in having codefresh pick this up (for codefresh people reading - this is NerdWallet. I'll ping you on slack); we might run some tests with it this week to get some production experience before submitting a PR; also I wanted to add tests for the alias processing.

Anyway - just letting you know this is in the works in case it changes what you want to do here.

@bewinsnw
Copy link
Contributor

bewinsnw commented Mar 3, 2025

Moved that over to my work account: https://github.com/bewinsnw/argocd-image-updater/tree/bazzargh/yamlv3 , also fixed up the tests to be yaml/yaml comparisons not compare the Node tree, and tests showing this preserves comments, multiline strings, anchors, and follows anchors for setting values too. I'll open it as a separate PR just now so it can be reviewed as an alternative.

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.

5 participants