From 0e354e503b5e190f565665c52dc803f7c9467392 Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Fri, 21 Nov 2025 12:43:46 +0530 Subject: [PATCH] FEAT: Adds support for updating HCP Packer registry channels Enables specifying channels in the build configuration to automatically update existing HCP Packer registry channels to point to the new build version upon completion. Improves workflow automation and reduces manual channel management for users. --- .../types.build.hcp_packer_registry.go | 4 +++ internal/hcp/api/service_build.go | 20 ++++++++++++ internal/hcp/registry/types.bucket.go | 32 +++++++++++++++++++ .../blocks/build/hcp_packer_registry.mdx | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/hcl2template/types.build.hcp_packer_registry.go b/hcl2template/types.build.hcp_packer_registry.go index 640359aa1..2b7c1f71e 100644 --- a/hcl2template/types.build.hcp_packer_registry.go +++ b/hcl2template/types.build.hcp_packer_registry.go @@ -20,6 +20,8 @@ type HCPPackerRegistryBlock struct { BucketLabels map[string]string // Build labels BuildLabels map[string]string + // Channels + Channels []string HCL2Ref } @@ -37,6 +39,7 @@ func (p *Parser) decodeHCPRegistry(block *hcl.Block, cfg *PackerConfig) (*HCPPac Labels map[string]string `hcl:"labels,optional"` BucketLabels map[string]string `hcl:"bucket_labels,optional"` BuildLabels map[string]string `hcl:"build_labels,optional"` + Channels []string `hcl:"channels,optional"` Config hcl.Body `hcl:",remain"` } ectx := cfg.EvalContext(BuildContext, nil) @@ -69,6 +72,7 @@ func (p *Parser) decodeHCPRegistry(block *hcl.Block, cfg *PackerConfig) (*HCPPac par.Slug = b.Slug par.Description = b.Description + par.Channels = b.Channels if len(b.Labels) > 0 && len(b.BucketLabels) > 0 { diags = append(diags, &hcl.Diagnostic{ diff --git a/internal/hcp/api/service_build.go b/internal/hcp/api/service_build.go index a857192c3..51a0f37f6 100644 --- a/internal/hcp/api/service_build.go +++ b/internal/hcp/api/service_build.go @@ -118,3 +118,23 @@ func (c *Client) UploadSbom( _, err := c.Packer.PackerServiceUploadSbom(params, nil) return err } + +func (c *Client) UpdateChannel( + ctx context.Context, + bucketName, channelName string, + body *hcpPackerModels.HashicorpCloudPacker20230101UpdateChannelBody, +) (*hcpPackerAPI.PackerServiceUpdateChannelOK, error) { + + params := hcpPackerAPI.NewPackerServiceUpdateChannelParamsWithContext(ctx) + params.LocationOrganizationID = c.OrganizationID + params.LocationProjectID = c.ProjectID + params.BucketName = bucketName + params.ChannelName = channelName + params.Body = body + resp, err := c.Packer.PackerServiceUpdateChannel(params, nil) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/internal/hcp/registry/types.bucket.go b/internal/hcp/registry/types.bucket.go index 264852492..c81f03412 100644 --- a/internal/hcp/registry/types.bucket.go +++ b/internal/hcp/registry/types.bucket.go @@ -36,6 +36,7 @@ type Bucket struct { Destination string BucketLabels map[string]string BuildLabels map[string]string + Channels []string SourceExternalIdentifierToParentVersions map[string]ParentVersion RunningBuilds map[string]chan struct{} Version *Version @@ -94,6 +95,7 @@ func (bucket *Bucket) ReadFromHCPPackerRegistryBlock(registryBlock *hcl2template bucket.Description = registryBlock.Description bucket.BucketLabels = registryBlock.BucketLabels bucket.BuildLabels = registryBlock.BuildLabels + bucket.Channels = registryBlock.Channels // If there's already a Name this was set from env variable. // In Packer, env variable overrides config values so we keep it that way for consistency. if bucket.Name == "" && registryBlock.Slug != "" { @@ -244,6 +246,30 @@ func (bucket *Bucket) uploadSbom(ctx context.Context, buildName string, sbom pac return bucket.client.UploadSbom(ctx, bucket.Name, bucket.Version.Fingerprint, buildToUpdate.ID, sbom) } +func (bucket *Bucket) updateChannels(ctx context.Context) error { + if len(bucket.Channels) == 0 { + return nil + } + + log.Printf("[INFO] Updating %d channel(s) to point to version %s", len(bucket.Channels), bucket.Version.ID) + + body := &hcpPackerModels.HashicorpCloudPacker20230101UpdateChannelBody{ + VersionFingerprint: bucket.Version.Fingerprint, + UpdateMask: "versionFingerprint", + } + + for _, channel := range bucket.Channels { + log.Printf("[INFO] Updating channel %s to version %s", channel, bucket.Version.ID) + _, err := bucket.client.UpdateChannel(ctx, bucket.Name, channel, body) + if err != nil { + log.Printf("[ERROR] Failed to update channel %s: %s", channel, err) + return fmt.Errorf("failed to update channel %s: %w", channel, err) + } + } + + return nil +} + // markBuildComplete should be called to set a build on the HCP Packer registry to DONE. // Upon a successful call markBuildComplete will publish all artifacts created by the named build, // and set the build to done. A build with no artifacts can not be set to DONE. @@ -726,6 +752,12 @@ func (bucket *Bucket) doCompleteBuild( parErr) } + // Update channels after build is marked complete + channelErr := bucket.updateChannels(ctx) + if channelErr != nil { + log.Printf("[ERROR] Failed to update channels after completing build %s: %s", buildName, channelErr) + } + return append(packerSDKArtifacts, ®istryArtifact{ BuildName: buildName, BucketName: bucket.Name, diff --git a/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx b/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx index 503ba23d4..e649e194e 100644 --- a/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx +++ b/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx @@ -10,7 +10,7 @@ This topic provides reference information about the `hcp_packer_registry` block. ## Description -The `hcp_packer_registry` block configures details about an image Packer creates or updates in the HCP Packer registry. Use the `hcp_packer_registry` block to customize the metadata Packer sends to HCP Packer Registry. +The `hcp_packer_registry` block configures details about an image Packer creates or updates in the HCP Packer registry. Use the `hcp_packer_registry` block to customize the metadata Packer sends to HCP Packer Registry. To get started with HCP Packer, refer to the [HCP Packer documentation](/hcp/docs/packer) or try the [Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started). @@ -77,5 +77,8 @@ Some nice description about the image which artifact is being published to HCP P Packer registry. Should contain a maximum of 255 characters. Defaults to `build.description` if not set. +- `channels` ([]string) - List of channel to update to point to the new build + once the build is complete. Channels must already exist in the HCP Packer registry. + - `labels` (map[string]string) - Deprecated in Packer 1.7.9. See [`bucket_labels`](#bucket_labels) for details.