Skip to content

Commit 06540b8

Browse files
committed
feat: add Docker build and release call workflow Action`
Add a workflow that takes a Dockerfile, target, a registry, and desired platforms, builds images, and pushes them to the registry, and creates attestations. Keeps some of the inputs from the Goreleaser workflow, but not all. I removed some stuff that looked unecessary (because it could be done in the Dockerfile instead) or where it looked like there were better options for reasonable defaults. If the pushed ref is a tag, create a release for it, unless the release already exists. Signed-off-by: Travis Raines <571832+rainest@users.noreply.github.com>
1 parent 9b25637 commit 06540b8

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Build image
2+
run-name: Dockeer image build for ${{ github.event.push.ref }}
3+
4+
on:
5+
workflow_call:
6+
inputs:
7+
fetch-depth:
8+
description: 'Git fetch depth for checkout'
9+
required: false
10+
type: number
11+
default: 0
12+
fetch-tags:
13+
description: 'Whether to fetch tags during checkout'
14+
required: false
15+
type: number
16+
default: 1
17+
cgo-enabled:
18+
description: 'Set CGO_ENABLED environment variable'
19+
required: false
20+
type: string
21+
default: ''
22+
additional-env-vars:
23+
description: 'Additional environment variables to set (KEY=value format, one per line)'
24+
required: false
25+
type: string
26+
default: ''
27+
registry-name:
28+
description: 'Container registry name (e.g., ghcr.io/openchami/project-name) to Generate build provenance for container'
29+
required: true
30+
type: string
31+
docker-file:
32+
description: 'Dockerfile to use'
33+
required: false
34+
type: string
35+
default: 'Dockerfile'
36+
docker-target:
37+
description: 'Dockerfile target to build'
38+
required: false
39+
type: string
40+
default: 'main'
41+
platforms:
42+
description: 'Platforms to build for'
43+
type: string
44+
default: 'linux/amd64, linux/arm64'
45+
46+
permissions: write-all # Necessary for the generate-build-provenance action with containers
47+
48+
jobs:
49+
build-push-images:
50+
environment: 'Docker Push'
51+
runs-on: ubuntu-latest
52+
steps:
53+
- name: checkout repository
54+
uses: actions/checkout@v4.2.2
55+
with:
56+
fetch-depth: 0
57+
58+
- name: Setup golang
59+
uses: actions/setup-go@v5.5.0
60+
with:
61+
go-version-file: go.mod
62+
63+
- run: echo "GOPATH=$(go env GOPATH)" >> "$GITHUB_ENV"
64+
65+
- run: echo "GOCACHE=$(go env GOCACHE)" >> "$GITHUB_ENV"
66+
67+
- name: Set CGO_ENABLED if specified
68+
if: ${{ inputs.cgo-enabled != '' }}
69+
run: echo "CGO_ENABLED=${{ inputs.cgo-enabled }}" >> "$GITHUB_ENV"
70+
71+
- name: Set additional environment variables
72+
if: ${{ inputs.additional-env-vars != '' }}
73+
run: |
74+
# Process additional environment variables
75+
echo "${{ inputs.additional-env-vars }}" | while IFS= read -r line; do
76+
if [[ -n "$line" && "$line" == *"="* ]]; then
77+
echo "$line" >> "$GITHUB_ENV"
78+
fi
79+
done
80+
81+
- name: Set up Docker Buildkit
82+
uses: docker/setup-buildx-action@v3.11.1
83+
84+
- name: Cache Docker layers
85+
uses: actions/cache@v4.2.3
86+
with:
87+
path: /tmp/.buildx-cache
88+
key: ${{ runner.os }}-buildx-${{ github.sha }}
89+
restore-keys: |
90+
${{ runner.os }}-buildx-
91+
92+
- name: Fill image meta
93+
id: meta
94+
uses: docker/metadata-action@v5.8.0
95+
with:
96+
images: ${{ inputs.registry-name }}
97+
tags: |
98+
# branch event
99+
type=ref,event=branch
100+
# tag event
101+
type=ref,event=tag
102+
# pull request event
103+
type=ref,event=pr
104+
105+
- name: Auth to registry
106+
uses: docker/login-action@v3.5.0
107+
with:
108+
username: ${{ github.actor }}
109+
password: ${{ secrets.GITHUB_TOKEN }}
110+
registry: ghcr.io
111+
112+
- name: Build and push image
113+
id: docker_build
114+
uses: docker/build-push-action@v6.18.0
115+
with:
116+
push: true
117+
file: ${{ inputs.docker-file }}
118+
tags: ${{ steps.meta.outputs.tags }}
119+
labels: ${{ steps.meta.outputs.labels }}
120+
# Unclear how https://docs.docker.com/build/ci/github-actions/attestations/ interacts with
121+
# multi-stage builds and cache. A separate build and cache step is useful if we copy the
122+
# same binary to multiple images, but a single invocation may still be able to handle that?
123+
cache-from: type=local,src=/tmp/.buildx-cache
124+
cache-to: type=local,dest=/tmp/.buildx-cache
125+
provenance: mode=max
126+
sbom: true
127+
target: ${{ inputs.docker-target }}
128+
platforms: ${{ inputs.platforms }}
129+
build-args: |
130+
TAG=${{ steps.meta.outputs.version }}
131+
COMMIT=${{ github.sha }}
132+
REPO_INFO=https://github.com/${{ github.repository }}.git
133+
GOPATH=${{ env.GOPATH}}
134+
GOCACHE=${{ env.GOCACHE}}
135+
CGO_ENABLED=${{ env.CGO_ENABLED }}
136+
CC=${{ env.CC }}
137+
- name: Attest
138+
uses: actions/attest-build-provenance@v3
139+
id: attest
140+
with:
141+
subject-name: ${{ inputs.registry-name }}
142+
subject-digest: ${{ steps.docker_build.outputs.digest }}
143+
push-to-registry: true
144+
145+
publish-release:
146+
runs-on: ubuntu-latest
147+
needs: build-push-images
148+
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
149+
permissions:
150+
contents: write
151+
steps:
152+
- name: Parse semver string
153+
id: semver_parser
154+
uses: booxmedialtd/ws-action-parse-semver@v1.4.7
155+
with:
156+
input_string: ${{ github.event.ref }}
157+
version_extractor_regex: 'refs/tags/v(.*)$'
158+
- uses: ncipollo/release-action@v1.18.0
159+
with:
160+
# by default this will use the tag push tag as the tag and name
161+
# if we want to trigger tagging from the workflow, "tag" and "commit"
162+
# need to be set to create a new one
163+
prerelease: ${{ steps.semver_parser.outputs.prerelease != '' }}
164+
skipIfReleaseExists: true

.github/workflows/go-build-release.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ on:
5858
required: false
5959
type: string
6060
default: 'auto'
61+
devel:
62+
description: 'Create and upload a development build'
63+
type: boolean
64+
required: false
65+
default: false
66+
ref:
67+
description: 'The commit hash for development builds'
68+
required: false
69+
type: string
70+
default: ''
6171

6272
permissions: write-all # Necessary for the generate-build-provenance action with containers
6373

@@ -86,6 +96,7 @@ jobs:
8696
with:
8797
fetch-tags: ${{ inputs.fetch-tags }}
8898
fetch-depth: ${{ inputs.fetch-depth }}
99+
ref: ${{ inputs.ref }}
89100

90101
- name: Set build environment variables
91102
run: |
@@ -161,3 +172,22 @@ jobs:
161172
subject-name: ${{ inputs.registry-name }}
162173
subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }}
163174
push-to-registry: true
175+
176+
# Credit to the https://github.com/goreleaser/goreleaser/issues/2828#issuecomment-1311662146 workaround
177+
# for nightly/snapshot builds being locked behind the paid version of goreleaser.
178+
- name: List snapshot images
179+
# types are hard vov https://github.com/actions/runner/issues/2238
180+
if: true
181+
run: |
182+
docker image ls --format "{{.Repository}}:{{.Tag}}" | \
183+
grep -e "$GITHUB_REPOSITORY:.*$(git rev-parse --short HEAD).*" | \
184+
paste -sd ' ' /dev/stdin > images
185+
- name: Push snapshot images
186+
if: true
187+
run: |
188+
cat images | xargs -d ' ' -I{} -n1 sh -c "docker push {}"
189+
- name: Create and push manifest for :snapshot tag
190+
if: true
191+
run: |
192+
docker manifest create $GITHUB_REPOSITORY:snapshot $(cat images)
193+
docker manifest push $GITHUB_REPOSITORY:snapshot

0 commit comments

Comments
 (0)