Skip to content

Commit 81fa635

Browse files
committed
feature(bake): add promote action
1 parent aff13cd commit 81fa635

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

buildx-bake/promote/action.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: "Promote Manifests"
2+
description: "Promote an existing manifest with new tags"
3+
inputs:
4+
version:
5+
description: 'Conventional version to promote (e.g. 1.2.3)'
6+
required: true
7+
image-digests:
8+
description: 'JSON with all merged image manifest digests'
9+
required: true
10+
registry:
11+
description: 'The container registry'
12+
required: false
13+
default: 'ghcr.io'
14+
registry-username:
15+
description: 'The container registry username'
16+
required: true
17+
default: ${{ github.actor }}
18+
registry-password:
19+
description: 'The container registry password'
20+
required: true
21+
tag-latest:
22+
description: 'Also tag as latest'
23+
required: false
24+
default: 'true'
25+
tag-major:
26+
description: 'Also tag with major version'
27+
required: false
28+
default: 'true'
29+
tag-minor:
30+
description: 'Also tag with major.minor version'
31+
required: false
32+
default: 'true'
33+
runs:
34+
using: "composite"
35+
steps:
36+
- name: Login to registry
37+
uses: docker/login-action@v3
38+
with:
39+
registry: ${{ inputs.registry }}
40+
username: ${{ inputs.registry-username }}
41+
password: ${{ inputs.registry-password }}
42+
43+
- name: Setup Docker Buildx
44+
uses: docker/setup-buildx-action@v3
45+
46+
- name: Promote manifests
47+
shell: python
48+
env:
49+
VERSION: ${{ inputs.version }}
50+
IMAGE_DIGESTS: ${{ inputs.image-digests }}
51+
TAG_LATEST: ${{ inputs.tag-latest }}
52+
TAG_MAJOR: ${{ inputs.tag-major }}
53+
TAG_MINOR: ${{ inputs.tag-minor }}
54+
run: |
55+
import json, os, re, subprocess
56+
57+
version = os.environ["VERSION"]
58+
image_digests = json.loads(os.environ["IMAGE_DIGESTS"])
59+
tag_latest = os.environ["TAG_LATEST"].lower() == "true"
60+
tag_major = os.environ["TAG_MAJOR"].lower() == "true"
61+
tag_minor = os.environ["TAG_MINOR"].lower() == "true"
62+
63+
# Parse semantic version
64+
m = re.match(r"^v?(\d+)\.(\d+)\.(\d+)", version)
65+
if not m:
66+
raise ValueError(f"Invalid semantic version: {version}")
67+
major, minor, patch = m.groups()
68+
version_clean = f"{major}.{minor}.{patch}"
69+
70+
# Build tag list
71+
tags = [version_clean]
72+
if tag_minor:
73+
tags.append(f"{major}.{minor}")
74+
if tag_major:
75+
tags.append(major)
76+
if tag_latest:
77+
tags.append("latest")
78+
79+
print(f"Promoting version: {version_clean}", flush=True)
80+
print(f"Tags: {', '.join(tags)}", flush=True)
81+
82+
def run(cmd):
83+
print(f"+ {' '.join(cmd)}", flush=True)
84+
subprocess.run(cmd, check=True)
85+
86+
# Promote each image
87+
for item in image_digests:
88+
image_name = item["name"]
89+
digest = item["digest"]
90+
source = f"{image_name}@{digest}"
91+
tag_args = [a for t in tags for a in ("-t", f"{image_name}:{t}")]
92+
print(f"\nPromoting: {source}", flush=True)
93+
run(["docker", "buildx", "imagetools", "create", *tag_args, source])

0 commit comments

Comments
 (0)