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
23 changes: 20 additions & 3 deletions pkg/blueprint/blueprint_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ func (b *BaseBlueprintHandler) LoadConfig() error {
return err
}

if err := b.setRepositoryDefaults(); err != nil {
return fmt.Errorf("error setting repository defaults: %w", err)
}

b.configLoaded = true
return nil
}
Expand Down Expand Up @@ -1831,7 +1835,9 @@ func (b *BaseBlueprintHandler) setRepositoryDefaults() error {
return nil
}

if b.configHandler.GetBool("dev") {
devMode := b.configHandler.GetBool("dev")

if devMode {
url := b.getDevelopmentRepositoryURL()
if url != "" {
b.blueprint.Repository.Url = url
Expand All @@ -1841,17 +1847,28 @@ func (b *BaseBlueprintHandler) setRepositoryDefaults() error {

gitURL, err := b.shell.ExecSilent("git", "config", "--get", "remote.origin.url")
if err == nil && gitURL != "" {
b.blueprint.Repository.Url = strings.TrimSpace(gitURL)
b.blueprint.Repository.Url = b.normalizeGitURL(strings.TrimSpace(gitURL))
return nil
}

return nil
}

// normalizeGitURL normalizes git repository URLs by prepending https:// when needed.
// Preserves SSH URLs (git@...), http://, and https:// URLs as-is.
func (b *BaseBlueprintHandler) normalizeGitURL(url string) string {
if strings.HasPrefix(url, "git@") ||
strings.HasPrefix(url, "http://") ||
strings.HasPrefix(url, "https://") {
return url
}
return "https://" + url
}

// getDevelopmentRepositoryURL generates a development repository URL from configuration.
// Returns URL in format: http://git.<domain>/git/<folder>
func (b *BaseBlueprintHandler) getDevelopmentRepositoryURL() string {
domain := b.configHandler.GetString("dns.domain")
domain := b.configHandler.GetString("dns.domain", "test")
if domain == "" {
return ""
}
Expand Down
99 changes: 96 additions & 3 deletions pkg/blueprint/blueprint_handler_private_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3511,6 +3511,33 @@ func TestBaseBlueprintHandler_setRepositoryDefaults(t *testing.T) {
}
})

t.Run("PreservesSSHGitRemoteOrigin", func(t *testing.T) {
handler := setup(t)

mockConfigHandler := handler.configHandler.(*config.MockConfigHandler)
mockConfigHandler.GetBoolFunc = func(key string, defaultValue ...bool) bool {
return false
}

mockShell := handler.shell.(*shell.MockShell)
mockShell.ExecSilentFunc = func(command string, args ...string) (string, error) {
if command == "git" && len(args) == 3 && args[0] == "config" && args[2] == "remote.origin.url" {
return "git@github.com:windsorcli/core.git\n", nil
}
return "", fmt.Errorf("command not found")
}

err := handler.setRepositoryDefaults()

if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
expectedURL := "git@github.com:windsorcli/core.git"
if handler.blueprint.Repository.Url != expectedURL {
t.Errorf("Expected URL to be %s, got %s", expectedURL, handler.blueprint.Repository.Url)
}
})

t.Run("HandlesGitRemoteOriginError", func(t *testing.T) {
handler := setup(t)

Expand Down Expand Up @@ -3589,6 +3616,64 @@ func TestBaseBlueprintHandler_setRepositoryDefaults(t *testing.T) {
t.Errorf("Expected URL to be %s, got %s", expectedURL, handler.blueprint.Repository.Url)
}
})

}

func TestBaseBlueprintHandler_normalizeGitURL(t *testing.T) {
setup := func(t *testing.T) *BaseBlueprintHandler {
t.Helper()
mocks := setupMocks(t)
handler := NewBlueprintHandler(mocks.Injector)
return handler
}

t.Run("PreservesSSHURL", func(t *testing.T) {
handler := setup(t)

input := "git@github.com:windsorcli/core.git"
expected := "git@github.com:windsorcli/core.git"
result := handler.normalizeGitURL(input)

if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
})

t.Run("PreservesHTTPSURL", func(t *testing.T) {
handler := setup(t)

input := "https://github.com/windsorcli/core.git"
expected := "https://github.com/windsorcli/core.git"
result := handler.normalizeGitURL(input)

if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
})

t.Run("PreservesHTTPURL", func(t *testing.T) {
handler := setup(t)

input := "http://git.test/git/core"
expected := "http://git.test/git/core"
result := handler.normalizeGitURL(input)

if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
})

t.Run("PrependsHTTPSToPlainURL", func(t *testing.T) {
handler := setup(t)

input := "github.com/windsorcli/core.git"
expected := "https://github.com/windsorcli/core.git"
result := handler.normalizeGitURL(input)

if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
})
}

func TestBaseBlueprintHandler_getDevelopmentRepositoryURL(t *testing.T) {
Expand Down Expand Up @@ -3630,11 +3715,14 @@ func TestBaseBlueprintHandler_getDevelopmentRepositoryURL(t *testing.T) {
}
})

t.Run("ReturnsEmptyWhenDomainNotSet", func(t *testing.T) {
t.Run("UsesDefaultDomainWhenNotSet", func(t *testing.T) {
handler := setup(t)

mockConfigHandler := handler.configHandler.(*config.MockConfigHandler)
mockConfigHandler.GetStringFunc = func(key string, defaultValue ...string) string {
if key == "dns.domain" && len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}

Expand All @@ -3643,10 +3731,15 @@ func TestBaseBlueprintHandler_getDevelopmentRepositoryURL(t *testing.T) {
return "/home/user/projects/my-project", nil
}

handler.shims.FilepathBase = func(path string) string {
return "my-project"
}

url := handler.getDevelopmentRepositoryURL()

if url != "" {
t.Errorf("Expected empty URL when domain not set, got %s", url)
expectedURL := "http://git.test/git/my-project"
if url != expectedURL {
t.Errorf("Expected URL to be %s, got %s", expectedURL, url)
}
})

Expand Down
75 changes: 75 additions & 0 deletions pkg/blueprint/blueprint_handler_public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,81 @@ func TestBlueprintHandler_LoadConfig(t *testing.T) {
t.Errorf("expected normalized path, got %q", ks[0].Path)
}
})

t.Run("SetsRepositoryDefaultsInDevMode", func(t *testing.T) {
handler, mocks := setup(t)

mockConfigHandler := mocks.ConfigHandler.(*config.MockConfigHandler)
mockConfigHandler.GetBoolFunc = func(key string, defaultValue ...bool) bool {
if key == "dev" {
return true
}
return false
}
mockConfigHandler.GetStringFunc = func(key string, defaultValue ...string) string {
if key == "dns.domain" && len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
mockConfigHandler.GetBoolFunc = func(key string, defaultValue ...bool) bool {
if key == "dev" {
return true
}
return false
}
mockConfigHandler.GetConfigRootFunc = func() (string, error) {
return "/tmp/test-config", nil
}

mocks.Shell.GetProjectRootFunc = func() (string, error) {
return "/Users/test/project/cli", nil
}

handler.shims.FilepathBase = func(path string) string {
if path == "/Users/test/project/cli" {
return "cli"
}
return ""
}

handler.shims.Stat = func(name string) (os.FileInfo, error) {
if strings.HasSuffix(name, ".yaml") {
return nil, nil
}
return nil, os.ErrNotExist
}

blueprintWithoutURL := `kind: Blueprint
apiVersion: v1alpha1
metadata:
name: test-blueprint
description: A test blueprint
repository:
ref:
branch: main
sources: []
terraform: []
kustomize: []`

handler.shims.ReadFile = func(name string) ([]byte, error) {
if strings.HasSuffix(name, ".yaml") {
return []byte(blueprintWithoutURL), nil
}
return nil, os.ErrNotExist
}

err := handler.LoadConfig()

if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

expectedURL := "http://git.test/git/cli"
if handler.blueprint.Repository.Url != expectedURL {
t.Errorf("Expected repository URL to be %s, got %s", expectedURL, handler.blueprint.Repository.Url)
}
})
}

func TestBlueprintHandler_Install(t *testing.T) {
Expand Down
Loading