Skip to content

Commit 526befb

Browse files
authored
fix: Setting of right exit code in case of detailed-exitcode (#4357)
* Detailed exit code update * Added reset to success error * Added unit test to track exit code
1 parent f247b25 commit 526befb

4 files changed

Lines changed: 54 additions & 6 deletions

File tree

cli/commands/run/run.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ func RunTerraformWithRetry(ctx context.Context, terragruntOptions *options.Terra
485485
return err
486486
} else {
487487
terragruntOptions.Logger.Infof("Encountered an error eligible for retrying. Sleeping %v before retrying.\n", terragruntOptions.RetrySleepInterval)
488+
// Reset the exit code to success so that we can retry the command
489+
if exitCode := tf.DetailedExitCodeFromContext(ctx); exitCode != nil {
490+
exitCode.ResetSuccess()
491+
}
488492
select {
489493
case <-time.After(terragruntOptions.RetrySleepInterval):
490494
// try again

test/integration_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,32 @@ func TestDetailedExitCodeChangesPresentAll(t *testing.T) {
233233
assert.Equal(t, 2, exitCode.Get())
234234
}
235235

236+
func TestDetailedExitCodeChangesUnit(t *testing.T) {
237+
t.Parallel()
238+
239+
testFixturePath := filepath.Join(testFixtureDetailedExitCode, "changes")
240+
241+
helpers.CleanupTerraformFolder(t, testFixturePath)
242+
tmpEnvPath := helpers.CopyEnvironment(t, testFixturePath)
243+
rootPath := util.JoinPath(tmpEnvPath, testFixturePath)
244+
ctx := t.Context()
245+
246+
_, _, err := helpers.RunTerragruntCommandWithOutputWithContext(t, ctx, "terragrunt run --all --log-level trace --non-interactive --working-dir "+rootPath+" -- apply")
247+
require.NoError(t, err)
248+
249+
// delete example.txt from rootPath/app1 to have changes in one unit
250+
err = os.Remove(filepath.Join(rootPath, "app1", "example.txt"))
251+
require.NoError(t, err)
252+
253+
// check that the exit code is 2 when there are changes in one unit
254+
var exitCode tf.DetailedExitCode
255+
ctx = tf.ContextWithDetailedExitCode(ctx, &exitCode)
256+
257+
_, _, err = helpers.RunTerragruntCommandWithOutputWithContext(t, ctx, "terragrunt run --all --log-level trace --non-interactive --working-dir "+rootPath+" -- plan -detailed-exitcode")
258+
require.NoError(t, err)
259+
assert.Equal(t, 2, exitCode.Get())
260+
}
261+
236262
func TestDetailedExitCodeFailOnFirstRun(t *testing.T) {
237263
t.Parallel()
238264

tf/detailed_exitcode.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,49 @@ import (
44
"sync"
55
)
66

7+
const (
8+
DetailedExitCodeSuccess = 0
9+
DetailedExitCodeError = 1
10+
)
11+
712
// DetailedExitCode is the TF detailed exit code. https://opentofu.org/docs/cli/commands/plan/
813
type DetailedExitCode struct {
914
Code int
1015
mu sync.RWMutex
1116
}
1217

13-
// Get returns exit code.
18+
// Get return exit code.
1419
func (coder *DetailedExitCode) Get() int {
1520
coder.mu.RLock()
1621
defer coder.mu.RUnlock()
1722

1823
return coder.Code
1924
}
2025

26+
// ResetSuccess resets the exit code to success (0).
27+
func (coder *DetailedExitCode) ResetSuccess() {
28+
coder.mu.Lock()
29+
defer coder.mu.Unlock()
30+
31+
coder.Code = DetailedExitCodeSuccess
32+
}
33+
2134
// Set updates the exit code following OpenTofu's exit code convention:
2235
// - 0 = Success
2336
// - 1 = Error
2437
// - 2 = Success with changes pending
38+
// The method only updates if:
39+
// - The current code is not 1 (error state)
40+
// - The new code is greater than current OR equals 1
2541
func (coder *DetailedExitCode) Set(newCode int) {
2642
coder.mu.Lock()
2743
defer coder.mu.Unlock()
2844

29-
coder.Code = newCode
45+
if coder.Code == DetailedExitCodeError {
46+
return
47+
}
48+
49+
if coder.Code < newCode || newCode == DetailedExitCodeError {
50+
coder.Code = newCode
51+
}
3052
}

tf/run_cmd.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ func RunCommandWithOutput(ctx context.Context, opts *options.TerragruntOptions,
7474
if code != 1 {
7575
return output, nil
7676
}
77-
} else {
78-
if exitCode := DetailedExitCodeFromContext(ctx); exitCode != nil {
79-
exitCode.Set(0)
80-
}
8177
}
8278

8379
return output, err

0 commit comments

Comments
 (0)