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
17 changes: 12 additions & 5 deletions server/events/github_app_working_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,16 @@ type GithubAppWorkingDir struct {

// Clone writes a fresh token for Github App authentication
func (g *GithubAppWorkingDir) Clone(logger logging.SimpleLogging, headRepo models.Repo, p models.PullRequest, workspace string) (string, error) {
baseRepo := &p.BaseRepo
g.fixReposURL(&p, &headRepo)
return g.WorkingDir.Clone(logger, headRepo, p, workspace)
}

func (g *GithubAppWorkingDir) MergeAgain(logger logging.SimpleLogging, headRepo models.Repo, p models.PullRequest, workspace string) (bool, error) {
g.fixReposURL(&p, &headRepo)
return g.WorkingDir.MergeAgain(logger, headRepo, p, workspace)
}

func (g *GithubAppWorkingDir) fixReposURL(p *models.PullRequest, headRepo *models.Repo) {
// Realistically, this is a super brittle way of supporting clones using gh app installation tokens
// This URL should be built during Repo creation and the struct should be immutable going forward.
// Doing this requires a larger refactor however, and can probably be coupled with supporting > 1 installation
Expand All @@ -31,10 +39,9 @@ func (g *GithubAppWorkingDir) Clone(logger logging.SimpleLogging, headRepo model
// git will then pick up credentials from the credential store which is set in vcs.WriteGitCreds.
// Git credentials will then be rotated by vcs.GitCredsTokenRotator
replacement := "://"
baseRepo.CloneURL = strings.Replace(baseRepo.CloneURL, "://:@", replacement, 1)
baseRepo.SanitizedCloneURL = strings.Replace(baseRepo.SanitizedCloneURL, redactedReplacement, replacement, 1)
p.BaseRepo.CloneURL = strings.Replace(p.BaseRepo.CloneURL, "://:@", replacement, 1)
p.BaseRepo.SanitizedCloneURL = strings.Replace(p.BaseRepo.SanitizedCloneURL, redactedReplacement, replacement, 1)
headRepo.CloneURL = strings.Replace(headRepo.CloneURL, "://:@", replacement, 1)
headRepo.SanitizedCloneURL = strings.Replace(baseRepo.SanitizedCloneURL, redactedReplacement, replacement, 1)
headRepo.SanitizedCloneURL = strings.Replace(p.BaseRepo.SanitizedCloneURL, redactedReplacement, replacement, 1)

return g.WorkingDir.Clone(logger, headRepo, p, workspace)
}
46 changes: 46 additions & 0 deletions server/events/github_app_working_dir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,49 @@ func TestClone_GithubAppSetsCorrectUrl(t *testing.T) {

Ok(t, err)
}

// Similar to `Clone()`
// `MergeAgain()` should set the repo URL correctly
func TestMergeAgain_GithubAppSetsCorrectUrl(t *testing.T) {
logger := logging.NewNoopLogger(t)

RegisterMockTestingT(t)

workingDir := eventMocks.NewMockWorkingDir()

credentials := vcsMocks.NewMockGithubCredentials()

ghAppWorkingDir := events.GithubAppWorkingDir{
WorkingDir: workingDir,
Credentials: credentials,
GithubHostname: "some-host",
}

baseRepo, _ := models.NewRepo(
models.Github,
"runatlantis/atlantis",
"https://github.com/runatlantis/atlantis.git",

// user and token have to be blank otherwise this proxy wouldn't be invoked to begin with
"",
"",
)

headRepo := baseRepo

modifiedBaseRepo := baseRepo
// remove credentials from both urls since we want to use the credential store
modifiedBaseRepo.CloneURL = "https://github.com/runatlantis/atlantis.git"
modifiedBaseRepo.SanitizedCloneURL = "https://github.com/runatlantis/atlantis.git"

When(credentials.GetToken()).ThenReturn("token", nil)
When(workingDir.MergeAgain(Any[logging.SimpleLogging](), Eq(modifiedBaseRepo), Eq(models.PullRequest{BaseRepo: modifiedBaseRepo}),
Eq("default"))).ThenReturn(false, nil)

_, err := ghAppWorkingDir.MergeAgain(logger, headRepo, models.PullRequest{BaseRepo: baseRepo}, "default")

// MergeAgain
workingDir.VerifyWasCalledOnce().MergeAgain(logger, modifiedBaseRepo, models.PullRequest{BaseRepo: modifiedBaseRepo}, "default")

Ok(t, err)
}