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.
This commit is contained in:
Tanmay Jain 2025-11-21 12:43:46 +05:30
parent c60dc95eda
commit 0e354e503b
4 changed files with 60 additions and 1 deletions

View file

@ -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{

View file

@ -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
}

View file

@ -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, &registryArtifact{
BuildName: buildName,
BucketName: bucket.Name,

View file

@ -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.