Skip to content

Commit acfb897

Browse files
jlegronescottrigby
authored andcommitted
Add option to skip upgrade testing of deleted/renamed values files (#132)
* feat(upgrade): allow skipping missing values files This allows fixing previous chart versions in a single pull request without applying a major version bump to the chart version. Signed-off-by: Jacob LeGrone <[email protected]> * test(skip-missing-values): validate config and HasCIValuesFile method Signed-off-by: Jacob LeGrone <[email protected]> * docs(skip-missing-values): generate documentation Signed-off-by: Jacob LeGrone <[email protected]> * fix(chart): switch to filepath from path Signed-off-by: Jacob LeGrone <[email protected]>
1 parent 52a4be9 commit acfb897

13 files changed

+86
-15
lines changed

ct/cmd/install.go

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ func addInstallFlags(flags *flag.FlagSet) {
6868
flags.Bool("upgrade", false, heredoc.Doc(`
6969
Whether to test an in-place upgrade of each chart from its previous revision if the
7070
current version should not introduce a breaking change according to the SemVer spec`))
71+
flags.Bool("skip-missing-values", false, heredoc.Doc(`
72+
When --upgrade has been passed, this flag will skip testing CI values files from the
73+
previous chart revision if they have been deleted or renamed at the current chart
74+
revision`))
7175
flags.String("namespace", "", heredoc.Doc(`
7276
Namespace to install the release(s) into. If not specified, each release will be
7377
installed in its own randomly generated namespace`))

doc/ct.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ in given chart directories.
2626
* [ct list-changed](ct_list-changed.md) - List changed charts
2727
* [ct version](ct_version.md) - Print version information
2828

29-
###### Auto generated by spf13/cobra on 26-Feb-2019
29+
###### Auto generated by spf13/cobra on 21-Mar-2019

doc/ct_install.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ ct install [flags]
5959
--release-label string The label to be used as a selector when inspecting resources created by charts.
6060
This is only used if namespace is specified (default "app.kubernetes.io/instance")
6161
--remote string The name of the Git remote used to identify changed charts (default "origin")
62+
--skip-missing-values When --upgrade has been passed, this flag will skip testing CI values files from the
63+
previous chart revision if they have been deleted or renamed at the current chart
64+
revision
6265
--target-branch string The name of the target branch used to identify changed charts (default "master")
6366
--upgrade Whether to test an in-place upgrade of each chart from its previous revision if the
6467
current version should not introduce a breaking change according to the SemVer spec
@@ -68,4 +71,4 @@ ct install [flags]
6871

6972
* [ct](ct.md) - The Helm chart testing tool
7073

71-
###### Auto generated by spf13/cobra on 26-Feb-2019
74+
###### Auto generated by spf13/cobra on 21-Mar-2019

doc/ct_lint-and-install.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ ct lint-and-install [flags]
5050
--release-label string The label to be used as a selector when inspecting resources created by charts.
5151
This is only used if namespace is specified (default "app.kubernetes.io/instance")
5252
--remote string The name of the Git remote used to identify changed charts (default "origin")
53+
--skip-missing-values When --upgrade has been passed, this flag will skip testing CI values files from the
54+
previous chart revision if they have been deleted or renamed at the current chart
55+
revision
5356
--target-branch string The name of the target branch used to identify changed charts (default "master")
5457
--upgrade Whether to test an in-place upgrade of each chart from its previous revision if the
5558
current version should not introduce a breaking change according to the SemVer spec
@@ -63,4 +66,4 @@ ct lint-and-install [flags]
6366

6467
* [ct](ct.md) - The Helm chart testing tool
6568

66-
###### Auto generated by spf13/cobra on 26-Feb-2019
69+
###### Auto generated by spf13/cobra on 21-Mar-2019

doc/ct_lint.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ ct lint [flags]
6565

6666
* [ct](ct.md) - The Helm chart testing tool
6767

68-
###### Auto generated by spf13/cobra on 26-Feb-2019
68+
###### Auto generated by spf13/cobra on 21-Mar-2019

doc/ct_list-changed.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ ct list-changed [flags]
2828

2929
* [ct](ct.md) - The Helm chart testing tool
3030

31-
###### Auto generated by spf13/cobra on 26-Feb-2019
31+
###### Auto generated by spf13/cobra on 21-Mar-2019

doc/ct_version.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ ct version [flags]
2020

2121
* [ct](ct.md) - The Helm chart testing tool
2222

23-
###### Auto generated by spf13/cobra on 26-Feb-2019
23+
###### Auto generated by spf13/cobra on 21-Mar-2019

pkg/chart/chart.go

+23-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package chart
1616

1717
import (
1818
"fmt"
19-
"path"
2019
"path/filepath"
2120
"strings"
2221

@@ -175,10 +174,21 @@ func (c *Chart) ValuesFilePathsForCI() []string {
175174
return c.ciValuesPaths
176175
}
177176

177+
// HasCIValuesFile checks whether a given CI values file is present.
178+
func (c *Chart) HasCIValuesFile(path string) bool {
179+
fileName := filepath.Base(path)
180+
for _, file := range c.ValuesFilePathsForCI() {
181+
if fileName == filepath.Base(file) {
182+
return true
183+
}
184+
}
185+
return false
186+
}
187+
178188
// CreateInstallParams generates a randomized release name and namespace based on the chart path
179189
// and optional buildID. If a buildID is specified, it will be part of the generated namespace.
180190
func (c *Chart) CreateInstallParams(buildID string) (release string, namespace string) {
181-
release = path.Base(c.Path())
191+
release = filepath.Base(c.Path())
182192
if release == "." || release == "/" {
183193
yaml := c.Yaml()
184194
release = yaml.Name
@@ -200,7 +210,7 @@ func NewChart(chartPath string) (*Chart, error) {
200210
if err != nil {
201211
return nil, err
202212
}
203-
matches, _ := filepath.Glob(path.Join(chartPath, "ci/*-values.yaml"))
213+
matches, _ := filepath.Glob(filepath.Join(chartPath, "ci", "*-values.yaml"))
204214
return &Chart{chartPath, yaml, matches}, nil
205215
}
206216

@@ -248,7 +258,7 @@ const ctPreviousRevisionTree = "ct_previous_revision"
248258
// computePreviousRevisionPath converts any file or directory path to the same path in the
249259
// previous revision's working tree.
250260
func computePreviousRevisionPath(fileOrDirPath string) string {
251-
return path.Join(ctPreviousRevisionTree, fileOrDirPath)
261+
return filepath.Join(ctPreviousRevisionTree, fileOrDirPath)
252262
}
253263

254264
func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestResult, error) {
@@ -389,8 +399,8 @@ func (t *Testing) LintChart(chart *Chart) TestResult {
389399
}
390400
}
391401

392-
chartYaml := path.Join(chart.Path(), "Chart.yaml")
393-
valuesYaml := path.Join(chart.Path(), "values.yaml")
402+
chartYaml := filepath.Join(chart.Path(), "Chart.yaml")
403+
valuesYaml := filepath.Join(chart.Path(), "values.yaml")
394404
valuesFiles := chart.ValuesFilePathsForCI()
395405

396406
if t.config.ValidateChartSchema {
@@ -530,7 +540,11 @@ func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) er
530540
}
531541
for _, valuesFile := range valuesFiles {
532542
if valuesFile != "" {
533-
fmt.Printf("\nInstalling chart '%s' with values file '%s'...\n\n", oldChart.Path(), valuesFile)
543+
if t.config.SkipMissingValues && !newChart.HasCIValuesFile(valuesFile) {
544+
fmt.Printf("Upgrade testing for values file '%s' skipped because a corresponding values file was not found in %s/ci", valuesFile, newChart.Path())
545+
continue
546+
}
547+
fmt.Printf("\nInstalling chart '%s' with values file '%s'...\n\n", oldChart, valuesFile)
534548
}
535549

536550
// Use anonymous function. Otherwise deferred calls would pile up
@@ -677,7 +691,7 @@ func (t *Testing) ReadAllChartDirectories() ([]string, error) {
677691
dirs, err := t.directoryLister.ListChildDirs(chartParentDir,
678692
func(dir string) bool {
679693
_, err := t.chartUtils.LookupChartDir(cfg.ChartDirs, dir)
680-
return err == nil && !util.StringSliceContains(cfg.ExcludedCharts, path.Base(dir))
694+
return err == nil && !util.StringSliceContains(cfg.ExcludedCharts, filepath.Base(dir))
681695
})
682696
if err != nil {
683697
return nil, errors.Wrap(err, "Error reading chart directories")
@@ -739,7 +753,7 @@ func (t *Testing) checkBreakingChangeAllowed(chart *Chart) (allowed bool, err er
739753
func (t *Testing) GetOldChartVersion(chartPath string) (string, error) {
740754
cfg := t.config
741755

742-
chartYamlFile := path.Join(chartPath, "Chart.yaml")
756+
chartYamlFile := filepath.Join(chartPath, "Chart.yaml")
743757
if !t.git.FileExistsOnBranch(chartYamlFile, cfg.Remote, cfg.TargetBranch) {
744758
fmt.Printf("Unable to find chart on %s. New chart detected.\n", cfg.TargetBranch)
745759
return "", nil

pkg/chart/chart_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,46 @@ func TestGenerateInstallConfig(t *testing.T) {
379379
})
380380
}
381381
}
382+
383+
func TestChart_HasCIValuesFile(t *testing.T) {
384+
type testData struct {
385+
name string
386+
chart *Chart
387+
file string
388+
expected bool
389+
}
390+
391+
testCases := []testData{
392+
{
393+
name: "has file",
394+
chart: &Chart{
395+
ciValuesPaths: []string{"foo-values.yaml"},
396+
},
397+
file: "foo-values.yaml",
398+
expected: true,
399+
},
400+
{
401+
name: "different paths",
402+
chart: &Chart{
403+
ciValuesPaths: []string{"ci/foo-values.yaml"},
404+
},
405+
file: "foo/bar/foo-values.yaml",
406+
expected: true,
407+
},
408+
{
409+
name: "does not have file",
410+
chart: &Chart{
411+
ciValuesPaths: []string{"foo-values.yaml"},
412+
},
413+
file: "bar-values.yaml",
414+
expected: false,
415+
},
416+
}
417+
418+
for _, tc := range testCases {
419+
t.Run(tc.name, func(t *testing.T) {
420+
actual := tc.chart.HasCIValuesFile(tc.file)
421+
assert.Equal(t, tc.expected, actual)
422+
})
423+
}
424+
}

pkg/config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type Configuration struct {
5757
HelmRepoExtraArgs []string `mapstructure:"helm-repo-extra-args"`
5858
Debug bool `mapstructure:"debug"`
5959
Upgrade bool `mapstructure:"upgrade"`
60+
SkipMissingValues bool `mapstructure:"skip-missing-values"`
6061
Namespace string `mapstructure:"namespace"`
6162
ReleaseLabel string `mapstructure:"release-label"`
6263
}

pkg/config/config_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func loadAndAssertConfigFromFile(t *testing.T, configFile string) {
5050
require.Equal(t, []string{"common"}, cfg.ExcludedCharts)
5151
require.Equal(t, "--timeout 300", cfg.HelmExtraArgs)
5252
require.Equal(t, true, cfg.Upgrade)
53+
require.Equal(t, true, cfg.SkipMissingValues)
5354
require.Equal(t, "default", cfg.Namespace)
5455
require.Equal(t, "release", cfg.ReleaseLabel)
5556
}

pkg/config/test_config.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
],
2626
"helm-extra-args": "--timeout 300",
2727
"upgrade": true,
28+
"skip-missing-values": true,
2829
"namespace": "default",
2930
"release-label": "release"
3031
}

pkg/config/test_config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ excluded-charts:
2020
- common
2121
helm-extra-args: --timeout 300
2222
upgrade: true
23+
skip-missing-values: true
2324
namespace: default
2425
release-label: release

0 commit comments

Comments
 (0)