Skip to content

Commit

Permalink
feat: consider untracked/uncommitted in the change detector.
Browse files Browse the repository at this point in the history
Signed-off-by: i4k <[email protected]>
  • Loading branch information
i4ki committed Oct 8, 2024
1 parent 0d777b1 commit fb211bf
Show file tree
Hide file tree
Showing 12 changed files with 786 additions and 52 deletions.
4 changes: 2 additions & 2 deletions benchmarks/changed/changed_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func BenchmarkChangeDetection(b *testing.B) {

b.StartTimer()
for i := 0; i < b.N; i++ {
report, err := manager.ListChanged("origin/main")
report, err := manager.ListChanged(stack.ChangeConfig{BaseRef: "origin/main"})
assert.NoError(b, err)
assert.EqualInts(b, 1, len(report.Stacks))
assert.EqualStrings(b, fmt.Sprintf("/stack-%d", nstacks-1), report.Stacks[0].Stack.Dir.String())
Expand Down Expand Up @@ -91,7 +91,7 @@ func BenchmarkChangeDetectionTFAndTG(b *testing.B) {

b.StartTimer()
for i := 0; i < b.N; i++ {
report, err := manager.ListChanged("origin/main")
report, err := manager.ListChanged(stack.ChangeConfig{BaseRef: "origin/main"})
assert.NoError(b, err)
assert.EqualInts(b, 2, len(report.Stacks))
assert.EqualStrings(b, fmt.Sprintf("/stack-%d", nTfStacks-1), report.Stacks[0].Stack.Dir.String())
Expand Down
62 changes: 61 additions & 1 deletion cmd/terramate/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -150,10 +151,13 @@ type cliSpec struct {
cloudFilterFlags
Target string `help:"Select the deployment target of the filtered stacks."`
RunOrder bool `default:"false" help:"Sort listed stacks by order of execution"`

changeDetectionFlags
} `cmd:"" help:"List stacks."`

Run struct {
cloudFilterFlags
changeDetectionFlags
Target string `help:"Set the deployment target for stacks synchronized to Terramate Cloud."`
FromTarget string `help:"Migrate stacks from given deployment target."`
EnableSharing bool `help:"Enable sharing of stack outputs as stack inputs."`
Expand Down Expand Up @@ -200,6 +204,7 @@ type cliSpec struct {
} `cmd:"" help:"Show detailed information about a script"`
Run struct {
cloudFilterFlags
changeDetectionFlags
Target string `help:"Set the deployment target for stacks synchronized to Terramate Cloud."`
FromTarget string `help:"Migrate stacks from given deployment target."`
NoRecursive bool `default:"false" help:"Do not recurse into nested child stacks."`
Expand Down Expand Up @@ -253,6 +258,7 @@ type cliSpec struct {
IgnoreChange bool `default:"false" help:"Trigger stacks to be ignored by change detection"`
Reason string `default:"" name:"reason" help:"Set a reason for triggering the stack."`
cloudFilterFlags
changeDetectionFlags
} `cmd:"" help:"Mark a stack as changed so it will be triggered in Change Detection."`

RunGraph struct {
Expand All @@ -262,6 +268,7 @@ type cliSpec struct {

RunOrder struct {
Basedir string `arg:"" optional:"true" help:"Base directory to search stacks (DEPRECATED)"`
changeDetectionFlags
} `hidden:"" cmd:"" help:"Show the topological ordering of the stacks (DEPRECATED)"`

Vendor struct {
Expand Down Expand Up @@ -334,6 +341,11 @@ type cloudFilterFlags struct {
DriftStatus string `help:"Filter by Terramate Cloud drift status of the stack"`
}

type changeDetectionFlags struct {
EnableChangeDetection []string `help:"Enable specific change detection modes" enum:"git-untracked,git-uncommitted"`
DisableChangeDetection []string `help:"Disable specific change detection modes" enum:"git-untracked,git-uncommitted"`
}

// Exec will execute terramate with the provided flags defined on args.
// Only flags should be on the args slice.
//
Expand Down Expand Up @@ -380,6 +392,13 @@ type cli struct {
checkpointResults chan *checkpoint.CheckResponse

tags filter.TagClause

changeDetection changeDetection
}

type changeDetection struct {
untracked *bool
uncommitted *bool
}

func newCLI(version string, args []string, stdin io.Reader, stdout, stderr io.Writer) *cli {
Expand Down Expand Up @@ -662,20 +681,24 @@ func (c *cli) run() {
c.scanCreate()
case "list":
c.setupGit()
c.setupChangeDetection(c.parsedArgs.List.EnableChangeDetection, c.parsedArgs.List.DisableChangeDetection)
c.printStacks()
case "run":
fatal("no command specified")
case "run <cmd>":
c.setupGit()
c.setupChangeDetection(c.parsedArgs.Run.EnableChangeDetection, c.parsedArgs.Run.DisableChangeDetection)
c.setupSafeguards(c.parsedArgs.Run.runSafeguardsCliSpec)
c.runOnStacks()
case "generate":
c.generate()
case "experimental clone <srcdir> <destdir>":
c.cloneStack()
case "experimental trigger":
c.setupChangeDetection(c.parsedArgs.Experimental.Trigger.EnableChangeDetection, c.parsedArgs.Experimental.Trigger.DisableChangeDetection)
c.triggerStackByFilter()
case "experimental trigger <stack>":
c.setupChangeDetection(c.parsedArgs.Experimental.Trigger.EnableChangeDetection, c.parsedArgs.Experimental.Trigger.DisableChangeDetection)
c.triggerStack(c.parsedArgs.Experimental.Trigger.Stack)
case "experimental vendor download <source> <ref>":
c.vendorDownload()
Expand All @@ -693,6 +716,7 @@ func (c *cli) run() {
c.generateGraph()
case "experimental run-order":
c.setupGit()
c.setupChangeDetection(c.parsedArgs.Experimental.RunOrder.EnableChangeDetection, c.parsedArgs.Experimental.RunOrder.DisableChangeDetection)
c.printRunOrder(false)
case "debug show runtime-env":
c.setupGit()
Expand Down Expand Up @@ -735,6 +759,7 @@ func (c *cli) run() {
case "script run <cmds>":
c.checkScriptEnabled()
c.setupGit()
c.setupChangeDetection(c.parsedArgs.Script.Run.EnableChangeDetection, c.parsedArgs.Script.Run.DisableChangeDetection)
c.setupSafeguards(c.parsedArgs.Script.Run.runSafeguardsCliSpec)
c.runScript()
default:
Expand Down Expand Up @@ -1228,6 +1253,37 @@ func (c *cli) gitSafeguardDefaultBranchIsReachable() {
}
}

func (c *cli) checkChangeDetectionFlagConflicts(enable []string, disable []string) {
for _, enableOpt := range enable {
if slices.Contains(disable, enableOpt) {
fatal(errors.E("conflicting option %s in --{enable,disable}-change-detection flags", enableOpt))
}
}
}

func (c *cli) setupChangeDetection(enable []string, disable []string) {
c.checkChangeDetectionFlagConflicts(enable, disable)

on := true
off := false

if slices.Contains(enable, "git-untracked") {
c.changeDetection.untracked = &on
}

if slices.Contains(enable, "git-uncommitted") {
c.changeDetection.uncommitted = &on
}

if slices.Contains(disable, "git-untracked") {
c.changeDetection.untracked = &off
}

if slices.Contains(disable, "git-uncommitted") {
c.changeDetection.uncommitted = &off
}
}

func (c *cli) listStacks(isChanged bool, target string, stackFilters cloud.StatusFilters) (*stack.Report, error) {
var (
err error
Expand All @@ -1237,7 +1293,11 @@ func (c *cli) listStacks(isChanged bool, target string, stackFilters cloud.Statu
mgr := c.stackManager()

if isChanged {
report, err = mgr.ListChanged(c.baseRef())
report, err = mgr.ListChanged(stack.ChangeConfig{
BaseRef: c.baseRef(),
UntrackedChanges: c.changeDetection.untracked,
UncommittedChanges: c.changeDetection.uncommitted,
})
} else {
report, err = mgr.List(true)
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/terramate/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,11 @@ func (c *cli) getAffectedStacks() []stack.Entry {
var report *stack.Report
var err error
if c.parsedArgs.Changed {
report, err = mgr.ListChanged(c.baseRef())
report, err = mgr.ListChanged(stack.ChangeConfig{
BaseRef: c.baseRef(),
UntrackedChanges: c.changeDetection.untracked,
UncommittedChanges: c.changeDetection.uncommitted,
})
if err != nil {
fatalWithDetailf(err, "listing changed stacks")
}
Expand Down
11 changes: 11 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,17 @@ func (root *Root) TerragruntEnabledOption() hcl.TerragruntChangeDetectionEnabled
return hcl.TerragruntAutoOption // "auto" is the default.
}

// ChangeDetectionGitConfig returns the `terramate.config.change_detection.git` object config.
func (root *Root) ChangeDetectionGitConfig() (*hcl.GitChangeDetectionConfig, bool) {
if root.tree.Node.Terramate != nil &&
root.tree.Node.Terramate.Config != nil &&
root.tree.Node.Terramate.Config.ChangeDetection != nil &&
root.tree.Node.Terramate.Config.ChangeDetection.Git != nil {
return root.tree.Node.Terramate.Config.ChangeDetection.Git, true
}
return nil, false
}

// HasTerragruntStacks returns true if the stack loading has detected Terragrunt files.
func (root *Root) HasTerragruntStacks() bool {
b := root.hasTerragruntStacks
Expand Down
Loading

0 comments on commit fb211bf

Please sign in to comment.