Skip to content

Commit 5deb091

Browse files
authored
fix(pipeline): update Bitbucket URL handling (#2400)
Previously, when users `git clone`d their Bitbucket repos with SSH, the URL was not being appropriate parsed and reconstructed, leading to invalid URLs in their pipeline manifests and pipelines that wouldn't build. This fixes that bug (#2395), and also reformats the generated URL. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent 82df36a commit 5deb091

File tree

5 files changed

+30
-15
lines changed

5 files changed

+30
-15
lines changed

internal/pkg/cli/pipeline_init.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const (
6060
// For a Bitbucket repository.
6161
bbURL = "bitbucket.org"
6262
defaultBBBranch = "main"
63-
fmtBBRepoURL = "https://%s@%s/%s/%s" // Ex: "https://repoOwner@bitbucket.org/repoOwner/repoName
63+
fmtBBRepoURL = "https://%s/%s/%s" // Ex: "https://bitbucket.org/repoOwner/repoName"
6464
)
6565

6666
var (
@@ -365,7 +365,8 @@ func (o *initPipelineOpts) selectURL() error {
365365
// https https://git-codecommit.us-west-2.amazonaws.com/v1/repos/aws-sample (fetch)
366366
// fed codecommit::us-west-2://aws-sample (fetch)
367367
// ssh ssh://git-codecommit.us-west-2.amazonaws.com/v1/repos/aws-sample (push)
368-
// bb https://huanjani@bitbucket.org/huanjani/aws-copilot-sample-service.git (fetch)
368+
// bbhttps https://huanjani@bitbucket.org/huanjani/aws-copilot-sample-service.git (fetch)
369+
// bbssh ssh://git@bitbucket.org:teamsinspace/documentation-tests.git (fetch)
369370

370371
// parseGitRemoteResults returns just the trimmed middle column (url) of the `git remote -v` results,
371372
// and skips urls from unsupported sources.
@@ -452,14 +453,19 @@ func (url ccRepoURL) parse() (ccRepoDetails, error) {
452453
}, nil
453454
}
454455

456+
// Bitbucket URLs, post-parseGitRemoteResults(), may look like:
457+
// https://username@bitbucket.org/teamsinspace/documentation-tests
458+
// ssh://git@bitbucket.org:teamsinspace/documentation-tests
455459
func (url bbRepoURL) parse() (bbRepoDetails, error) {
456460
urlString := string(url)
457461
splitURL := strings.Split(urlString, "/")
458462
if len(splitURL) < 2 {
459463
return bbRepoDetails{}, fmt.Errorf("unable to parse the Bitbucket repository name from %s", url)
460464
}
461465
repoName := splitURL[len(splitURL)-1]
462-
repoOwner := splitURL[len(splitURL)-2]
466+
// rather than check for the SSH prefix, split on colon here; HTTPS version will be unaffected.
467+
splitRepoOwner := strings.Split(splitURL[len(splitURL)-2], ":")
468+
repoOwner := splitRepoOwner[len(splitRepoOwner)-1]
463469

464470
return bbRepoDetails{
465471
name: repoName,
@@ -610,7 +616,7 @@ func (o *initPipelineOpts) pipelineProvider() (manifest.Provider, error) {
610616
}
611617
case manifest.BitbucketProviderName:
612618
config = &manifest.BitbucketProperties{
613-
RepositoryURL: fmt.Sprintf(fmtBBRepoURL, o.repoOwner, bbURL, o.repoOwner, o.repoName),
619+
RepositoryURL: fmt.Sprintf(fmtBBRepoURL, bbURL, o.repoOwner, o.repoName),
614620
Branch: o.repoBranch,
615621
}
616622
default:

internal/pkg/cli/pipeline_init_test.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ func TestInitPipelineGHRepoURL_parse(t *testing.T) {
11121112
expectedDetails ghRepoDetails
11131113
expectedError error
11141114
}{
1115-
"matches repo name without .git suffix": {
1115+
"successfully parses name without .git suffix": {
11161116
inRepoURL: "https://github.com/badgoose/cli",
11171117

11181118
expectedDetails: ghRepoDetails{
@@ -1121,7 +1121,7 @@ func TestInitPipelineGHRepoURL_parse(t *testing.T) {
11211121
},
11221122
expectedError: nil,
11231123
},
1124-
"matches repo name with .git suffix": {
1124+
"successfully parses repo name with .git suffix": {
11251125
inRepoURL: "https://github.com/koke/grit.git",
11261126

11271127
expectedDetails: ghRepoDetails{
@@ -1159,7 +1159,7 @@ func TestInitPipelineCCRepoURL_parse(t *testing.T) {
11591159
expectedDetails ccRepoDetails
11601160
expectedError error
11611161
}{
1162-
"matches with https url": {
1162+
"successfully parses https url": {
11631163
inRepoURL: "https://git-codecommit.sa-east-1.amazonaws.com/v1/repos/aws-sample",
11641164

11651165
expectedDetails: ccRepoDetails{
@@ -1168,7 +1168,7 @@ func TestInitPipelineCCRepoURL_parse(t *testing.T) {
11681168
},
11691169
expectedError: nil,
11701170
},
1171-
"matches with ssh url": {
1171+
"successfully parses ssh url": {
11721172
inRepoURL: "ssh://git-codecommit.us-east-2.amazonaws.com/v1/repos/aws-sample",
11731173

11741174
expectedDetails: ccRepoDetails{
@@ -1177,7 +1177,7 @@ func TestInitPipelineCCRepoURL_parse(t *testing.T) {
11771177
},
11781178
expectedError: nil,
11791179
},
1180-
"matches with federated (GRC) url": {
1180+
"successfully parses federated (GRC) url": {
11811181
inRepoURL: "codecommit::us-gov-west-1://aws-sample",
11821182

11831183
expectedDetails: ccRepoDetails{
@@ -1210,9 +1210,18 @@ func TestInitPipelineBBRepoURL_parse(t *testing.T) {
12101210
expectedDetails bbRepoDetails
12111211
expectedError error
12121212
}{
1213-
"matches with https url": {
1213+
"successfully parses https url": {
12141214
inRepoURL: "https://huanjani@bitbucket.org/huanjani/aws-copilot-sample-service",
12151215

1216+
expectedDetails: bbRepoDetails{
1217+
name: "aws-copilot-sample-service",
1218+
owner: "huanjani",
1219+
},
1220+
expectedError: nil,
1221+
},
1222+
"successfully parses ssh url": {
1223+
inRepoURL: "ssh://git@bitbucket.org:huanjani/aws-copilot-sample-service",
1224+
12161225
expectedDetails: bbRepoDetails{
12171226
name: "aws-copilot-sample-service",
12181227
owner: "huanjani",

internal/pkg/deploy/cloudformation/pipeline_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func TestCloudFormation_CreatePipeline(t *testing.T) {
7777
AppName: "kudos",
7878
Name: "cicd",
7979
Source: &deploy.BitbucketSource{
80-
RepositoryURL: "https://aws@bitbucket.org/aws/somethingCool",
80+
RepositoryURL: "https://bitbucket.org/aws/somethingCool",
8181
ProviderName: "Bitbucket",
8282
Branch: "main",
8383
},

internal/pkg/deploy/cloudformation/stack/bb_pipeline_integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestBB_Pipeline_Template(t *testing.T) {
2525
Name: "phonetool-pipeline",
2626
Source: &deploy.BitbucketSource{
2727
ProviderName: manifest.BitbucketProviderName,
28-
RepositoryURL: "https://huanjani@bitbucket.org/huanjani/sample",
28+
RepositoryURL: "https://bitbucket.org/huanjani/sample",
2929
Branch: "main",
3030
},
3131
Build: deploy.PipelineBuildFromManifest(nil),

internal/pkg/deploy/pipeline.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ var (
2727
ghRepoExp = regexp.MustCompile(`(https:\/\/github\.com\/|)(?P<owner>.+)\/(?P<repo>.+)`)
2828
// Ex: https://git-codecommit.us-west-2.amazonaws.com/v1/repos/aws-sample/browse
2929
ccRepoExp = regexp.MustCompile(`(https:\/\/(?P<region>.+).console.aws.amazon.com\/codesuite\/codecommit\/repositories\/(?P<repo>.+)(\/browse))`)
30-
// Ex: https://repoOwner@bitbucket.org/repoOwner/repoName
31-
bbRepoExp = regexp.MustCompile(`(https:\/\/(.+)@bitbucket.org\/)(?P<owner>.+)\/(?P<repo>.+)`)
30+
// Ex: https://bitbucket.org/repoOwner/repoName
31+
bbRepoExp = regexp.MustCompile(`(https:\/\/bitbucket.org\/)(?P<owner>.+)\/(?P<repo>.+)`)
3232
)
3333

3434
// CreatePipelineInput represents the fields required to deploy a pipeline.
@@ -60,7 +60,7 @@ type CreatePipelineInput struct {
6060
// Build represents CodeBuild project used in the CodePipeline
6161
// to build and test Docker image.
6262
type Build struct {
63-
// The URI that identifies the Docker image to use for this build project.
63+
// The URI that identifies the Docker image to use for this build project.
6464
Image string
6565
}
6666

0 commit comments

Comments
 (0)