Skip to content

Commit e1ec3af

Browse files
authored
chore: bump to Go 1.26, harden release workflow, tidy code (helm#835)
* chore: bump to Go 1.26 and golangci-lint v2.12 Signed-off-by: Carlos Panato <ctadeu@gmail.com> * ci: harden release workflow against script injection Signed-off-by: Carlos Panato <ctadeu@gmail.com> * chore: tidy code and tests - Drop dead rand.New init in pkg/util (Go's global source has been auto-seeded since 1.20). - Replace StringSliceContains helper with slices.Contains. - Fix nil-pointer panic risk in GetRandomPort by moving defer past the error check. - Remove unused TestResults struct; replace with a local bool. - Switch interface{} to any across touched files. - Iterate strings.FieldsSeq instead of materializing a slice in GetDeploymentsRollout. - Tests: use t.Setenv, t.Helper, require.True/False, assert.NoError. - Preallocate kubectlArgs slice in GetPods. - Drop redundant err.Error() under %v in config flag-binding panic. Signed-off-by: Carlos Panato <ctadeu@gmail.com> --------- Signed-off-by: Carlos Panato <ctadeu@gmail.com>
1 parent ceb983e commit e1ec3af

9 files changed

Lines changed: 52 additions & 76 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
- name: Setup go
3131
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
3232
with:
33-
go-version: '1.25'
33+
go-version: '1.26'
3434
check-latest: true
3535
cache: false
3636

@@ -99,7 +99,7 @@ jobs:
9999

100100
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
101101
with:
102-
go-version: '1.25'
102+
go-version: '1.26'
103103
check-latest: true
104104
cache: false
105105

@@ -128,11 +128,11 @@ jobs:
128128

129129
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
130130
with:
131-
go-version: '1.25'
131+
go-version: '1.26'
132132
check-latest: true
133133
cache: false
134134

135135
- name: golangci-lint
136136
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
137137
with:
138-
version: v2.7
138+
version: v2.12

.github/workflows/release.yaml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ jobs:
2222
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2323
with:
2424
fetch-depth: 0
25+
persist-credentials: true
2526

2627
- name: shellcheck
2728
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
2829

2930
- name: Setup go
3031
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
3132
with:
32-
go-version: '1.25'
33+
go-version: '1.26'
3334
check-latest: true
3435
cache: false
3536

@@ -69,20 +70,23 @@ jobs:
6970
password: ${{ secrets.DOCKER_PASSWORD }}
7071

7172
- name: Tag
73+
env:
74+
INPUTS_VERSION: ${{ github.event.inputs.version }}
7275
run: |
7376
git config user.name "$GITHUB_ACTOR"
7477
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
7578
76-
tag='${{ github.event.inputs.version }}'
79+
tag="${INPUTS_VERSION}"
7780
git tag --annotate --message "Tag for release $tag" "$tag"
7881
git push origin "refs/tags/$tag"
7982
8083
- name: Build
8184
env:
8285
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86+
INPUTS_VERSION: ${{ github.event.inputs.version }}
8387
run: |
8488
set -o nounset
8589
set -o pipefail
8690
87-
echo "Building release ${{ github.event.inputs.version }}"
91+
echo "Building release ${INPUTS_VERSION}"
8892
./build.sh --release

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/helm/chart-testing/v3
22

3-
go 1.25.0
3+
go 1.26
44

55
require (
66
github.com/MakeNowJust/heredoc v1.0.0

pkg/chart/chart.go

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"path/filepath"
22+
"slices"
2223
"strings"
2324

2425
"github.com/Masterminds/semver"
@@ -144,7 +145,7 @@ type Linter interface {
144145
//
145146
// RunCommand renders cmdTemplate as go template using data and executes the resulting command
146147
type CmdExecutor interface {
147-
RunCommand(cmdTemplate string, data interface{}) error
148+
RunCommand(cmdTemplate string, data any) error
148149
}
149150

150151
// DirectoryLister is the interface
@@ -253,12 +254,6 @@ type Testing struct {
253254
loadRules func(string) (*helmignore.Rules, error)
254255
}
255256

256-
// TestResults holds results and overall status
257-
type TestResults struct {
258-
OverallSuccess bool
259-
TestResults []TestResult
260-
}
261-
262257
// TestResult holds test results for a specific chart
263258
type TestResult struct {
264259
Chart *Chart
@@ -368,10 +363,7 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes
368363
}
369364
}
370365

371-
testResults := TestResults{
372-
OverallSuccess: true,
373-
TestResults: results,
374-
}
366+
overallSuccess := true
375367

376368
// Checkout previous chart revisions and build their dependencies
377369
if t.config.Upgrade {
@@ -410,11 +402,11 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes
410402

411403
result := action(chart)
412404
if result.Error != nil {
413-
testResults.OverallSuccess = false
405+
overallSuccess = false
414406
}
415407
results = append(results, result)
416408
}
417-
if testResults.OverallSuccess {
409+
if overallSuccess {
418410
return results, nil
419411
}
420412

@@ -764,7 +756,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) {
764756
changedChartFiles := map[string][]string{}
765757
for _, file := range allChangedChartFiles {
766758
pathElements := strings.SplitN(filepath.ToSlash(file), "/", 3)
767-
if len(pathElements) < 2 || util.StringSliceContains(cfg.ExcludedCharts, pathElements[1]) {
759+
if len(pathElements) < 2 || slices.Contains(cfg.ExcludedCharts, pathElements[1]) {
768760
continue
769761
}
770762
dir := filepath.Dir(file)
@@ -774,7 +766,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) {
774766
if err == nil {
775767
if len(chartDirElement) > 1 {
776768
chartDirName := chartDirElement[len(chartDirElement)-1]
777-
if util.StringSliceContains(cfg.ExcludedCharts, chartDirName) {
769+
if slices.Contains(cfg.ExcludedCharts, chartDirName) {
778770
continue
779771
}
780772
}
@@ -818,7 +810,7 @@ func (t *Testing) ReadAllChartDirectories() ([]string, error) {
818810
dirs, err := t.directoryLister.ListChildDirs(chartParentDir,
819811
func(dir string) bool {
820812
_, err := t.utils.LookupChartDir(cfg.ChartDirs, dir)
821-
return err == nil && !util.StringSliceContains(cfg.ExcludedCharts, filepath.Base(dir))
813+
return err == nil && !slices.Contains(cfg.ExcludedCharts, filepath.Base(dir))
822814
})
823815
if err != nil {
824816
return nil, fmt.Errorf("failed reading chart directories: %w", err)

pkg/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*C
9090
if flagName != "config" && flagName != "help" {
9191
if err := v.BindPFlag(flagName, flag); err != nil {
9292
// can't really happen
93-
panic(fmt.Sprintf("failed binding flag %q: %v\n", flagName, err.Error()))
93+
panic(fmt.Sprintf("failed binding flag %q: %v\n", flagName, err))
9494
}
9595
}
9696
})

pkg/config/config_test.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package config
1616

1717
import (
18-
"os"
1918
"path/filepath"
2019
"testing"
2120
"time"
@@ -34,6 +33,7 @@ func TestUnmarshalJson(t *testing.T) {
3433
}
3534

3635
func loadAndAssertConfigFromFile(t *testing.T, configFile string) {
36+
t.Helper()
3737
cfg, _ := LoadConfiguration(configFile, &cobra.Command{
3838
Use: "install",
3939
}, true)
@@ -43,25 +43,25 @@ func loadAndAssertConfigFromFile(t *testing.T, configFile string) {
4343
require.Equal(t, "pr-42", cfg.BuildID)
4444
require.Equal(t, "my-lint-conf.yaml", cfg.LintConf)
4545
require.Equal(t, "my-chart-yaml-schema.yaml", cfg.ChartYamlSchema)
46-
require.Equal(t, true, cfg.ValidateMaintainers)
47-
require.Equal(t, true, cfg.ValidateChartSchema)
48-
require.Equal(t, true, cfg.ValidateYaml)
49-
require.Equal(t, true, cfg.CheckVersionIncrement)
50-
require.Equal(t, false, cfg.ProcessAllCharts)
46+
require.True(t, cfg.ValidateMaintainers)
47+
require.True(t, cfg.ValidateChartSchema)
48+
require.True(t, cfg.ValidateYaml)
49+
require.True(t, cfg.CheckVersionIncrement)
50+
require.False(t, cfg.ProcessAllCharts)
5151
require.Equal(t, []string{"incubator=https://incubator"}, cfg.ChartRepos)
5252
require.Equal(t, []string{"incubator=--username test"}, cfg.HelmRepoExtraArgs)
5353
require.Equal(t, []string{"stable", "incubator"}, cfg.ChartDirs)
5454
require.Equal(t, []string{"common"}, cfg.ExcludedCharts)
5555
require.Equal(t, "--timeout 300s", cfg.HelmExtraArgs)
5656
require.Equal(t, "--quiet", cfg.HelmLintExtraArgs)
57-
require.Equal(t, true, cfg.Upgrade)
58-
require.Equal(t, true, cfg.SkipMissingValues)
57+
require.True(t, cfg.Upgrade)
58+
require.True(t, cfg.SkipMissingValues)
5959
require.Equal(t, "default", cfg.Namespace)
6060
require.Equal(t, "release", cfg.ReleaseLabel)
61-
require.Equal(t, true, cfg.ExcludeDeprecated)
61+
require.True(t, cfg.ExcludeDeprecated)
6262
require.Equal(t, 120*time.Second, cfg.KubectlTimeout)
63-
require.Equal(t, true, cfg.SkipCleanUp)
64-
require.Equal(t, true, cfg.UseHelmignore)
63+
require.True(t, cfg.SkipCleanUp)
64+
require.True(t, cfg.UseHelmignore)
6565
}
6666

6767
func Test_findConfigFile(t *testing.T) {
@@ -96,13 +96,7 @@ func Test_findConfigFile(t *testing.T) {
9696
for _, tt := range tests {
9797
t.Run(tt.name, func(t *testing.T) {
9898
if tt.envVar != "" {
99-
err := os.Setenv("CT_CONFIG_DIR", tt.envVar)
100-
require.NoError(t, err)
101-
102-
t.Cleanup(func() {
103-
err := os.Unsetenv("CT_CONFIG_DIR")
104-
require.NoError(t, err)
105-
})
99+
t.Setenv("CT_CONFIG_DIR", tt.envVar)
106100
}
107101
configSearchLocations = []string{tt.defaultDir}
108102

pkg/tool/kubectl.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (k Kubectl) forceNamespaceDeletion(namespace string) error {
7878
return err
7979
}
8080

81-
namespaceUpdate := map[string]interface{}{}
81+
namespaceUpdate := map[string]any{}
8282
err = json.Unmarshal([]byte(cmdOutput), &namespaceUpdate)
8383
if err != nil {
8484
fmt.Println("Error in unmarshalling the payload:", err)
@@ -154,8 +154,7 @@ func (k Kubectl) WaitForDeployments(namespace string, selector string) error {
154154
return err
155155
}
156156

157-
deployments := strings.Fields(output)
158-
for _, deployment := range deployments {
157+
for deployment := range strings.FieldsSeq(output) {
159158
deployment = strings.Trim(deployment, "'")
160159
err = k.exec.RunProcess("kubectl",
161160
fmt.Sprintf("--request-timeout=%s", k.timeout),
@@ -188,15 +187,15 @@ func (k Kubectl) GetPodsforDeployment(namespace string, deployment string) ([]st
188187
jsonString, _ := k.exec.RunProcessAndCaptureStdout("kubectl",
189188
fmt.Sprintf("--request-timeout=%s", k.timeout),
190189
"get", "deployment", deployment, "--namespace", namespace, "--output=json")
191-
var deploymentMap map[string]interface{}
190+
var deploymentMap map[string]any
192191
err := json.Unmarshal([]byte(jsonString), &deploymentMap)
193192
if err != nil {
194193
return nil, err
195194
}
196195

197-
spec := deploymentMap["spec"].(map[string]interface{})
198-
selector := spec["selector"].(map[string]interface{})
199-
matchLabels := selector["matchLabels"].(map[string]interface{})
196+
spec := deploymentMap["spec"].(map[string]any)
197+
selector := spec["selector"].(map[string]any)
198+
matchLabels := selector["matchLabels"].(map[string]any)
200199
var ls string
201200
for name, value := range matchLabels {
202201
if ls != "" {
@@ -209,7 +208,8 @@ func (k Kubectl) GetPodsforDeployment(namespace string, deployment string) ([]st
209208
}
210209

211210
func (k Kubectl) GetPods(args ...string) ([]string, error) {
212-
kubectlArgs := []string{"get", "pods"}
211+
kubectlArgs := make([]string, 0, 2+len(args))
212+
kubectlArgs = append(kubectlArgs, "get", "pods")
213213
kubectlArgs = append(kubectlArgs, args...)
214214
pods, err := k.exec.RunProcessAndCaptureStdout("kubectl",
215215
fmt.Sprintf("--request-timeout=%s", k.timeout), kubectlArgs)

pkg/util/util.go

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"path/filepath"
2626
"regexp"
2727
"strings"
28-
"time"
2928

3029
"github.com/Masterminds/semver"
3130
"github.com/hashicorp/go-multierror"
@@ -46,23 +45,19 @@ type ChartYaml struct {
4645
Maintainers []Maintainer
4746
}
4847

49-
func Flatten(items []interface{}) ([]string, error) {
48+
func Flatten(items []any) ([]string, error) {
5049
return doFlatten([]string{}, items)
5150
}
5251

53-
func init() {
54-
rand.New(rand.NewSource(time.Now().UnixNano())) // nolint: gosec
55-
}
56-
57-
func doFlatten(result []string, items interface{}) ([]string, error) {
52+
func doFlatten(result []string, items any) ([]string, error) {
5853
var err error
5954

6055
switch v := items.(type) {
6156
case string:
6257
result = append(result, v)
6358
case []string:
6459
result = append(result, v...)
65-
case []interface{}:
60+
case []any:
6661
for _, item := range v {
6762
result, err = doFlatten(result, item)
6863
if err != nil {
@@ -76,15 +71,6 @@ func doFlatten(result []string, items interface{}) ([]string, error) {
7671
return result, err
7772
}
7873

79-
func StringSliceContains(slice []string, s string) bool {
80-
for _, element := range slice {
81-
if s == element {
82-
return true
83-
}
84-
}
85-
return false
86-
}
87-
8874
func FileExists(file string) bool {
8975
if _, err := os.Stat(file); err != nil {
9076
return false
@@ -243,10 +229,10 @@ func SanitizeName(s string, maxLength int) string {
243229

244230
func GetRandomPort() (int, error) {
245231
listener, err := net.Listen("tcp", ":0") // nolint: gosec
246-
defer listener.Close() // nolint: staticcheck
247232
if err != nil {
248233
return 0, err
249234
}
235+
defer listener.Close() // nolint: errcheck
250236

251237
return listener.Addr().(*net.TCPAddr).Port, nil
252238
}

pkg/util/util_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,23 @@ import (
2424

2525
func TestFlatten(t *testing.T) {
2626
var testDataSlice = []struct {
27-
input []interface{}
27+
input []any
2828
expected []string
2929
}{
30-
{[]interface{}{"foo", "bar", []string{"bla", "blubb"}}, []string{"foo", "bar", "bla", "blubb"}},
31-
{[]interface{}{"foo", "bar", "bla", "blubb"}, []string{"foo", "bar", "bla", "blubb"}},
32-
{[]interface{}{"foo", "bar", []interface{}{"bla", []string{"blubb"}}}, []string{"foo", "bar", "bla", "blubb"}},
33-
{[]interface{}{"foo", 42, []interface{}{"bla", []string{"blubb"}}}, nil},
30+
{[]any{"foo", "bar", []string{"bla", "blubb"}}, []string{"foo", "bar", "bla", "blubb"}},
31+
{[]any{"foo", "bar", "bla", "blubb"}, []string{"foo", "bar", "bla", "blubb"}},
32+
{[]any{"foo", "bar", []any{"bla", []string{"blubb"}}}, []string{"foo", "bar", "bla", "blubb"}},
33+
{[]any{"foo", 42, []any{"bla", []string{"blubb"}}}, nil},
3434
}
3535

3636
for index, testData := range testDataSlice {
3737
t.Run(strconv.Itoa(index), func(t *testing.T) {
3838
actual, err := Flatten(testData.input)
3939
assert.Equal(t, testData.expected, actual)
4040
if testData.expected != nil {
41-
assert.Nil(t, err)
41+
assert.NoError(t, err)
4242
} else {
43-
assert.NotNil(t, err)
43+
assert.Error(t, err)
4444
}
4545
})
4646
}

0 commit comments

Comments
 (0)