Skip to content

Commit ee4c1e9

Browse files
committed
fix(lifecycle): only prefix semver tags with 'v'
Change automatic v prefixing to only apply to semver tags. Signed-off-by: Erik Cederberg <erik.cederberg@sectra.com>
1 parent 28ee4ef commit ee4c1e9

File tree

2 files changed

+48
-142
lines changed

2 files changed

+48
-142
lines changed

pkg/porter/lifecycle.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ func (p *Porter) BuildActionArgs(ctx context.Context, installation storage.Insta
364364
}
365365

366366
// ensureVPrefix adds a "v" prefix to the version tag if it's not already there.
367-
// Version tag should always be prefixed with a "v", see https://github.com/getporter/porter/issues/2886.
367+
// Semver version tags tag should always be prefixed with a "v", see https://github.com/getporter/porter/issues/2886.
368368
// This is safe because "porter publish" adds a "v", see
369369
// https://github.com/getporter/porter/blob/17bd7816ef6bde856793f6122e32274aa9d01d1b/pkg/storage/installation.go#L350
370370
func ensureVPrefix(opts *BundleReferenceOptions, out io.Writer) error {
@@ -379,8 +379,8 @@ func ensureVPrefix(opts *BundleReferenceOptions, out io.Writer) error {
379379
ociRef = &ref
380380
}
381381

382-
if ociRef.Tag() == "" || ociRef.Tag() == "latest" || strings.HasPrefix(ociRef.Tag(), "v") {
383-
// don't do anything if missing tag, if tag is "latest", or if "v" is already there
382+
// Do nothing for empty tags, non semver-tags or if tag is not a version
383+
if !tagStartsWithNumber(ociRef) || !ociRef.HasVersion() {
384384
return nil
385385
}
386386

@@ -398,6 +398,10 @@ func ensureVPrefix(opts *BundleReferenceOptions, out io.Writer) error {
398398
return nil
399399
}
400400

401+
func tagStartsWithNumber(ociRef *cnab.OCIReference) bool {
402+
return ociRef.HasTag() && ociRef.Tag()[0] >= '0' && ociRef.Tag()[0] <= '9'
403+
}
404+
401405
// prepullBundleByReference handles calling the bundle pull operation and updating
402406
// the shared options like name and bundle file path. This is used by install, upgrade
403407
// and uninstall

pkg/porter/lifecycle_test.go

+41-139
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package porter
22

33
import (
44
"context"
5-
"fmt"
65
"io"
76
"runtime"
87
"sort"
9-
"strings"
108
"testing"
119

1210
"get.porter.sh/porter/pkg"
@@ -540,167 +538,71 @@ func TestPorter_applyActionOptionsToInstallation_PreservesExistingParams(t *test
540538
}, params, "Incorrect parameter values were persisted on the installationß")
541539
}
542540

543-
// make sure ensureVPrefix correctly adds a 'v' to the version tag of a reference
544541
func Test_ensureVPrefix(t *testing.T) {
545-
type args struct {
546-
opts *BundleReferenceOptions
547-
}
548-
549542
ref, err := cnab.ParseOCIReference("registry/bundle:1.2.3")
550-
assert.NoError(t, err)
543+
require.NoError(t, err)
551544

552545
testCases := []struct {
553-
name string
554-
args args
555-
wantErr assert.ErrorAssertionFunc
546+
name string
547+
reference string
548+
ref *cnab.OCIReference
549+
want string
550+
wantRefTag string
556551
}{
557552
{
558-
name: "add v to Reference (nil _ref)",
559-
args: struct{ opts *BundleReferenceOptions }{opts: &BundleReferenceOptions{
560-
installationOptions: installationOptions{},
561-
BundlePullOptions: BundlePullOptions{
562-
Reference: "registry/bundle:1.2.3",
563-
_ref: nil,
564-
InsecureRegistry: false,
565-
Force: false,
566-
},
567-
bundleRef: nil,
568-
},
569-
}, wantErr: assert.NoError,
553+
name: "adds v prefix to semver reference",
554+
reference: "registry/bundle:1.2.3",
555+
ref: nil,
556+
want: "registry/bundle:v1.2.3",
570557
},
571558
{
572-
name: "add v to Reference (non-nil _ref)",
573-
args: struct{ opts *BundleReferenceOptions }{opts: &BundleReferenceOptions{
574-
installationOptions: installationOptions{},
575-
BundlePullOptions: BundlePullOptions{
576-
Reference: "registry/bundle:1.2.3",
577-
_ref: &ref,
578-
InsecureRegistry: false,
579-
Force: false,
580-
},
581-
bundleRef: nil,
582-
},
583-
}, wantErr: assert.NoError,
559+
name: "updates _ref if present",
560+
reference: "registry/bundle:1.2.3",
561+
ref: &ref,
562+
want: "registry/bundle:v1.2.3",
563+
wantRefTag: "v1.2.3",
584564
},
585-
}
586-
for _, tt := range testCases {
587-
t.Run(tt.name, func(t *testing.T) {
588-
// before
589-
idx := strings.LastIndex(tt.args.opts.Reference, ":")
590-
assert.False(t, tt.args.opts.Reference[idx+1] == 'v')
591-
if tt.args.opts._ref != nil {
592-
assert.False(t, tt.args.opts._ref.Tag()[0] == 'v')
593-
}
594-
595-
err := ensureVPrefix(tt.args.opts, io.Discard)
596-
597-
// after
598-
tt.wantErr(t, err, fmt.Sprintf("ensureVPrefix(%v)", tt.args.opts))
599-
600-
idx = strings.LastIndex(tt.args.opts.Reference, ":")
601-
assert.True(t, tt.args.opts.Reference[idx+1] == 'v')
602-
if tt.args.opts._ref != nil {
603-
assert.True(t, tt.args.opts._ref.Tag()[0] == 'v')
604-
}
605-
})
606-
}
607-
}
608-
609-
// make sure ensureVPrefix doesn't add an extra 'v' to the version tag of a reference if it's already there
610-
func Test_ensureVPrefix_idempotent(t *testing.T) {
611-
type args struct {
612-
opts *BundleReferenceOptions
613-
}
614-
615-
vRef, err := cnab.ParseOCIReference("registry/bundle:v1.2.3")
616-
assert.NoError(t, err)
617-
618-
testcasesIdempotent := []struct {
619-
name string
620-
args args
621-
wantErr assert.ErrorAssertionFunc
622-
}{
623565
{
624-
name: "don't add v to Reference with existing v (nil _ref)",
625-
args: struct{ opts *BundleReferenceOptions }{opts: &BundleReferenceOptions{
626-
installationOptions: installationOptions{},
627-
BundlePullOptions: BundlePullOptions{
628-
Reference: "registry/bundle:v1.2.3",
629-
_ref: nil,
630-
InsecureRegistry: false,
631-
Force: false,
632-
},
633-
bundleRef: nil,
634-
},
635-
}, wantErr: assert.NoError,
566+
name: "is idempotent",
567+
reference: "registry/bundle:v1.2.3",
568+
ref: nil,
569+
want: "registry/bundle:v1.2.3",
636570
},
637571
{
638-
name: "don't add v to Reference with existing v (non-nil _ref)",
639-
args: struct{ opts *BundleReferenceOptions }{opts: &BundleReferenceOptions{
640-
installationOptions: installationOptions{},
641-
BundlePullOptions: BundlePullOptions{
642-
Reference: "registry/bundle:v1.2.3",
643-
_ref: &vRef,
644-
InsecureRegistry: false,
645-
Force: false,
646-
},
647-
bundleRef: nil,
648-
},
649-
}, wantErr: assert.NoError,
572+
name: "ignores non-semver references",
573+
reference: "registry/bundle:latest",
574+
ref: nil,
575+
want: "registry/bundle:latest",
576+
},
577+
{
578+
name: "ignores references with no tag",
579+
reference: "registry/bundle",
580+
ref: nil,
581+
want: "registry/bundle",
650582
},
651583
}
652-
for _, tt := range testcasesIdempotent {
653-
t.Run(tt.name, func(t *testing.T) {
654-
// before
655-
idx := strings.LastIndex(tt.args.opts.Reference, ":")
656-
assert.True(t, tt.args.opts.Reference[idx+1] == 'v')
657-
assert.True(t, tt.args.opts.Reference[idx+2] != 'v')
658-
if tt.args.opts._ref != nil {
659-
assert.True(t, tt.args.opts._ref.Tag()[0] == 'v')
660-
assert.True(t, tt.args.opts._ref.Tag()[1] != 'v')
661-
}
662-
663-
err := ensureVPrefix(tt.args.opts, io.Discard)
664-
665-
// after
666-
tt.wantErr(t, err, fmt.Sprintf("ensureVPrefix(%v)", tt.args.opts))
667-
668-
idx = strings.LastIndex(tt.args.opts.Reference, ":")
669-
assert.True(t, tt.args.opts.Reference[idx+1] == 'v')
670-
assert.True(t, tt.args.opts.Reference[idx+2] != 'v')
671-
if tt.args.opts._ref != nil {
672-
assert.True(t, tt.args.opts._ref.Tag()[0] == 'v')
673-
assert.True(t, tt.args.opts._ref.Tag()[1] != 'v')
674-
}
675-
})
676-
}
677-
}
678584

679-
// ensure no v is added if specifying :latest tag or no tag at all
680-
func Test_ensureVPrefix_latest(t *testing.T) {
681-
testcases := map[string]struct {
682-
latestRef string
683-
}{
684-
"latest": {latestRef: "example/porter-hello:latest"},
685-
"not-latest": {latestRef: "example/porter-hello"},
686-
}
687-
for name, test := range testcases {
688-
t.Run(name, func(t *testing.T) {
585+
for _, tc := range testCases {
586+
t.Run(tc.name, func(t *testing.T) {
689587
opts := BundleReferenceOptions{
690588
installationOptions: installationOptions{},
691589
BundlePullOptions: BundlePullOptions{
692-
Reference: test.latestRef,
693-
_ref: nil,
590+
Reference: tc.reference,
591+
_ref: tc.ref,
694592
InsecureRegistry: false,
695593
Force: false,
696594
},
697595
bundleRef: nil,
698596
}
699-
err := ensureVPrefix(&opts, io.Discard)
700-
assert.NoError(t, err)
701597

702-
// shouldn't change
703-
assert.Equal(t, test.latestRef, opts.BundlePullOptions.Reference)
598+
err = ensureVPrefix(&opts, io.Discard)
599+
600+
assert.Equal(t, tc.want, opts.BundlePullOptions.Reference)
601+
assert.NoError(t, err)
602+
if tc.wantRefTag != "" {
603+
require.NotNil(t, opts.BundlePullOptions._ref)
604+
assert.Equal(t, tc.wantRefTag, opts.BundlePullOptions._ref.Tag())
605+
}
704606
})
705607
}
706608
}

0 commit comments

Comments
 (0)