Skip to content

4211 - fix: Setting correct exit code for hcl validate #4290

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 8 additions & 0 deletions cli/commands/hcl/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ func RunValidate(ctx context.Context, opts *options.TerragruntOptions) error {
if err := writeDiagnostics(opts, diags); err != nil {
return err
}

// If there were diagnostics and stackErr is currently nil,
// create a new error to signal overall validation failure.
//
// This also ensures a non-zero exit code is returned by Terragrunt.
if stackErr == nil {
stackErr = errors.Errorf("%d HCL validation error(s) found", len(diags))
}
}

return stackErr
Expand Down
7 changes: 6 additions & 1 deletion docs-starlight/src/components/Flag.astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { slug } = Astro.props;

const flagEntry = await getEntry('flags', slug) as CollectionEntry<'flags'>;
const { Content } = await render(flagEntry);
const { aliases, description, type, env, name } = flagEntry.data;
const { aliases, description, type, env, name, defaultVal } = flagEntry.data;
---

<section id={name}>
Expand All @@ -21,6 +21,11 @@ const { aliases, description, type, env, name } = flagEntry.data;
<div>
<span>Type: </span><Badge text={type} variant="note" style={{ fontWeight: 'bold' }}/>
</div>
{defaultVal && (
<div>
<span>Default: </span><Badge text={defaultVal} variant="tip" style={{ fontWeight: 'bold' }}/>
</div>
)}
{aliases && aliases.length > 0 && (
<>
<p>Aliases:</p>
Expand Down
1 change: 1 addition & 0 deletions docs-starlight/src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const flags = defineCollection({
schema: z.object({
name: z.string(),
description: z.string(),
defaultVal: z.string().optional(),
type: z.string(),
env: z.array(z.string()).optional(),
aliases: z.array(z.string()).optional(),
Expand Down
12 changes: 9 additions & 3 deletions docs-starlight/src/data/flags/queue-excludes-file.mdx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
---
name: queue-excludes-file
description: Path to a file containing Unix-style globs of directories to exclude from the queue of Units to run.
description: Path to a file with a list of directories that need to be excluded when running `run --all` commands.
type: string
defaultVal: .terragrunt-excludes
env:
- TG_QUEUE_EXCLUDES_FILE
---

Specifies a file containing patterns of directories to exclude when running commands with [`--all`](/docs/reference/cli/commands/run#all).
Units in these directories will be excluded during execution of the commands. If a relative path is specified, it should be relative from
[--working-dir](/docs/reference/cli/global-flags#working-directory). This will only exclude the module, not its dependencies.

To learn more about how to use this flag, see the [Stacks](/docs/features/stacks/#the-run---all-command) feature documentation.
This flag has been designed to integrate nicely with the `hcl validate` command, which can return a list of invalid files delimited by newlines when passed the `--show-config-path` flag. To integrate the two, you can run something like the following using bash process substitution:

```bash
terragrunt run --all plan --queue-excludes-file <(terragrunt hcl validate --show-config-path || true)
```
6 changes: 3 additions & 3 deletions docs/_docs/04_reference/02-cli-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -1685,14 +1685,14 @@ When passed in, the `*-all` commands continue processing components even if a de
**Environment Variable Alias**: `TERRAGRUNT_EXCLUDES_FILE` (deprecated: [See migration guide](/docs/migrate/cli-redesign/))<br/>
**Requires an argument**: `--queue-excludes-file /path/to/file`<br/>

Path to a file with a list of directories that need to be excluded when running *-all commands, by default `.terragrunt-excludes`. Modules under these directories will be
Path to a file with a list of directories that need to be excluded when running `run --all` commands, by default `.terragrunt-excludes`. Units in these directories will be
excluded during execution of the commands. If a relative path is specified, it should be relative from
[--working-dir](#working-dir). This will only exclude the module, not its dependencies.

This flag has been designed to integrate nicely with the `hclvalidate` command, which can return a list of invalid files delimited by newlines when passed the `--show-config-path` flag. To integrate the two, you can run something like the following using bash process substitution:
This flag has been designed to integrate nicely with the `hcl validate` command, which can return a list of invalid files delimited by newlines when passed the `--show-config-path` flag. To integrate the two, you can run something like the following using bash process substitution:

```bash
terragrunt run --all plan --queue-excludes-file <(terragrunt hclvalidate --show-config-path)
terragrunt run --all plan --queue-excludes-file <(terragrunt hcl validate --show-config-path || true)
```

### queue-exclude-dir
Expand Down
2 changes: 1 addition & 1 deletion test/integration_deprecated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestDeprecatedHclvalidateCommand_HclvalidateInvalidConfigPath(t *testing.T)
}

stdout, _, err := helpers.RunTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt hclvalidate --terragrunt-working-dir %s --terragrunt-hclvalidate-json --terragrunt-hclvalidate-show-config-path", rootPath))
require.NoError(t, err)
require.Error(t, err)

var actualPaths []string

Expand Down
22 changes: 20 additions & 2 deletions test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ func TestHclvalidateDiagnostic(t *testing.T) {
}

stdout, _, err := helpers.RunTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt hcl validate --working-dir %s --json", rootPath))
require.NoError(t, err)
require.Error(t, err)

var actualDiags diagnostic.Diagnostics

Expand All @@ -728,6 +728,24 @@ func TestHclvalidateDiagnostic(t *testing.T) {
assert.ElementsMatch(t, expectedDiags, actualDiags)
}

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

helpers.CleanupTerraformFolder(t, testFixtureHclvalidate)
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureHclvalidate)
rootPath := util.JoinPath(tmpEnvPath, testFixtureHclvalidate)

// We expect an error because the fixture has HCL validation issues.
// The content of stdout and stderr isn't the primary focus here,
// rather the fact that an error (non-zero exit code) is returned.
_, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt hcl validate --working-dir "+rootPath)
require.Error(t, err, "terragrunt hcl validate should return a non-zero exit code on HCL errors")

// As an additional check, we can verify that the error message indicates HCL validation errors.
// This makes the test more robust.
assert.Contains(t, err.Error(), "HCL validation error(s) found")
}

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

Expand All @@ -741,7 +759,7 @@ func TestHclvalidateInvalidConfigPath(t *testing.T) {
}

stdout, _, err := helpers.RunTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt hcl validate --working-dir %s --json --show-config-path", rootPath))
require.NoError(t, err)
require.Error(t, err)

var actualPaths []string

Expand Down
Loading