add `helm bump [VERSION_TYPE] [CHART]` for setting chart versions

Signed-off-by: Jan Braje <12571346+janluak@users.noreply.github.com>
pull/32402/head
Jan Braje 3 months ago
parent 06978bd8c5
commit 3120d85753
No known key found for this signature in database
GPG Key ID: AA98A2FCFE70D0C9

@ -0,0 +1,353 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"errors"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
"helm.sh/helm/v4/pkg/chart/v2/loader"
"helm.sh/helm/v4/pkg/chart/v2/util"
)
// Bump is the action for bumping a chart version.
//
// It provides the implementation of 'helm bump'.
type Bump struct {
ChartPathOptions
cfg *Configuration
bump string
chart *chart.Chart
}
const defaultBumpType = "patch"
// NewBump creates a new Bump object with the given configuration.
func NewBump(cfg *Configuration) *Bump {
return &Bump{
cfg: cfg,
}
}
// Run executes 'helm bump' against the given chart.
func (b *Bump) Run(bumpType string, chartpath string) (string, error) {
if b.chart == nil {
chrt, err := loader.Load(chartpath)
if err != nil {
return "", err
}
b.chart = chrt
}
cv, err := yaml.Marshal(b.chart.Metadata.Version)
if err != nil {
return "", err
}
// Determine new version based on bump type or explicit version
b.bump = bumpType
if b.bump == "" {
// Default to "patch" if no version specified
b.bump = defaultBumpType
}
currentVersion := strings.TrimSpace(string(cv))
if !isValidVersion(currentVersion) {
return "", fmt.Errorf("invalid origin version: %s", currentVersion)
}
var newVersion string
switch b.bump {
case "major":
newVersion, err = bumpMajor(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump major version: %w", err)
}
case "minor":
newVersion, err = bumpMinor(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump minor version: %w", err)
}
case "patch":
newVersion, err = bumpPatch(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump patch version: %w", err)
}
case "stable":
newVersion, err = bumpStable(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump stable version: %w", err)
}
case "alpha":
newVersion, err = bumpAlpha(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump alpha version: %w", err)
}
case "beta":
newVersion, err = bumpBeta(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump beta version: %w", err)
}
case "rc":
newVersion, err = bumpRC(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump rc version: %w", err)
}
case "post":
newVersion, err = bumpPost(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump post version: %w", err)
}
case "dev":
newVersion, err = bumpDev(currentVersion)
if err != nil {
return "", fmt.Errorf("failed to bump dev version: %w", err)
}
default:
if !isValidVersion(b.bump) {
return "", fmt.Errorf("invalid bump type or version: %s", b.bump)
}
newVersion = b.bump
}
// Update the chart metadata with the new version
b.chart.Metadata.Version = newVersion
// Save the updated chart to disk (this will update Chart.yaml)
err = util.SaveChartfile(filepath.Join(chartpath, "Chart.yaml"), b.chart.Metadata)
if err != nil {
return "", fmt.Errorf("failed to save updated chart: %w", err)
}
return newVersion, nil
}
// bumpMajor increases the major version number (e.g., 1.2.3 -> 2.0.0)
func bumpMajor(version string) (string, error) {
parts := strings.Split(version, ".")
if len(parts) < 3 {
return "", errors.New("invalid version format for major bump")
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return "", errors.New("invalid major version number")
}
newMajor := major + 1
return fmt.Sprintf("%d.0.0", newMajor), nil
}
// bumpMinor increases the minor version number (e.g., 1.2.3 -> 1.3.0)
func bumpMinor(version string) (string, error) {
parts := strings.Split(version, ".")
if len(parts) < 3 {
return "", errors.New("invalid version format for minor bump")
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return "", errors.New("invalid major version number")
}
minor, err := strconv.Atoi(parts[1])
if err != nil {
return "", errors.New("invalid minor version number")
}
newMinor := minor + 1
return fmt.Sprintf("%d.%d.0", major, newMinor), nil
}
// bumpPatch increases the patch version number (e.g., 1.2.3 -> 1.2.4)
func bumpPatch(version string) (string, error) {
parts := strings.Split(version, ".")
if len(parts) < 3 {
return "", errors.New("invalid version format for patch bump")
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return "", errors.New("invalid major version number")
}
minor, err := strconv.Atoi(parts[1])
if err != nil {
return "", errors.New("invalid minor version number")
}
patch, err := strconv.Atoi(parts[2])
if err != nil {
return "", errors.New("invalid patch version number")
}
newPatch := patch + 1
return fmt.Sprintf("%d.%d.%d", major, minor, newPatch), nil
}
// bumpStable removes any pre-release suffix (e.g., 1.2.3-alpha -> 1.2.3)
func bumpStable(version string) (string, error) {
// Remove any pre-release suffixes (like -alpha, -beta, etc.)
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-.+)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for stable bump")
}
return matches[1], nil
}
// bumpAlpha increases the pre-release version (e.g., 1.2.3-alpha -> 1.2.3-alpha.1)
func bumpAlpha(version string) (string, error) {
// Check if version has an alpha suffix - simple regex that works with all cases
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-alpha(?:\.(\d+))?)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for alpha bump")
}
baseVersion := matches[1]
var preRelease string
if len(matches) >= 4 && matches[3] != "" {
// Increment the pre-release number
num, err := strconv.Atoi(matches[3])
if err != nil {
return "", errors.New("invalid alpha pre-release number")
}
preRelease = fmt.Sprintf(".%d", num+1)
} else {
// Start with .1 if no pre-release number exists
preRelease = ".1"
}
return baseVersion + "-alpha" + preRelease, nil
}
// bumpBeta increases the pre-release version (e.g., 1.2.3-beta -> 1.2.3-beta.1)
func bumpBeta(version string) (string, error) {
// Check if version has a beta suffix - simple regex that works with all cases
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-beta(?:\.(\d+))?)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for beta bump")
}
baseVersion := matches[1]
var preRelease string
if len(matches) >= 4 && matches[3] != "" {
// Increment the pre-release number
num, err := strconv.Atoi(matches[3])
if err != nil {
return "", errors.New("invalid beta pre-release number")
}
preRelease = fmt.Sprintf(".%d", num+1)
} else {
// Start with .1 if no pre-release number exists
preRelease = ".1"
}
return baseVersion + "-beta" + preRelease, nil
}
// bumpRC increases the pre-release version (e.g., 1.2.3-rc -> 1.2.3-rc.1)
func bumpRC(version string) (string, error) {
// Check if version has a rc suffix - simple regex that works with all cases
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-rc(?:\.(\d+))?)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for rc bump")
}
baseVersion := matches[1]
var preRelease string
if len(matches) >= 4 && matches[3] != "" {
// Increment the pre-release number
num, err := strconv.Atoi(matches[3])
if err != nil {
return "", errors.New("invalid rc pre-release number")
}
preRelease = fmt.Sprintf(".%d", num+1)
} else {
// Start with .1 if no pre-release number exists
preRelease = ".1"
}
return baseVersion + "-rc" + preRelease, nil
}
// bumpPost increases the post-release version (e.g., 1.2.3-post -> 1.2.3-post.1)
func bumpPost(version string) (string, error) {
// Check if version has a post-suffix
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-post(\.(\d+))?)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for post bump")
}
baseVersion := matches[1]
var preRelease string
if len(matches) >= 4 && matches[4] != "" {
// Increment the pre-release number
num, err := strconv.Atoi(matches[4])
if err != nil {
return "", errors.New("invalid post pre-release number")
}
preRelease = fmt.Sprintf(".%d", num+1)
} else {
// Start with .1 if no pre-release number exists
preRelease = ".1"
}
return baseVersion + "-post" + preRelease, nil
}
// bumpDev increases the dev version (e.g., 1.2.3-dev -> 1.2.3-dev.1)
func bumpDev(version string) (string, error) {
// Check if version has a dev suffix
re := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-dev(\.(\d+))?)?$`)
matches := re.FindStringSubmatch(version)
if len(matches) < 2 {
return "", errors.New("invalid version format for dev bump")
}
baseVersion := matches[1]
var preRelease string
if len(matches) >= 4 && matches[4] != "" {
// Increment the pre-release number
num, err := strconv.Atoi(matches[4])
if err != nil {
return "", errors.New("invalid dev pre-release number")
}
preRelease = fmt.Sprintf(".%d", num+1)
} else {
// Start with .1 if no pre-release number exists
preRelease = ".1"
}
return baseVersion + "-dev" + preRelease, nil
}
// isValidVersion checks if a string is a valid semantic version format
func isValidVersion(version string) bool {
re := regexp.MustCompile(`^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+(\.\d+)?)?$`)
return re.MatchString(version)
}

@ -0,0 +1,437 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
chart "helm.sh/helm/v4/pkg/chart/v2"
)
func TestNewBump(t *testing.T) {
cfg := actionConfigFixture(t)
client := NewBump(cfg)
assert.NotNil(t, client)
require.Equal(t, cfg, client.cfg)
}
func TestBump_Run_Major(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Major bump with valid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("major", "")
require.NoError(t, err)
require.Equal(t, "2.0.0", result)
})
t.Run("Major bump with invalid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("major", "")
require.Error(t, err)
require.Empty(t, result)
})
t.Run("Major bump with invalid major version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.a"
result, err := client.Run("major", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Minor(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Minor bump with valid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("minor", "")
require.NoError(t, err)
require.Equal(t, "1.3.0", result)
})
t.Run("Minor bump with invalid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("minor", "")
require.Error(t, err)
require.Empty(t, result)
})
t.Run("Minor bump with invalid minor version", func(t *testing.T) {
client.chart.Metadata.Version = "1.a.3"
result, err := client.Run("minor", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Patch(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Patch bump with valid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("patch", "")
require.NoError(t, err)
require.Equal(t, "1.2.4", result)
})
t.Run("Patch bump with invalid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("patch", "")
require.Error(t, err)
require.Empty(t, result)
})
t.Run("Patch bump with invalid patch version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.a"
result, err := client.Run("patch", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Stable(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Stable bump with pre-release version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-alpha"
result, err := client.Run("stable", "")
require.NoError(t, err)
require.Equal(t, "1.2.3", result)
})
t.Run("Stable bump with pre-release version with number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-alpha.1"
result, err := client.Run("stable", "")
require.NoError(t, err)
require.Equal(t, "1.2.3", result)
})
t.Run("Stable bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("stable", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Alpha(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Alpha bump with version without pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("alpha", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-alpha.1", result)
})
t.Run("Alpha bump with version with pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-alpha"
result, err := client.Run("alpha", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-alpha.1", result)
})
t.Run("Alpha bump with version with pre-release number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-alpha.1"
result, err := client.Run("alpha", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-alpha.2", result)
})
t.Run("Alpha bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("alpha", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Beta(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Beta bump with version without pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("beta", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-beta.1", result)
})
t.Run("Beta bump with version with pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-beta"
result, err := client.Run("beta", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-beta.1", result)
})
t.Run("Beta bump with version with pre-release number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-beta.1"
result, err := client.Run("beta", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-beta.2", result)
})
t.Run("Beta bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("beta", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_RC(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("RC bump with version without pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("rc", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-rc.1", result)
})
t.Run("RC bump with version with pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-rc"
result, err := client.Run("rc", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-rc.1", result)
})
t.Run("RC bump with version with pre-release number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-rc.1"
result, err := client.Run("rc", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-rc.2", result)
})
t.Run("RC bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("rc", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Post(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Post bump with version without pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("post", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-post.1", result)
})
t.Run("Post bump with version with post-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-post"
result, err := client.Run("post", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-post.1", result)
})
t.Run("Post bump with version with pre-release number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-post.1"
result, err := client.Run("post", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-post.2", result)
})
t.Run("Post bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("post", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_Dev(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Dev bump with version without pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("dev", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-dev.1", result)
})
t.Run("Dev bump with version with pre-release", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-dev"
result, err := client.Run("dev", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-dev.1", result)
})
t.Run("Dev bump with version with pre-release number", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3-dev.1"
result, err := client.Run("dev", "")
require.NoError(t, err)
require.Equal(t, "1.2.3-dev.2", result)
})
t.Run("Dev bump with invalid version format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2"
result, err := client.Run("dev", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_Run_ExplicitVersion(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
t.Run("Explicit version with valid format", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("2.0.1", "")
require.NoError(t, err)
require.Equal(t, "2.0.1", result)
})
t.Run("Explicit version with post version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("1.5.3-post.1", "")
require.NoError(t, err)
require.Equal(t, "1.5.3-post.1", result)
})
}
func TestBump_Run_InvalidVersion(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
// We cannot test actual bumping since chart loading is not implemented,
// but we can test error handling for invalid bump types
t.Run("Invalid bump type", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("invalid", "")
require.Error(t, err)
require.Empty(t, result)
})
}
func TestBump_IsValidVersion(t *testing.T) {
t.Parallel()
testCases := []struct {
version string
expected bool
}{
{"1.2.3", true},
{"1.2.3-alpha", true},
{"1.2.3-beta.1", true},
{"1.2.3-rc.2", true},
{"1.2.3-post.1", true},
{"1.2.3-dev.1", true},
{"1.2", false},
{"invalid", false},
{"1.2.3.4", false},
{"1.a.3", false},
}
for _, tc := range testCases {
t.Run("Version "+tc.version, func(t *testing.T) {
result := isValidVersion(tc.version)
require.Equal(t, tc.expected, result)
})
}
}
func TestBump_Run_WithDefault(t *testing.T) {
t.Parallel()
cfg := actionConfigFixture(t)
client := NewBump(cfg)
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test"},
}
// Test that it properly handles the default case
t.Run("Patch bump with valid version", func(t *testing.T) {
client.chart.Metadata.Version = "1.2.3"
result, err := client.Run("patch", "")
require.NoError(t, err)
require.Equal(t, "1.2.4", result)
require.Equal(t, "patch", client.bump)
})
}

@ -0,0 +1,84 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"io"
"path/filepath"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/action"
"helm.sh/helm/v4/pkg/cmd/require"
)
const bumpDesc = `
Bump the version of a chart.
`
type bumpOptions struct {
bumpType string
chart string
}
// newBumpCmd creates a new bump command with the given configuration and output writer.
func newBumpCmd(actionConfig *action.Configuration, out io.Writer) *cobra.Command {
o := &bumpOptions{}
cmd := &cobra.Command{
Use: "bump [VERSION_TYPE] [CHART]",
Short: "bump the version of a chart",
Long: bumpDesc,
Args: require.MaximumNArgs(2),
ValidArgsFunction: noMoreArgsCompFunc,
RunE: func(_ *cobra.Command, args []string) error {
if len(args) == 2 {
o.bumpType = args[0]
o.chart = args[1]
} else {
o.bumpType = ""
o.chart = args[0]
}
return o.run(actionConfig, out)
},
}
f := cmd.Flags()
f.StringVar(&o.chart, "chart", "", "path to the chart directory")
return cmd
}
func (o *bumpOptions) run(actionConfig *action.Configuration, out io.Writer) error {
// Resolve the chart path to an absolute path
absPath, err := filepath.Abs(o.chart)
if err != nil {
return fmt.Errorf("failed to resolve chart path: %w", err)
}
o.chart = absPath
bump := action.NewBump(actionConfig)
newVersion, err := bump.Run(o.bumpType, o.chart)
if err != nil {
return err
}
fmt.Fprintf(out, "changed chart version to %q\n", newVersion)
return nil
}

@ -0,0 +1,63 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"io"
"os"
"path/filepath"
"testing"
)
func TestBump(t *testing.T) {
tempChartDir := t.TempDir()
testChartFile := filepath.Join("testdata", "testcharts", "empty", "Chart.yaml")
destFile := filepath.Join(tempChartDir, "Chart.yaml")
srcFile, err := os.Open(testChartFile)
if err != nil {
t.Fatalf("error on opening test file: %v", err)
}
defer srcFile.Close()
destFileHandle, err := os.Create(destFile)
if err != nil {
t.Fatalf("error on creating test file: %v", err)
}
defer destFileHandle.Close()
_, err = io.Copy(destFileHandle, srcFile)
if err != nil {
t.Fatalf("error on copying test file: %v", err)
}
tests := []cmdTestCase{{
name: "default",
cmd: "bump " + tempChartDir,
golden: "output/bump-default.txt",
}, {
name: "with bump type",
cmd: "bump minor " + tempChartDir,
golden: "output/bump-minor.txt",
}, {
name: "with explicit version",
cmd: "bump 2.0.0 " + tempChartDir,
golden: "output/bump-explicit.txt",
}}
runTestCmd(t, tests)
}

@ -286,6 +286,7 @@ func newRootCmdWithConfig(actionConfig *action.Configuration, out io.Writer, arg
newRollbackCmd(actionConfig, out),
newStatusCmd(actionConfig, out),
newTemplateCmd(actionConfig, out),
newBumpCmd(actionConfig, out),
newUninstallCmd(actionConfig, out),
newUpgradeCmd(actionConfig, out),

@ -0,0 +1 @@
changed chart version to "0.1.1"

@ -0,0 +1 @@
changed chart version to "2.0.0"

@ -0,0 +1 @@
changed chart version to "0.2.0"
Loading…
Cancel
Save