Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: git safeguards not using root config.git #234

Merged
merged 4 commits into from
Feb 25, 2022
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
81 changes: 39 additions & 42 deletions cmd/terramate/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import (

const (
ErrOutdatedLocalRev errutil.Error = "outdated local revision"
ErrNoDefaultRemoteConfig errutil.Error = "repository must have a configured origin/main"
ErrInit errutil.Error = "failed to initialize all stacks"
ErrOutdatedGenCodeDetected errutil.Error = "outdated generated code detected"
)
Expand Down Expand Up @@ -148,12 +147,7 @@ type cli struct {
prj project
}

func newCLI(
args []string,
stdin io.Reader,
stdout io.Writer,
stderr io.Writer,
) *cli {
func newCLI(args []string, stdin io.Reader, stdout, stderr io.Writer) *cli {
if len(args) == 0 {
// WHY: avoid default kong error, print help
args = []string{"--help"}
Expand Down Expand Up @@ -307,20 +301,19 @@ func (c *cli) run() {
Logger()

if c.parsedArgs.Changed {
logger.Trace().
Msg("`Changed` flag was set.")
logger.Trace().Msg("`Changed` flag was set.")
i4ki marked this conversation as resolved.
Show resolved Hide resolved

logger.Trace().Msg("Create new git wrapper.")

logger.Trace().
Msg("Create new git wrapper.")
git, err := newGit(c.root(), true)
if err != nil {
log.Fatal().
Err(err).
Msg("creating git wrapper.")
}

logger.Trace().
Msg("Check git default remote.")
logger.Trace().Msg("Check git default remote.")

if err := c.checkDefaultRemote(git); err != nil {
log.Fatal().
Err(err).
Expand Down Expand Up @@ -866,6 +859,10 @@ func (c *cli) runOnStacks() {
func (c *cli) wd() string { return c.prj.wd }
func (c *cli) root() string { return c.prj.root }

func (c *cli) gitcfg() *hcl.GitConfig {
return c.prj.rootcfg.Terramate.RootConfig.Git
}

func (c *cli) log(format string, args ...interface{}) {
fmt.Fprintln(c.stdout, fmt.Sprintf(format, args...))
}
Expand All @@ -880,45 +877,42 @@ func (c *cli) checkDefaultRemote(g *git.Git) error {
Str("stack", c.wd()).
Logger()

logger.Trace().
Msg("Get list of configured git remotes.")
logger.Trace().Msg("Get list of configured git remotes.")

remotes, err := g.Remotes()
if err != nil {
return fmt.Errorf("checking if remote %q exists: %v", defaultRemote, err)
}

var defRemote *git.Remote

gitcfg := c.gitcfg()

logger.Trace().
Msg("Find default git remote.")
for _, remote := range remotes {
if remote.Name == defaultRemote {
if remote.Name == gitcfg.DefaultRemote {
defRemote = &remote
break
}
}

if defRemote == nil {
return fmt.Errorf(
"%w:no default remote %q",
ErrNoDefaultRemoteConfig,
defaultRemote,
return fmt.Errorf("repository must have a configured %q remote",
gitcfg.DefaultRemote,
)
}

logger.Trace().
Msg("Find default git branch.")
logger.Trace().Msg("Find default git branch.")
for _, branch := range defRemote.Branches {
if branch == defaultBranch {
if branch == gitcfg.DefaultBranch {
return nil
}
}

return fmt.Errorf(
"%w:%q has no default branch %q,branches:%v",
ErrNoDefaultRemoteConfig,
defaultRemote,
defaultBranch,
return fmt.Errorf("remote %q has no default branch %q,branches:%v",
gitcfg.DefaultRemote,
gitcfg.DefaultBranch,
defRemote.Branches,
)
}
Expand All @@ -929,8 +923,8 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error {
Str("workingDir", c.wd()).
Logger()

logger.Trace().
Msg("Get current git branch.")
logger.Trace().Msg("Get current git branch.")

branch, err := g.CurrentBranch()
if err != nil {
// ON CI envs we don't have a clean way to get the branch name
Expand All @@ -948,23 +942,26 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error {
return nil
}

if branch != defaultBranch {
gitcfg := c.gitcfg()
if branch != gitcfg.DefaultBranch {
return nil
}

c.logerr("current branch %q is the default branch, checking if it is updated.", branch)
c.logerr("retrieving info from remote branch: %s/%s ...", defaultRemote, defaultBranch)
c.logerr("retrieving info from remote branch: %s/%s ...",
gitcfg.DefaultRemote, gitcfg.DefaultBranch)

logger.Trace().
Msg("Fetch remote reference.")
remoteRef, err := g.FetchRemoteRev(defaultRemote, defaultBranch)
logger.Trace().Msg("Fetch remote reference.")

remoteRef, err := g.FetchRemoteRev(gitcfg.DefaultRemote, gitcfg.DefaultBranch)
if err != nil {
return fmt.Errorf("checking if local branch %q is updated: %v", branch, err)
}
c.logerr("retrieved info from remote branch: %s/%s.", defaultRemote, defaultBranch)

logger.Trace().
Msg("Get local commit ID.")
c.logerr("retrieved info from remote branch: %s/%s.", gitcfg.DefaultRemote, gitcfg.DefaultBranch)

logger.Trace().Msg("Get local commit ID.")

localCommitID, err := g.RevParse(branch)
if err != nil {
return fmt.Errorf("checking if local branch %q is updated: %v", branch, err)
Expand All @@ -976,8 +973,8 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error {
return fmt.Errorf(
"%w: remote %s/%s=%q != local %s=%q",
ErrOutdatedLocalRev,
defaultRemote,
defaultBranch,
gitcfg.DefaultRemote,
gitcfg.DefaultBranch,
remoteRef.ShortCommitID(),
branch,
localRef.ShortCommitID(),
Expand Down Expand Up @@ -1083,8 +1080,8 @@ func lookupProject(wd string) (prj project, found bool, err error) {
Str("workingDir", wd).
Logger()

logger.Trace().
Msg("Create new git wrapper.")
logger.Trace().Msg("Create new git wrapper.")

gw, err := newGit(wd, false)
if err == nil {
logger.Trace().
Expand Down
39 changes: 34 additions & 5 deletions cmd/terramate/e2etests/general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,13 @@ func TestFailsOnChangeDetectionIfCurrentBranchIsMainAndItIsOutdated(t *testing.T

func TestFailsOnChangeDetectionIfRepoDoesntHaveOriginMain(t *testing.T) {
rootdir := t.TempDir()
assertFails := func() {
assertFails := func(stderrRegex string) {
t.Helper()

ts := newCLI(t, rootdir)
wantRes := runExpected{
Status: 1,
StderrRegex: cli.ErrNoDefaultRemoteConfig.Error(),
StderrRegex: stderrRegex,
}

assertRunResult(t, ts.run("stacks", "list", "--changed"), wantRes)
Expand All @@ -332,23 +332,52 @@ func TestFailsOnChangeDetectionIfRepoDoesntHaveOriginMain(t *testing.T) {
git := sandbox.NewGit(t, rootdir)
git.InitLocalRepo()

assertFails()
assertFails("repository must have a configured")

// the main branch only exists after first commit.
path := test.WriteFile(t, git.BaseDir(), "README.md", "# generated by terramate")
git.Add(path)
git.Commit("first commit")

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

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

func TestNoArgsProvidesBasicHelp(t *testing.T) {
cli := newCLI(t, "")
help := cli.run("--help")
assertRunResult(t, cli.run(), runExpected{Stdout: help.Stdout})
}

func TestFailsIfDefaultRemoteDoesntHaveDefaultBranch(t *testing.T) {
s := sandbox.NewWithGitConfig(t, sandbox.GitConfig{
LocalBranchName: "main",
DefaultRemoteName: "origin",
DefaultRemoteBranchName: "default",
})

cli := newCLI(t, s.RootDir())
assertRunResult(t,
cli.run("stacks", "list", "--changed"),
runExpected{
Status: 1,
StderrRegex: "has no default branch ",
},
)

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

assertRun(t, cli.run("stacks", "list", "--changed"))
}