Skip to content

Commit 89af952

Browse files
authored
Enable per-runner parallelism (#1944)
1 parent 3274417 commit 89af952

File tree

3 files changed

+33
-15
lines changed

3 files changed

+33
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ Application Options:
134134
--color Enable colorized output
135135
--no-color Disable colorized output
136136
--fix Fix issues automatically
137+
--no-parallel-runners Disable per-runner parallelism
137138
138139
Help Options:
139140
-h, --help Show this help message

cmd/inspect.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,10 @@ func (cli *CLI) inspectModule(opts Options, dir string, filterFiles []string) (t
128128
}
129129

130130
// Setup runners
131-
runners, err := cli.setupRunners(opts, dir)
131+
rootRunner, moduleRunners, err := cli.setupRunners(opts, dir)
132132
if err != nil {
133133
return issues, changes, err
134134
}
135-
rootRunner := runners[len(runners)-1]
136135

137136
// Launch plugin processes
138137
rulesetPlugin, err := launchPlugins(cli.config, opts.Fix)
@@ -176,16 +175,33 @@ By setting TFLINT_LOG=trace, you can confirm the changes made by the autofix and
176175
}
177176

178177
for name, ruleset := range rulesetPlugin.RuleSets {
179-
for _, runner := range runners {
180-
err = ruleset.Check(plugin.NewGRPCServer(runner, rootRunner, cli.loader.Files(), sdkVersions[name]))
178+
if err := ruleset.Check(plugin.NewGRPCServer(rootRunner, rootRunner, cli.loader.Files(), sdkVersions[name])); err != nil {
179+
return issues, changes, fmt.Errorf("Failed to check ruleset; %w", err)
180+
}
181+
// Run checks for module calls are performed in parallel.
182+
// The rootRunner is shared between goroutines but read-only, so this is goroutine-safe.
183+
// Note that checks against the rootRunner are not parallelized, as autofix may cause the module to be rebuilt.
184+
ch := make(chan error, len(moduleRunners))
185+
for _, runner := range moduleRunners {
186+
if opts.NoParallelRunners {
187+
ch <- ruleset.Check(plugin.NewGRPCServer(runner, rootRunner, cli.loader.Files(), sdkVersions[name]))
188+
} else {
189+
go func(runner *tflint.Runner) {
190+
ch <- ruleset.Check(plugin.NewGRPCServer(runner, rootRunner, cli.loader.Files(), sdkVersions[name]))
191+
}(runner)
192+
}
193+
}
194+
for i := 0; i < len(moduleRunners); i++ {
195+
err = <-ch
181196
if err != nil {
182197
return issues, changes, fmt.Errorf("Failed to check ruleset; %w", err)
183198
}
184199
}
200+
close(ch)
185201
}
186202

187203
changesInAttempt := map[string][]byte{}
188-
for _, runner := range runners {
204+
for _, runner := range append(moduleRunners, rootRunner) {
189205
for _, issue := range runner.LookupIssues(filterFiles...) {
190206
// On the second attempt, only fixable issues are appended to avoid duplicates.
191207
if loop == 1 || issue.Fixable {
@@ -214,15 +230,15 @@ By setting TFLINT_LOG=trace, you can confirm the changes made by the autofix and
214230
return issues, changes, nil
215231
}
216232

217-
func (cli *CLI) setupRunners(opts Options, dir string) ([]*tflint.Runner, error) {
233+
func (cli *CLI) setupRunners(opts Options, dir string) (*tflint.Runner, []*tflint.Runner, error) {
218234
configs, diags := cli.loader.LoadConfig(dir, cli.config.CallModuleType)
219235
if diags.HasErrors() {
220-
return []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
236+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
221237
}
222238

223239
files, diags := cli.loader.LoadConfigDirFiles(dir)
224240
if diags.HasErrors() {
225-
return []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
241+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
226242
}
227243
annotations := map[string]tflint.Annotations{}
228244
for path, file := range files {
@@ -234,30 +250,30 @@ func (cli *CLI) setupRunners(opts Options, dir string) ([]*tflint.Runner, error)
234250
annotations[path] = ants
235251
}
236252
if diags.HasErrors() {
237-
return []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
253+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to load configurations; %w", diags)
238254
}
239255

240256
variables, diags := cli.loader.LoadValuesFiles(dir, cli.config.Varfiles...)
241257
if diags.HasErrors() {
242-
return []*tflint.Runner{}, fmt.Errorf("Failed to load values files; %w", diags)
258+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to load values files; %w", diags)
243259
}
244260
cliVars, diags := terraform.ParseVariableValues(cli.config.Variables, configs.Module.Variables)
245261
if diags.HasErrors() {
246-
return []*tflint.Runner{}, fmt.Errorf("Failed to parse variables; %w", diags)
262+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to parse variables; %w", diags)
247263
}
248264
variables = append(variables, cliVars)
249265

250266
runner, err := tflint.NewRunner(cli.originalWorkingDir, cli.config, annotations, configs, variables...)
251267
if err != nil {
252-
return []*tflint.Runner{}, fmt.Errorf("Failed to initialize a runner; %w", err)
268+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to initialize a runner; %w", err)
253269
}
254270

255-
runners, err := tflint.NewModuleRunners(runner)
271+
moduleRunners, err := tflint.NewModuleRunners(runner)
256272
if err != nil {
257-
return []*tflint.Runner{}, fmt.Errorf("Failed to prepare rule checking; %w", err)
273+
return nil, []*tflint.Runner{}, fmt.Errorf("Failed to prepare rule checking; %w", err)
258274
}
259275

260-
return append(runners, runner), nil
276+
return runner, moduleRunners, nil
261277
}
262278

263279
func launchPlugins(config *tflint.Config, fix bool) (*plugin.Plugin, error) {

cmd/option.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Options struct {
3333
Color bool `long:"color" description:"Enable colorized output"`
3434
NoColor bool `long:"no-color" description:"Disable colorized output"`
3535
Fix bool `long:"fix" description:"Fix issues automatically"`
36+
NoParallelRunners bool `long:"no-parallel-runners" description:"Disable per-runner parallelism"`
3637
ActAsBundledPlugin bool `long:"act-as-bundled-plugin" hidden:"true"`
3738
}
3839

0 commit comments

Comments
 (0)