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
4 changes: 2 additions & 2 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ builds:
- arm64
- amd64
ldflags:
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/cmd.version={{ .Version }}'"
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/pkg/constants.Version={{ .Version }}'"
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/pkg/constants.CommitSHA={{ .Env.GITHUB_SHA }}'"
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/pkg/secrets.version={{ .Version }}'"
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/cmd.commitSHA={{ .Env.GITHUB_SHA }}'"
- "-X 'github.com/{{ .Env.GITHUB_REPOSITORY }}/pkg/constants.PinnedBlueprintURL={{ .Env.PINNED_BLUEPRINT_URL }}'"

# Archive configuration
Expand Down
3 changes: 0 additions & 3 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,6 @@ var initCmd = &cobra.Command{
}

if err := proj.Initialize(initReset); err != nil {
if !verbose {
return nil
}
return err
}

Expand Down
9 changes: 2 additions & 7 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ import (
"runtime"

"github.com/spf13/cobra"
)

// These variables will be set at build time
var (
version = "dev"
commitSHA = "none"
"github.com/windsorcli/cli/pkg/constants"
)

// Goos returns the operating system, can be mocked for testing
Expand All @@ -24,7 +19,7 @@ var versionCmd = &cobra.Command{
SilenceUsage: true,
Run: func(cmd *cobra.Command, args []string) {
platform := fmt.Sprintf("%s/%s", Goos, runtime.GOARCH)
cmd.Printf("Version: %s\nCommit SHA: %s\nPlatform: %s\n", version, commitSHA, platform)
cmd.Printf("Version: %s\nCommit SHA: %s\nPlatform: %s\n", constants.Version, constants.CommitSHA, platform)
},
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.25.3

require (
github.com/1password/onepassword-sdk-go v0.3.1
github.com/Masterminds/semver/v3 v3.4.0
github.com/abiosoft/colima v0.9.1
github.com/briandowns/spinner v1.23.2
github.com/compose-spec/compose-go/v2 v2.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.53.0/go.mod h1:jUZ5LYlw40WMd07qxcQJD5M40aUxrfwqQX1g7zxYnrQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 h1:Ron4zCA/yk6U7WOBXhTJcDpsUBG9npumK6xw2auFltQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0/go.mod h1:cSgYe11MCNYunTnRXrKiR/tHc0eoKjICUuWpNZoVCOo=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
Expand Down
50 changes: 50 additions & 0 deletions pkg/composer/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import (
"strings"
"time"

"github.com/Masterminds/semver/v3"
"github.com/briandowns/spinner"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/static"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/windsorcli/cli/pkg/constants"
"github.com/windsorcli/cli/pkg/runtime"
"github.com/windsorcli/cli/pkg/runtime/shell"
)
Expand All @@ -41,6 +43,7 @@ type BlueprintMetadata struct {
Tags []string `json:"tags,omitempty"`
Homepage string `json:"homepage,omitempty"`
License string `json:"license,omitempty"`
CliVersion string `json:"cliVersion,omitempty"`
Timestamp string `json:"timestamp"`
Git GitProvenance `json:"git"`
Builder BuilderInfo `json:"builder"`
Expand Down Expand Up @@ -78,6 +81,7 @@ type BlueprintMetadataInput struct {
Tags []string `yaml:"tags,omitempty"`
Homepage string `yaml:"homepage,omitempty"`
License string `yaml:"license,omitempty"`
CliVersion string `yaml:"cliVersion,omitempty"`
}

// =============================================================================
Expand Down Expand Up @@ -395,6 +399,9 @@ func (a *ArtifactBuilder) GetTemplateData(ociRef string) (map[string][]byte, err
if err := a.shims.YamlUnmarshal(content, &metadata); err != nil {
return nil, fmt.Errorf("failed to parse metadata.yaml: %w", err)
}
if err := ValidateCliVersion(constants.Version, metadata.CliVersion); err != nil {
return nil, err
}
metadataName = metadata.Name
case name == "_template/schema.yaml":
schemaContent, err = io.ReadAll(tarReader)
Expand Down Expand Up @@ -666,6 +673,9 @@ func (a *ArtifactBuilder) parseTagAndResolveMetadata(repoName, tag string) (stri
if err := a.shims.YamlUnmarshal(metadataFileInfo.Content, &input); err != nil {
return "", "", nil, fmt.Errorf("failed to parse metadata.yaml: %w", err)
}
if err := ValidateCliVersion(constants.Version, input.CliVersion); err != nil {
return "", "", nil, err
}
}

finalName := input.Name
Expand Down Expand Up @@ -937,6 +947,10 @@ func (a *ArtifactBuilder) generateMetadataWithNameVersion(input BlueprintMetadat
Builder: builderInfo,
}

if input.CliVersion != "" {
metadata.CliVersion = input.CliVersion
}

return a.shims.YamlMarshal(metadata)
}

Expand Down Expand Up @@ -1121,5 +1135,41 @@ func IsAuthenticationError(err error) bool {
return false
}

// ValidateCliVersion validates that the provided CLI version satisfies the cliVersion constraint
// specified in the template metadata. If constraint is empty, validation is skipped.
// If cliVersion is empty, validation is skipped (caller cannot determine version).
// If the CLI version is "dev" or "main" or "latest", validation is skipped as these are development builds.
// Returns an error if the constraint is specified and the version does not satisfy it.
func ValidateCliVersion(cliVersion, constraint string) error {
if constraint == "" {
return nil
}

if cliVersion == "" {
return nil
}

if cliVersion == "dev" || cliVersion == "main" || cliVersion == "latest" {
return nil
}

versionStr := strings.TrimPrefix(cliVersion, "v")
version, err := semver.NewVersion(versionStr)
if err != nil {
return fmt.Errorf("invalid CLI version format '%s': %w", cliVersion, err)
}

c, err := semver.NewConstraint(constraint)
if err != nil {
return fmt.Errorf("invalid cliVersion constraint '%s': %w", constraint, err)
}

if !c.Check(version) {
return fmt.Errorf("CLI version %s does not satisfy required constraint '%s'", cliVersion, constraint)
}

return nil
}

// Ensure ArtifactBuilder implements Artifact interface
var _ Artifact = (*ArtifactBuilder)(nil)
Loading
Loading