From 548893bbee4e5a49bbbb07a81d19b2e2641fa421 Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Wed, 7 Feb 2024 11:22:26 -0500 Subject: [PATCH] build: don't suggest lack of HCP support on fail When running a build with HCP Packer enabled, Packer attempts to push the build status to HCP. If the build fails, we update the status to BUILD_FAILED, and that's the end of it. If however the build succeeds, Packer attempts to get the HCP artifact from the builder, which will only succeed if the builder supports it. Otherwise, we'll get either nil, or an artifact type that is not compatible with what is expected for HCP support. When either of those happens, we warn that the builder may not support HCP Packer at all, so users are aware of the problem. However, when the error was introduced, it only looked at the fact that an error was produced, independently of the type of error. This caused legitimate errors while building to be reported as potential incompatibility between the builder and HCP, which was confusing to users. This commit changes this by introducing a new error type, only produced when the artifact either is nil, or failed to be deserialised into a HCP artifact, which lets us produce the incompatibility warning with more accuracy. --- command/build.go | 43 ++++++++++++++------------- internal/hcp/registry/types.bucket.go | 17 +++++++++-- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/command/build.go b/command/build.go index c0a4d8c01..60ede4168 100644 --- a/command/build.go +++ b/command/build.go @@ -207,7 +207,6 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int }{m: make(map[string]error)} limitParallel := semaphore.NewWeighted(cla.ParallelBuilds) - var hasPossibleIncompatibleHCPIntegration bool for i := range builds { if err := buildCtx.Err(); err != nil { log.Println("Interrupted, not going to start any more builds.") @@ -270,16 +269,29 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int runArtifacts, err) if hcperr != nil { - writeDiags(c.Ui, nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: fmt.Sprintf( - "publishing build metadata to HCP Packer for %q failed", - name), - Severity: hcl.DiagError, - Detail: hcperr.Error(), - }, - }) - hasPossibleIncompatibleHCPIntegration = true + if _, ok := hcperr.(*registry.NotAHCPArtifactError); ok { + writeDiags(c.Ui, nil, hcl.Diagnostics{ + &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("The %q builder produced an artifact that cannot be pushed to HCP Packer", b.Name()), + Detail: fmt.Sprintf( + `%s +Check that you are using an HCP Ready integration before trying again: +%s`, + hcperr, hcpReadyIntegrationURL), + }, + }) + } else { + writeDiags(c.Ui, nil, hcl.Diagnostics{ + &hcl.Diagnostic{ + Summary: fmt.Sprintf( + "publishing build metadata to HCP Packer for %q failed", + name), + Severity: hcl.DiagError, + Detail: hcperr.Error(), + }, + }) + } } if err != nil { @@ -391,15 +403,6 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int c.Ui.Say("\n==> Builds finished but no artifacts were created.") } - if hasPossibleIncompatibleHCPIntegration { - msg := fmt.Sprintf(` -It looks like one or more plugins in your build may be incompatible with HCP Packer. -Check that you are using an HCP Ready integration before trying again: -%s`, hcpReadyIntegrationURL) - - c.Ui.Error(msg) - } - if len(errs.m) > 0 { // If any errors occurred, exit with a non-zero exit status ret = 1 diff --git a/internal/hcp/registry/types.bucket.go b/internal/hcp/registry/types.bucket.go index 00b40e345..6b92e6ce1 100644 --- a/internal/hcp/registry/types.bucket.go +++ b/internal/hcp/registry/types.bucket.go @@ -595,6 +595,10 @@ func (bucket *Bucket) startBuild(ctx context.Context, buildName string) error { return nil } +type NotAHCPArtifactError struct { + error +} + func (bucket *Bucket) completeBuild( ctx context.Context, buildName string, @@ -638,12 +642,19 @@ func (bucket *Bucket) completeBuild( } state := art.State(packerSDKRegistry.ArtifactStateURI) + if state == nil { + return packerSDKArtifacts, &NotAHCPArtifactError{ + fmt.Errorf("The HCP artifact returned by the builder is nil, this is likely because the builder does not support HCP Packer."), + } + } + err = decoder.Decode(state) if err != nil { - return packerSDKArtifacts, fmt.Errorf( - "failed to obtain HCP Packer compliant artifact: %w", - err) + return packerSDKArtifacts, &NotAHCPArtifactError{ + fmt.Errorf("Failed to obtain HCP Packer compliant artifact: %s", err), + } } + log.Printf("[TRACE] updating artifacts for build %q", buildName) err = bucket.UpdateArtifactForBuild(buildName, sdkImages...)