Skip to content

Commit 6e1749d

Browse files
committed
allow checking for value changes before bumping helm chart version
Add flag `--check-for-value-updates` to `arkade chart bump` which skips bumping the chart version if the values file does not have any changes according to the Git. Signed-off-by: Sanskar Jaiswal <[email protected]>
1 parent 4e0c130 commit 6e1749d

File tree

1 file changed

+67
-60
lines changed

1 file changed

+67
-60
lines changed

cmd/chart/bump.go

+67-60
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package chart
22

33
import (
4+
"context"
45
"fmt"
5-
"io/fs"
66
"log"
77
"os"
88
"path/filepath"
99

1010
"github.com/Masterminds/semver"
1111
"github.com/alexellis/arkade/pkg/helm"
12+
"github.com/alexellis/go-execute/v2"
1213
"github.com/spf13/cobra"
1314
)
1415

@@ -25,15 +26,16 @@ func MakeBump() *cobra.Command {
2526
Long: `Bump the version present in the Chart.yaml of a Helm chart.
2627
If the provided directory contains multiple charts, then the --recursive flag
2728
can be used to bump the version in all charts.`,
28-
Example: `arkade bump --dir ./chart
29-
arkade --dir ./charts --recursive`,
29+
Example: `arkade chart bump --dir ./chart
30+
arkade chart bump --dir ./charts --check-for-value-updates values.yaml`,
3031
SilenceUsage: true,
3132
}
3233

3334
command.Flags().StringP("dir", "d", "", "Path to the Helm chart directory or a directory containing Helm charts")
3435
command.Flags().BoolP("recursive", "r", false, "Recursively iterate through directory while bumping chart versions")
3536
command.Flags().BoolP("verbose", "v", false, "Verbose output")
3637
command.Flags().BoolP("write", "w", false, "Write the updated values back to the file, or stdout when set to false")
38+
command.Flags().String("check-for-value-updates", "", "File name to check if the chart's values have been modified before bumping version")
3739

3840
command.RunE = func(cmd *cobra.Command, args []string) error {
3941
chartDir, err := cmd.Flags().GetString("dir")
@@ -44,80 +46,85 @@ can be used to bump the version in all charts.`,
4446
return fmt.Errorf("flag --dir is required")
4547
}
4648
verbose, _ := cmd.Flags().GetBool("verbose")
47-
recursive, err := cmd.Flags().GetBool("recursive")
48-
if err != nil {
49-
return fmt.Errorf("invalid value for --recursive")
50-
}
5149
write, err := cmd.Flags().GetBool("write")
5250
if err != nil {
5351
return fmt.Errorf("invalid value for --write")
5452
}
53+
valuesFile, err := cmd.Flags().GetString("check-for-value-updates")
54+
if err != nil {
55+
return fmt.Errorf("invalid value for --check-for-value-updates")
56+
}
5557

5658
// Map with key as the path to Chart.yaml and the value as the parsed contents of Chart.yaml
57-
chartYamls := make(map[string]helm.ValuesMap, 0)
58-
if !recursive {
59-
chartYamlPath := filepath.Join(chartDir, ChartYamlFileName)
60-
var values helm.ValuesMap
61-
// Try to read a Chart.yaml, but if thats unsuccessful then fall back to Chart.yml
59+
chartYamlPath := filepath.Join(chartDir, ChartYamlFileName)
60+
var values helm.ValuesMap
61+
// Try to read a Chart.yaml, but if thats unsuccessful then fall back to Chart.yml
62+
if values, err = helm.Load(chartYamlPath); err != nil {
63+
if verbose {
64+
log.Printf("unable to read %s, falling back to Chart.yml\n", chartYamlPath)
65+
}
66+
chartYamlPath = filepath.Join(chartDir, ChartYmlFileName)
6267
if values, err = helm.Load(chartYamlPath); err != nil {
63-
if verbose {
64-
log.Printf("unable to read %s, falling back to Chart.yml\n", chartYamlPath)
65-
}
66-
chartYamlPath = filepath.Join(chartDir, ChartYmlFileName)
67-
if values, err = helm.Load(chartYamlPath); err != nil {
68-
return fmt.Errorf("unable to read Chart.yaml or Chart.yml in directory %s", chartDir)
69-
}
68+
return fmt.Errorf("unable to read Chart.yaml or Chart.yml in directory %s", chartDir)
7069
}
71-
chartYamls[chartYamlPath] = values
70+
}
71+
72+
// If the yaml does not contain a `version` key then error out
73+
if val, ok := values[versionKey]; !ok {
74+
return fmt.Errorf("unable to find a version in %s", chartYamlPath)
7275
} else {
73-
filepath.WalkDir(chartDir, func(path string, d fs.DirEntry, err error) error {
76+
version, ok := val.(string)
77+
if !ok {
78+
log.Printf("unable to find a valid version in %s", chartYamlPath)
79+
}
80+
if valuesFile != "" {
81+
absPath, err := filepath.Abs(chartDir)
7482
if err != nil {
7583
return err
7684
}
77-
if d.Name() == ChartYamlFileName || d.Name() == ChartYmlFileName {
78-
values, err := helm.Load(path)
79-
if err != nil {
80-
return err
81-
}
82-
chartYamls[path] = values
85+
absValuesFile := filepath.Join(absPath, valuesFile)
86+
_, err = os.Stat(absValuesFile)
87+
if err != nil {
88+
return fmt.Errorf("unable to find values file: %s", absValuesFile)
89+
}
90+
91+
// Run `git diff --exit-code <file>` to check if the values file has any changes.
92+
// An exit code of 0 indicates that there are no changes, thus we skip bumping the
93+
// version of the chart.
94+
cmd := execute.ExecTask{
95+
Command: "git",
96+
Args: []string{"diff", "--exit-code", valuesFile},
97+
Cwd: absPath,
98+
}
99+
res, err := cmd.Execute(context.Background())
100+
if err != nil {
101+
return fmt.Errorf("could not check updates to chart values: %s", err)
83102
}
84-
return nil
85-
})
86-
if len(chartYamls) > 0 {
87-
fmt.Printf("Found %d chart(s)\n", len(chartYamls))
88-
}
89-
}
90103

91-
for file, contents := range chartYamls {
92-
// If the yaml does not contain a `version` key then skip it.
93-
if val, ok := contents[versionKey]; !ok {
94-
continue
95-
} else {
96-
version, ok := val.(string)
97-
if !ok {
98-
log.Printf("unable to find a valid version in %s", file)
99-
continue
104+
if res.ExitCode == 0 {
105+
fmt.Printf("no changes detected in %s; skipping version bump\n", filepath.Join(chartDir, valuesFile))
106+
os.Exit(0)
107+
}
108+
}
109+
ver, err := semver.NewVersion(version)
110+
if err != nil {
111+
return fmt.Errorf("%s", err)
112+
}
113+
newVer := ver.IncMinor()
114+
fmt.Printf("%s %s => %s\n", chartYamlPath, ver.String(), newVer.String())
115+
if write {
116+
if verbose {
117+
log.Printf("Bumping version")
118+
}
119+
update := map[string]string{
120+
fmt.Sprintf("%s: %s", versionKey, ver.String()): fmt.Sprintf("%s: %s", versionKey, newVer.String()),
100121
}
101-
ver, err := semver.NewVersion(version)
122+
rawChartYaml, err := helm.ReplaceValuesInHelmValuesFile(update, chartYamlPath)
102123
if err != nil {
103-
continue
124+
return fmt.Errorf("unable to bump chart version in %s", chartYamlPath)
104125
}
105-
newVer := ver.IncMinor()
106-
fmt.Printf("%s %s => %s\n", file, ver.String(), newVer.String())
107-
if write {
108-
if verbose {
109-
log.Printf("Bumping version")
110-
}
111-
update := map[string]string{
112-
fmt.Sprintf("%s: %s", versionKey, ver.String()): fmt.Sprintf("%s: %s", versionKey, newVer.String()),
113-
}
114-
rawChartYaml, err := helm.ReplaceValuesInHelmValuesFile(update, file)
115-
if err != nil {
116-
return fmt.Errorf("unable to bump chart version in %s", file)
117-
}
118-
if err = os.WriteFile(file, []byte(rawChartYaml), 0600); err != nil {
119-
return fmt.Errorf("unable to write updated yaml to %s", file)
120-
}
126+
if err = os.WriteFile(chartYamlPath, []byte(rawChartYaml), 0600); err != nil {
127+
return fmt.Errorf("unable to write updated yaml to %s", chartYamlPath)
121128
}
122129
}
123130
}

0 commit comments

Comments
 (0)