diff --git a/bake/hcl.go b/bake/hcl.go index 9f99fac7ea6..6f19390efae 100644 --- a/bake/hcl.go +++ b/bake/hcl.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/hcl/v2/hclsimple" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/hcl/v2/json" + "github.com/moby/buildkit/solver/errdefs" + "github.com/moby/buildkit/solver/pb" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function/stdlib" @@ -103,7 +105,11 @@ type staticConfig struct { Remain hcl.Body `hcl:",remain"` } -func ParseHCL(dt []byte, fn string) (*Config, error) { +func ParseHCL(dt []byte, fn string) (_ *Config, err error) { + defer func() { + err = formatHCLError(dt, err) + }() + // Decode user defined functions, first parsing as hcl and falling back to // json, returning errors based on the file suffix. file, hcldiags := hclsyntax.ParseConfig(dt, fn, hcl.Pos{Line: 1, Column: 1}) @@ -172,3 +178,35 @@ func ParseHCL(dt []byte, fn string) (*Config, error) { } return &c, nil } + +func formatHCLError(dt []byte, err error) error { + if err == nil { + return nil + } + diags, ok := err.(hcl.Diagnostics) + if !ok { + return err + } + for _, d := range diags { + if d.Severity != hcl.DiagError { + continue + } + src := errdefs.Source{ + Info: &pb.SourceInfo{ + Filename: d.Subject.Filename, + Data: dt, + }, + Ranges: []*pb.Range{toErrRange(d.Subject)}, + } + err = errdefs.WithSource(err, src) + break + } + return err +} + +func toErrRange(in *hcl.Range) *pb.Range { + return &pb.Range{ + Start: pb.Position{Line: int32(in.Start.Line), Character: int32(in.Start.Column)}, + End: pb.Position{Line: int32(in.End.Line), Character: int32(in.End.Column)}, + } +}