Skip to content

Commit

Permalink
chore: try to auto-detect default branch name
Browse files Browse the repository at this point in the history
  • Loading branch information
snakster committed Dec 22, 2023
1 parent c7f2a37 commit b0c146c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 10 deletions.
17 changes: 13 additions & 4 deletions cmd/terramate/cli/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,23 @@ func (p *project) setDefaults() error {
gitOpt.DefaultBranchBaseRef = defaultBranchBaseRef
}

if gitOpt.DefaultBranch == "" {
gitOpt.DefaultBranch = defaultBranch
}

if gitOpt.DefaultRemote == "" {
gitOpt.DefaultRemote = defaultRemote
}

if gitOpt.DefaultBranch == "" {
autoDefaultBranch := ""
if p.git.wrapper != nil {
autoDefaultBranch = p.git.wrapper.RemoteDefaultBranch(gitOpt.DefaultRemote)
}

if autoDefaultBranch != "" {
gitOpt.DefaultBranch = autoDefaultBranch
} else {
gitOpt.DefaultBranch = defaultBranch
}
}

return nil
}

Expand Down
31 changes: 26 additions & 5 deletions cmd/terramate/e2etests/core/general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func TestMainAfterOriginMainMustUseDefaultBaseRef(t *testing.T) {
AssertRunResult(t, ts.ListChangedStacks(), wantRes)
}

func TestFailsOnChangeDetectionIfRepoDoesntHaveOriginMain(t *testing.T) {
func TestFailsOnChangeDetectionIfRepoDoesntHaveOrigin(t *testing.T) {
t.Parallel()

rootdir := test.TempDir(t)
Expand Down Expand Up @@ -344,10 +344,6 @@ func TestFailsOnChangeDetectionIfRepoDoesntHaveOriginMain(t *testing.T) {

git.SetupRemote("notorigin", "main", "main")
assertFails("repository must have a configured")

git.CheckoutNew("not-main")
git.SetupRemote("origin", "not-main", "main")
assertFails("has no default branch ")
}

func TestNoArgsProvidesBasicHelp(t *testing.T) {
Expand All @@ -368,6 +364,17 @@ func TestFailsIfDefaultRemoteDoesntHaveDefaultBranch(t *testing.T) {
})

cli := NewCLI(t, s.RootDir())

test.WriteFile(t, s.RootDir(), "terramate.tm.hcl", `
terramate {
config {
git {
default_branch = "wrong"
}
}
}
`)

AssertRunResult(t,
cli.ListChangedStacks(),
RunExpected{
Expand Down Expand Up @@ -414,6 +421,20 @@ terramate {
AssertRun(t, cli.ListChangedStacks())
}

func TestDefaultBranchDetection(t *testing.T) {
t.Parallel()

s := sandbox.NewWithGitConfig(t, sandbox.GitConfig{
DefaultRemoteName: "origin",
DefaultRemoteBranchName: "master",
LocalBranchName: "feat",
})

cli := newCLI(t, s.RootDir())

Check failure on line 433 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / Build and Test (windows-2022, 1.20)

undefined: newCLI

Check failure on line 433 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-20.04, 1.20)

undefined: newCLI

Check failure on line 433 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / checks

undefined: newCLI

assertRun(t, cli.listChangedStacks())

Check failure on line 435 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / Build and Test (windows-2022, 1.20)

undefined: assertRun

Check failure on line 435 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-20.04, 1.20)

undefined: assertRun

Check failure on line 435 in cmd/terramate/e2etests/core/general_test.go

View workflow job for this annotation

GitHub Actions / checks

undefined: assertRun (typecheck)
}

func TestE2ETerramateLogsWarningIfRootConfigIsNotAtProjectRoot(t *testing.T) {
t.Parallel()

Expand Down
36 changes: 36 additions & 0 deletions git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"os"
"os/exec"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -733,6 +734,41 @@ func (git *Git) GetConfigValue(key string) (string, error) {
return "", err
}
return strings.TrimSpace(s), nil

}

// RemoteDefaultBranch returns the default branch for the given remote,
// or an empty string if detection failed.
func (git *Git) RemoteDefaultBranch(remote string) string {
logger := log.With().
Str("action", "Git.RemoteDefaultBranch()").
Str("remote", remote).
Logger()

// First try to get default branch from local information
if out, err := git.exec("symbolic-ref", fmt.Sprintf("refs/remotes/%s/HEAD", remote), "--short"); err == nil {
if strings.HasPrefix(out, remote+"/") {
return strings.TrimPrefix(out, remote+"/")
}
logger.Debug().Msgf("failed to parse remote branch name from symbolic-ref: '%s'", out)
} else {
logger.Debug().Err(err).Msg("failed to get name of default branch locally")
}

// Otherwise try to query remote
if out, err := git.exec("ls-remote", "--symref", remote, "HEAD"); err == nil {
r := regexp.MustCompile(`^ref: refs/heads/(.+)\tHEAD`)
matches := r.FindStringSubmatch(out)
if len(matches) == 2 {
return matches[1]
}
logger.Debug().Msgf("failed to parse remote branch name from ls-remote: '%s'", out)
} else {
logger.Debug().Err(err).Msg("failed to get name of default branch remotely")
}

logger.Debug().Msg("failed to get name of default branch")
return ""
}

func (git *Git) exec(command string, args ...string) (string, error) {
Expand Down
27 changes: 26 additions & 1 deletion git/git_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 Terramate GmbH
// SPDX-License-Identifier: MPL-2.0

//go:build linux || darwin
///go:build linux

package git_test

Expand Down Expand Up @@ -447,6 +447,31 @@ func TestGetConfigValue(t *testing.T) {
assert.Error(t, err, "git config: non-existing key")
}

func TestGetRemoteDefaultBranch(t *testing.T) {
const (
remote = "origin"
defaultBranch = "main"
)

repodir := mkOneCommitRepo(t)
g := test.NewGitWrapper(t, repodir, []string{})

remoteDir := test.EmptyRepo(t, true)

assert.NoError(t, g.RemoteAdd(remote, remoteDir))
assert.NoError(t, g.Push(remote, defaultBranch))

name := g.RemoteDefaultBranch(remote)
assert.EqualStrings(t, name, defaultBranch, "default branch with init")

clonedir := t.TempDir()
g = test.NewGitWrapper(t, clonedir, []string{})
assert.NoError(t, g.Clone(remoteDir, clonedir))

name = g.RemoteDefaultBranch(remote)
assert.EqualStrings(t, name, defaultBranch, "default branch with clone")
}

const defaultBranch = "main"

func mkOneCommitRepo(t *testing.T) string {
Expand Down

0 comments on commit b0c146c

Please sign in to comment.