Skip to content

Commit c34f1dd

Browse files
committed
feat: check all git remotes for GitHub URL in ci migrate preflight
Previously, detectRepoFromGitRemote only checked the 'origin' remote. Some customers have multiple remotes where origin does not point to GitHub. Now we iterate all configured remotes and pick the first one with a github.com URL. Also adds hostname validation to parseGitHubRepo to ensure non-GitHub remotes are correctly skipped.
1 parent a586c19 commit c34f1dd

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

pkg/cmd/ci/migrate.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func secretsAndVars(ctx context.Context, opts migrateOptions) error {
9696
// Detect repo
9797
repo := detectRepoFromGitRemote(workDir)
9898
if repo == "" {
99-
return fmt.Errorf("could not detect GitHub repository from git remote — is this a GitHub repo with an origin remote?")
99+
return fmt.Errorf("could not detect GitHub repository from git remotes — is this a GitHub repo with a configured remote?")
100100
}
101101

102102
client := api.NewMigrationClient()
@@ -280,7 +280,7 @@ func preflight(ctx context.Context, opts migrateOptions) (*preflightResult, erro
280280
// Detect repo from git remote
281281
repo := detectRepoFromGitRemote(workDir)
282282
if repo == "" {
283-
return nil, fmt.Errorf("could not detect GitHub repository from git remote — is this a GitHub repo with an origin remote?")
283+
return nil, fmt.Errorf("could not detect GitHub repository from git remotes — is this a GitHub repo with a configured remote?")
284284
}
285285

286286
repoOwner := strings.SplitN(repo, "/", 2)[0]

pkg/cmd/ci/migrate_helpers.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,25 @@ func detectVariablesFromWorkflows(workflows []*migrate.WorkflowFile) ([]string,
109109
return deduped, nil
110110
}
111111

112-
// detectRepoFromGitRemote attempts to extract owner/repo from the origin remote URL.
112+
// detectRepoFromGitRemote attempts to extract owner/repo from a GitHub remote URL.
113+
// It checks all configured remotes for a GitHub URL.
113114
func detectRepoFromGitRemote(dir string) string {
114-
cmd := exec.Command("git", "-C", dir, "remote", "get-url", "origin")
115+
cmd := exec.Command("git", "-C", dir, "remote")
115116
out, err := cmd.Output()
116117
if err != nil {
117118
return ""
118119
}
119-
return parseGitHubRepo(strings.TrimSpace(string(out)))
120+
for _, name := range strings.Fields(string(out)) {
121+
urlCmd := exec.Command("git", "-C", dir, "remote", "get-url", name)
122+
urlOut, err := urlCmd.Output()
123+
if err != nil {
124+
continue
125+
}
126+
if repo := parseGitHubRepo(strings.TrimSpace(string(urlOut))); repo != "" {
127+
return repo
128+
}
129+
}
130+
return ""
120131
}
121132

122133
func parseGitHubRepo(remoteURL string) string {
@@ -126,6 +137,10 @@ func parseGitHubRepo(remoteURL string) string {
126137
if idx < 0 {
127138
return ""
128139
}
140+
host := remoteURL[len("git@"):idx]
141+
if host != "github.com" {
142+
return ""
143+
}
129144
path := remoteURL[idx+1:]
130145
path = strings.TrimSuffix(path, ".git")
131146
parts := strings.SplitN(path, "/", 3)
@@ -140,6 +155,9 @@ func parseGitHubRepo(remoteURL string) string {
140155
if err != nil {
141156
return ""
142157
}
158+
if u.Host != "github.com" {
159+
return ""
160+
}
143161
path := strings.TrimPrefix(u.Path, "/")
144162
path = strings.TrimSuffix(path, ".git")
145163
path = strings.TrimRight(path, "/")

pkg/cmd/ci/migrate_helpers_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ci
2+
3+
import "testing"
4+
5+
func TestParseGitHubRepo(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
remoteURL string
9+
want string
10+
}{
11+
{"ssh", "git@github.com:depot/cli.git", "depot/cli"},
12+
{"ssh no .git", "git@github.com:depot/cli", "depot/cli"},
13+
{"https", "https://github.com/depot/cli.git", "depot/cli"},
14+
{"https no .git", "https://github.com/depot/cli", "depot/cli"},
15+
{"https trailing slash", "https://github.com/depot/cli/", "depot/cli"},
16+
{"non-github ssh", "git@gitlab.com:depot/cli.git", ""},
17+
{"non-github https", "https://gitlab.com/depot/cli.git", ""},
18+
{"bitbucket ssh", "git@bitbucket.org:depot/cli.git", ""},
19+
{"empty", "", ""},
20+
{"invalid", "not-a-url", ""},
21+
}
22+
for _, tt := range tests {
23+
t.Run(tt.name, func(t *testing.T) {
24+
got := parseGitHubRepo(tt.remoteURL)
25+
if got != tt.want {
26+
t.Errorf("parseGitHubRepo(%q) = %q, want %q", tt.remoteURL, got, tt.want)
27+
}
28+
})
29+
}
30+
}

0 commit comments

Comments
 (0)