Skip to content

Commit 4a36f3f

Browse files
authored
fix #2072 make sure the generated code is formatted before writing it to a file. (#3917)
1 parent be02d45 commit 4a36f3f

File tree

3 files changed

+101
-3
lines changed

3 files changed

+101
-3
lines changed

codegen/generate.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111

1212
"github.com/hashicorp/hcl/v2"
1313
"github.com/hashicorp/hcl/v2/hclsimple"
14-
1514
"github.com/hashicorp/hcl/v2/hclwrite"
1615
ctyjson "github.com/zclconf/go-cty/cty/json"
1716

@@ -87,6 +86,7 @@ type GenerateConfig struct {
8786
Contents string `cty:"contents"`
8887
DisableSignature bool `cty:"disable_signature"`
8988
Disable bool `cty:"disable"`
89+
HclFmt *bool `cty:"hcl_fmt"`
9090
}
9191

9292
// WriteToFile will generate a new file at the given target path with the given contents. If a file already exists at
@@ -135,10 +135,30 @@ func WriteToFile(terragruntOptions *options.TerragruntOptions, basePath string,
135135
prefix = fmt.Sprintf("%s%s\n", config.CommentPrefix, TerragruntGeneratedSignature)
136136
}
137137

138-
contentsToWrite := fmt.Sprintf("%s%s", prefix, config.Contents)
138+
fmtGeneratedCode := false
139+
140+
if config.HclFmt == nil {
141+
var fmtExt = map[string]struct{}{
142+
".hcl": {},
143+
".tf": {},
144+
".tofu": {},
145+
}
146+
147+
ext := filepath.Ext(config.Path)
148+
if _, ok := fmtExt[ext]; ok {
149+
fmtGeneratedCode = true
150+
}
151+
} else {
152+
fmtGeneratedCode = *config.HclFmt
153+
}
154+
155+
contentsToWrite := []byte(fmt.Sprintf("%s%s", prefix, config.Contents))
156+
if fmtGeneratedCode {
157+
contentsToWrite = hclwrite.Format(contentsToWrite)
158+
}
139159

140160
const ownerWriteGlobalReadPerms = 0644
141-
if err := os.WriteFile(targetPath, []byte(contentsToWrite), ownerWriteGlobalReadPerms); err != nil {
161+
if err := os.WriteFile(targetPath, contentsToWrite, ownerWriteGlobalReadPerms); err != nil {
142162
return errors.New(err)
143163
}
144164

codegen/generate_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package codegen_test
33
import (
44
"bytes"
55
"fmt"
6+
"os"
67
"testing"
78

89
"github.com/gruntwork-io/terragrunt/codegen"
@@ -144,6 +145,81 @@ func TestRemoteStateConfigToTerraformCode(t *testing.T) {
144145
}
145146
}
146147

148+
func TestFmtGeneratedFile(t *testing.T) {
149+
t.Parallel()
150+
151+
testDir := t.TempDir()
152+
153+
bTrue := true
154+
bFalse := false
155+
156+
tc := []struct {
157+
name string
158+
disabled bool
159+
fmt *bool
160+
path string
161+
contents string
162+
expected string
163+
ifExists codegen.GenerateConfigExists
164+
}{
165+
{
166+
name: "fmt-simple-hcl-file",
167+
fmt: &bTrue,
168+
path: fmt.Sprintf("%s/%s", testDir, "fmt_simple.hcl"),
169+
contents: "variable \"msg\"{\ntype=string\n default=\"hello\"\n}\n",
170+
expected: "variable \"msg\" {\n type = string\n default = \"hello\"\n}\n",
171+
ifExists: codegen.ExistsError,
172+
},
173+
{
174+
name: "fmt-hcl-file-by-default",
175+
path: fmt.Sprintf("%s/%s", testDir, "fmt_hcl_file_by_default.hcl"),
176+
contents: "variable \"msg\"{\ntype=string\n default=\"hello\"\n}\n",
177+
expected: "variable \"msg\" {\n type = string\n default = \"hello\"\n}\n",
178+
ifExists: codegen.ExistsError,
179+
},
180+
{
181+
name: "ignore-hcl-fmt",
182+
fmt: &bFalse,
183+
path: fmt.Sprintf("%s/%s", testDir, "ignore_hcl_fmt.hcl"),
184+
contents: "variable \"msg\"{\ntype=string\n default=\"hello\"\n}\n",
185+
expected: "variable \"msg\"{\ntype=string\n default=\"hello\"\n}\n",
186+
ifExists: codegen.ExistsError,
187+
},
188+
}
189+
190+
for _, tt := range tc {
191+
tt := tt
192+
193+
t.Run(tt.name, func(t *testing.T) {
194+
t.Parallel()
195+
196+
config := codegen.GenerateConfig{
197+
Path: tt.path,
198+
IfExists: tt.ifExists,
199+
CommentPrefix: "",
200+
DisableSignature: true,
201+
Contents: tt.contents,
202+
Disable: tt.disabled,
203+
HclFmt: tt.fmt,
204+
}
205+
206+
opts, err := options.NewTerragruntOptionsForTest("mock-path-for-test.hcl")
207+
require.NoError(t, err)
208+
assert.NotNil(t, opts)
209+
210+
err = codegen.WriteToFile(opts, "", config)
211+
require.NoError(t, err)
212+
213+
assert.True(t, util.FileExists(tt.path))
214+
215+
fileContent, err := os.ReadFile(tt.path)
216+
require.NoError(t, err)
217+
218+
assert.Equal(t, tt.expected, string(fileContent))
219+
})
220+
}
221+
}
222+
147223
func TestGenerateDisabling(t *testing.T) {
148224
t.Parallel()
149225

docs/_docs/04_reference/04-config-blocks-and-attributes.md

+2
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,8 @@ The `generate` block supports the following arguments:
13011301
`false`. Optional.
13021302
- `contents` (attribute): The contents of the generated file.
13031303
- `disable` (attribute): Disables this generate block.
1304+
- `hcl_fmt` (attribute): Unless disabled (set to `false`), files with `.hcl`, `.tf`, and `.tofu` extensions will be formatted before being written to disk.
1305+
If explicitly set to `true`, formatting will be applied to the generated files.
13041306

13051307
Example:
13061308

0 commit comments

Comments
 (0)