diff --git a/command/validate_test.go b/command/validate_test.go index 3a2c6b20a..d4188c497 100644 --- a/command/validate_test.go +++ b/command/validate_test.go @@ -1,6 +1,7 @@ package command import ( + "fmt" "path/filepath" "testing" @@ -341,3 +342,42 @@ func TestValidateCommand_VarFilesDisableWarnOnUndeclared(t *testing.T) { }) } } + +func TestValidateCommand_ShowLineNumForMissing(t *testing.T) { + tt := []struct { + path string + exitCode int + extraArgs []string + }{ + {path: filepath.Join(testFixture("validate-invalid"), "missing_build_block.pkr.hcl"), exitCode: 1}, + } + + for _, tc := range tt { + t.Run(tc.path, func(t *testing.T) { + c := &ValidateCommand{ + Meta: TestMetaFile(t), + } + tc := tc + args := tc.extraArgs + args = append(args, tc.path) + if code := c.Run(args); code != tc.exitCode { + fatalCommand(t, c.Meta) + } + + stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta) + expected := fmt.Sprintf(`Error: Unknown source file.cho + + on %s line 6: + (source code not available) + +Known: [file.chocolate] + + +`, tc.path) + if diff := cmp.Diff(expected, stderr); diff != "" { + t.Errorf("Unexpected output: %s", diff) + } + t.Log(stdout) + }) + } +} diff --git a/hcl2template/types.build.go b/hcl2template/types.build.go index 3bb54b20c..73ae957d3 100644 --- a/hcl2template/types.build.go +++ b/hcl2template/types.build.go @@ -87,22 +87,26 @@ type Builds []*BuildBlock // decodeBuildConfig is called when a 'build' block has been detected. It will // load the references to the contents of the build block. func (p *Parser) decodeBuildConfig(block *hcl.Block, cfg *PackerConfig) (*BuildBlock, hcl.Diagnostics) { - build := &BuildBlock{} - body := block.Body - var b struct { Name string `hcl:"name,optional"` Description string `hcl:"description,optional"` FromSources []string `hcl:"sources,optional"` Config hcl.Body `hcl:",remain"` } + + body := block.Body diags := gohcl.DecodeBody(body, cfg.EvalContext(LocalContext, nil), &b) if diags.HasErrors() { return nil, diags } + build := &BuildBlock{ + HCL2Ref: newHCL2Ref(block, b.Config), + } + build.Name = b.Name build.Description = b.Description + build.HCL2Ref.DefRange = block.DefRange // Expose build.name during parsing of pps and provisioners ectx := cfg.EvalContext(BuildContext, nil)