Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cmd/ocm-backplane/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ var UpgradeCmd = &cobra.Command{

func runUpgrade(cmd *cobra.Command, _ []string) error {

if err := validateReleaseVersion(info.Version); err != nil {
return err
}

ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()

Expand All @@ -44,3 +48,18 @@ func runUpgrade(cmd *cobra.Command, _ []string) error {

return upgrade.UpgradePlugin(ctx, info.Version)
}

// validateReleaseVersion ensures the binary carries the release version metadata
// that the native self-upgrade relies on for the SemVer comparison. This metadata
// is injected via ldflags only when building official release binaries, so a CLI
// built without that injection (commonly a local source build) has an empty
// version and cannot self-upgrade.
func validateReleaseVersion(version string) error {
if version == "" {
return fmt.Errorf("release version metadata is missing; this commonly happens when the CLI is built from source without release version injection. " +
"Native self-upgrade requires release version metadata. " +
"Install or update Backplane CLI through an official release channel")
}

return nil
}
13 changes: 13 additions & 0 deletions cmd/ocm-backplane/upgrade/upgrade_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package upgrade

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestUpgrade(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Upgrade Command Test Suite")
}
36 changes: 36 additions & 0 deletions cmd/ocm-backplane/upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package upgrade

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("validateReleaseVersion", func() {
Context("when the release version metadata is missing", func() {
It("returns a clear, actionable error", func() {
err := validateReleaseVersion("")

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("release version metadata is missing"))
Expect(err.Error()).To(ContainSubstring("built from source"))
Expect(err.Error()).To(ContainSubstring("official release channel"))
})

It("does not expose the raw SemVer parsing error", func() {
err := validateReleaseVersion("")

Expect(err).To(HaveOccurred())
Expect(err.Error()).ToNot(ContainSubstring("Invalid Semantic Version"))
})
})

Context("when the release version metadata is present", func() {
It("does not trigger the missing-version validation", func() {
Expect(validateReleaseVersion("1.0.1")).To(Succeed())
})

It("passes the version through unchanged regardless of its format", func() {
Expect(validateReleaseVersion("1.0.1-0.20261009184111-fc8c9e8dedd0")).To(Succeed())
})
})
})