Skip to content

Commit 359d002

Browse files
committed
chore: enhance Docker workflow with metadata-action improvements
- Add docker/metadata-action to build job for consistent metadata handling - Add OCI-compliant labels (title, description, maintainer) - Enable annotations support at manifest and index levels - Use metadata-action outputs for tags, labels, and annotations - Support publishing to both Docker Hub and GitHub Container Registry - Add PR dry-run mode to release workflow
1 parent 647c448 commit 359d002

File tree

7 files changed

+312
-176
lines changed

7 files changed

+312
-176
lines changed

.dockerignore

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,68 @@
33
.gitignore
44
.gitattributes
55

6-
# CI/CD
7-
.github
8-
9-
# Documentation
10-
*.md
11-
docs/
6+
# Build artifacts
7+
dist/
8+
**/dist/
9+
# Allow CLI binaries for Docker builds
10+
!dist/github-actions-utils-cli-linux-*
11+
build/
12+
**/build/
13+
*.swp
14+
*.swo
15+
*~
1216

13-
# Development
14-
.cursor/
15-
.vscode/
16-
.idea/
17+
# Node
18+
node_modules/
19+
**/node_modules/
20+
npm-debug.log*
21+
yarn-debug.log*
22+
yarn-error.log*
23+
.npm
24+
.pnpm-store
1725

18-
# Build artifacts (we copy specific binaries)
19-
dist/*
20-
!dist/github-actions-utils-cli-linux-*
26+
# macOS files
27+
**/.DS_Store
2128

22-
# Go
23-
go.sum
24-
*.test
25-
*.out
26-
coverage.txt
29+
# Testing
30+
coverage/
31+
.nyc_output
2732

28-
# Dependencies
29-
vendor/
33+
# IDE
34+
.idea/
35+
.vscode/
36+
*.iml
37+
*.swp
38+
*.swo
39+
*~
40+
.DS_Store
3041

3142
# OS
32-
.DS_Store
3343
Thumbs.db
3444

35-
# Misc
36-
LICENSE
37-
renovate.json
38-
dprint.json
39-
Brewfile
40-
Makefile
45+
# Deployment
46+
deploy/
47+
.pulumi/
4148

42-
# Keep only what's needed for the build
43-
!dist/github-actions-utils-cli-linux-amd64
44-
!dist/github-actions-utils-cli-linux-arm64
49+
# Docs
50+
docs/
51+
*.md
52+
!README.md
4553

54+
# Examples and tests
55+
examples/
56+
*_test.go
57+
testdata/
58+
59+
# CI/CD
60+
.github/
61+
.gitlab-ci.yml
62+
.travis.yml
63+
64+
# Misc
65+
.env
66+
.env.*
67+
!.env.example
68+
tmp/
69+
temp/
70+
*.log
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Build CLI Docker Images
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
tag_name:
7+
description: "Tag name for Docker images"
8+
required: true
9+
type: string
10+
is_prerelease:
11+
description: "Whether this is a prerelease"
12+
required: true
13+
type: string
14+
15+
jobs:
16+
build:
17+
name: Build CLI Docker Image (${{ matrix.platform.name }})
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
attestations: write
23+
id-token: write
24+
timeout-minutes: 30
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
platform:
29+
- name: linux/amd64
30+
tag: linux-amd64
31+
- name: linux/arm64
32+
tag: linux-arm64
33+
concurrency:
34+
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.platform.name }}
35+
cancel-in-progress: true
36+
37+
steps:
38+
- name: Checkout Repository
39+
uses: actions/checkout@v5
40+
41+
- name: Download CLI artifacts
42+
uses: actions/download-artifact@v6
43+
with:
44+
path: dist
45+
pattern: cli-${{ matrix.platform.tag }}
46+
merge-multiple: true
47+
48+
- name: List downloaded files
49+
run: ls -lh dist/
50+
51+
- name: Set up QEMU
52+
uses: docker/setup-qemu-action@v3
53+
54+
- name: Set up Docker Buildx
55+
uses: docker/setup-buildx-action@v3
56+
57+
- name: Docker meta
58+
id: meta
59+
uses: docker/metadata-action@v5
60+
with:
61+
images: |
62+
docker.io/${{ github.repository }}
63+
ghcr.io/${{ github.repository }}
64+
tags: |
65+
type=raw,value=${{ inputs.tag_name }}
66+
labels: |
67+
org.opencontainers.image.title=GitHub Actions Utils CLI
68+
org.opencontainers.image.description=MCP server for GitHub Actions utilities
69+
maintainer=techprimate GmbH <[email protected]>
70+
71+
- name: Login to Docker Hub
72+
uses: docker/login-action@v3
73+
with:
74+
username: ${{ vars.DOCKERHUB_USERNAME }}
75+
password: ${{ secrets.DOCKERHUB_TOKEN }}
76+
77+
- name: Login to GitHub Container Registry
78+
uses: docker/login-action@v3
79+
with:
80+
registry: ghcr.io
81+
username: ${{ github.actor }}
82+
password: ${{ secrets.GITHUB_TOKEN }}
83+
84+
- name: Build ${{ github.event_name == 'pull_request' && '(dry run)' || 'and push' }} by digest
85+
id: build
86+
uses: docker/build-push-action@v6
87+
with:
88+
context: .
89+
file: ./Dockerfile
90+
platforms: ${{ matrix.platform.name }}
91+
tags: ${{ steps.meta.outputs.tags }}
92+
labels: ${{ steps.meta.outputs.labels }}
93+
annotations: ${{ steps.meta.outputs.annotations }}
94+
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache-${{ matrix.platform.tag }}
95+
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache-${{ matrix.platform.tag }},mode=max
96+
outputs: type=image,push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
97+
env:
98+
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
99+
100+
- name: Export digest
101+
if: github.event_name != 'pull_request'
102+
run: |
103+
set -e
104+
mkdir -p /tmp/digests
105+
digest="${{ steps.build.outputs.digest }}"
106+
touch "/tmp/digests/${digest#sha256:}"
107+
ls -la /tmp/digests
108+
109+
- name: Upload digest
110+
if: github.event_name != 'pull_request'
111+
uses: actions/upload-artifact@v5
112+
with:
113+
name: cli-docker-digests-${{ matrix.platform.tag }}
114+
path: /tmp/digests/*
115+
if-no-files-found: error
116+
retention-days: 1
117+
118+
merge:
119+
name: Create Manifest List
120+
runs-on: ubuntu-latest
121+
needs: build
122+
if: github.event_name != 'pull_request'
123+
permissions:
124+
contents: read
125+
packages: write
126+
id-token: write
127+
timeout-minutes: 10
128+
concurrency:
129+
group: ${{ github.workflow }}-${{ github.ref }}-merge
130+
cancel-in-progress: true
131+
steps:
132+
- name: Download digests
133+
uses: actions/download-artifact@v6
134+
with:
135+
path: /tmp/digests
136+
pattern: cli-docker-digests-*
137+
merge-multiple: true
138+
139+
- name: List digests
140+
run: ls -la /tmp/digests
141+
142+
- name: Set up Docker Buildx
143+
uses: docker/setup-buildx-action@v3
144+
145+
- name: Create Docker Metadata
146+
id: meta
147+
uses: docker/metadata-action@v5
148+
with:
149+
images: |
150+
docker.io/${{ github.repository }}
151+
ghcr.io/${{ github.repository }}
152+
tags: |
153+
type=raw,value=${{ inputs.tag_name }}
154+
type=raw,value=latest,enable=${{ inputs.is_prerelease == 'true' }}
155+
type=semver,pattern={{version}},value=${{ inputs.tag_name }},enable=${{ inputs.is_prerelease == 'false' }}
156+
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.tag_name }},enable=${{ inputs.is_prerelease == 'false' }}
157+
158+
- name: Login to Docker Hub
159+
uses: docker/login-action@v3
160+
with:
161+
username: ${{ vars.DOCKERHUB_USERNAME }}
162+
password: ${{ secrets.DOCKERHUB_TOKEN }}
163+
164+
- name: Login to GitHub Container Registry
165+
uses: docker/login-action@v3
166+
with:
167+
registry: ghcr.io
168+
username: ${{ github.actor }}
169+
password: ${{ secrets.GITHUB_TOKEN }}
170+
171+
- name: Create manifest list and push
172+
working-directory: /tmp/digests
173+
run: |
174+
# Extract all tags
175+
image_tags=$(printf '%s' "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr '.tags | map("-t " + .) | join(" ")')
176+
echo "Creating manifest list with tags: $image_tags"
177+
178+
# Extract unique image names (without tags) to build digest references
179+
image_names=$(printf '%s' "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr '.tags | map(split(":")[0]) | unique | join(" ")')
180+
echo "Image names: $image_names"
181+
182+
# Build digest references for all images
183+
digest_refs=""
184+
for image_name in $image_names; do
185+
for digest_file in *; do
186+
digest_refs="$digest_refs ${image_name}@sha256:${digest_file}"
187+
done
188+
done
189+
echo "Digest references: $digest_refs"
190+
191+
echo "Creating manifest using buildx..."
192+
docker buildx imagetools create $image_tags $digest_refs
193+
194+
# Inspect the first tag for verification
195+
first_tag=$(printf '%s' "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr '.tags[0]')
196+
docker buildx imagetools inspect "$first_tag"

0 commit comments

Comments
 (0)