Use semver to enforce blueprint version numbers
This changes osbuild-composer's behavior to match lorax-composer when
encountering invalid versions. Instead of leaving them as-is it will
return a BlueprintError explaining the problem. eg.
"errors": [
{
"id": "BlueprintsError",
"msg": "Invalid 'version', must use Semantic Versioning: is not in dotted-tri format"
}
]
This is enforced on new blueprints (including the workspace). If a
previously stored blueprint has an invalid version and a new one is
pushed it will use the new version number instead of trying to bump the
invalid one.
This also moves the version bump logic into blueprint instead of store,
and adds an Initialize function that will make sure that the blueprint
has sane default values for any missing fields.
This includes tests for the Initialize and BumpVersion functions.
This commit is contained in:
parent
8e1bc2b644
commit
58839cf927
12 changed files with 647 additions and 71 deletions
|
|
@ -3,6 +3,9 @@ package blueprint
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
)
|
||||
|
||||
// A Blueprint is a high-level description of an image.
|
||||
|
|
@ -51,6 +54,39 @@ func (b *Blueprint) DeepCopy() (Blueprint, error) {
|
|||
return bp, nil
|
||||
}
|
||||
|
||||
// Initialize ensures that the blueprint has sane defaults for any missing fields
|
||||
func (b *Blueprint) Initialize() error {
|
||||
if b.Packages == nil {
|
||||
b.Packages = []Package{}
|
||||
}
|
||||
if b.Modules == nil {
|
||||
b.Modules = []Package{}
|
||||
}
|
||||
if b.Groups == nil {
|
||||
b.Groups = []Group{}
|
||||
}
|
||||
// Return an error if the version is not valid
|
||||
_, err := semver.NewVersion(b.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid 'version', must use Semantic Versioning: %s", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BumpVersion increments the previous blueprint's version
|
||||
// If the old version string is not vaild semver it will use the new version as-is
|
||||
// This assumes that the new blueprint's version has already been validated via Initialize
|
||||
func (b *Blueprint) BumpVersion(old string) {
|
||||
var ver *semver.Version
|
||||
ver, err := semver.NewVersion(old)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ver.BumpPatch()
|
||||
b.Version = ver.String()
|
||||
}
|
||||
|
||||
// packages, modules, and groups all resolve to rpm packages right now. This
|
||||
// function returns a combined list of "name-version" strings.
|
||||
func (b *Blueprint) GetPackages() []string {
|
||||
|
|
|
|||
|
|
@ -36,3 +36,53 @@ func TestDeepCopy(t *testing.T) {
|
|||
t.Fatalf("Blueprint.DeepCopy failed, copy modified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlueprintInitialize(t *testing.T) {
|
||||
cases := []struct {
|
||||
NewBlueprint Blueprint
|
||||
ExpectedError bool
|
||||
}{
|
||||
{Blueprint{Name: "bp-test-1", Description: "Empty version", Version: ""}, true},
|
||||
{Blueprint{Name: "bp-test-2", Description: "Invalid version 1", Version: "0"}, true},
|
||||
{Blueprint{Name: "bp-test-2", Description: "Invalid version 2", Version: "0.0"}, true},
|
||||
{Blueprint{Name: "bp-test-3", Description: "Invalid version 3", Version: "0.0.0.0"}, true},
|
||||
{Blueprint{Name: "bp-test-4", Description: "Invalid version 4", Version: "0.a.0"}, true},
|
||||
{Blueprint{Name: "bp-test-5", Description: "Invalid version 5", Version: "foo"}, true},
|
||||
{Blueprint{Name: "bp-test-7", Description: "Zero version", Version: "0.0.0"}, false},
|
||||
{Blueprint{Name: "bp-test-8", Description: "X.Y.Z version", Version: "2.1.3"}, false},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
bp := c.NewBlueprint
|
||||
err := bp.Initialize()
|
||||
if (err != nil) != c.ExpectedError {
|
||||
t.Errorf("Initialize(%#v) returned an unexpected error: %s", c.NewBlueprint, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpVersion(t *testing.T) {
|
||||
cases := []struct {
|
||||
NewBlueprint Blueprint
|
||||
OldVersion string
|
||||
ExpectedVersion string
|
||||
}{
|
||||
{Blueprint{Name: "bp-test-1", Description: "Empty version", Version: "0.0.1"}, "", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-2", Description: "Invalid version 1", Version: "0.0.1"}, "0", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-3", Description: "Invalid version 2", Version: "0.0.1"}, "0.0.0.0", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-4", Description: "Invalid version 3", Version: "0.0.1"}, "0.a.0", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-5", Description: "Invalid version 4", Version: "0.0.1"}, "foo", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-6", Description: "Invalid version 5", Version: "0.0.1"}, "0.0", "0.0.1"},
|
||||
{Blueprint{Name: "bp-test-8", Description: "Same version", Version: "4.2.0"}, "4.2.0", "4.2.1"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
bp := c.NewBlueprint
|
||||
bp.Initialize()
|
||||
|
||||
bp.BumpVersion(c.OldVersion)
|
||||
if bp.Version != c.ExpectedVersion {
|
||||
t.Errorf("BumpVersion(%#v) is expected to return %#v, but instead returned %#v", c.OldVersion, c.ExpectedVersion, bp.Version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue