Skip to content

Commit aa5a637

Browse files
authored
Merge pull request #863 from RoEdAl/docker-build-multiple-runners
Docker: distribute build across multiple runners
2 parents fc33494 + 40d8243 commit aa5a637

3 files changed

Lines changed: 199 additions & 35 deletions

File tree

Lines changed: 194 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,234 @@
1+
#
2+
# Based on:
3+
#
4+
# Docker docs: Distribute build across multiple runners
5+
# https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
6+
#
7+
18
name: Upload Docker images to GitHub Container Registry (ghcr.io)
29

310
on:
411
release:
5-
types: [published]
12+
types:
13+
- released
14+
615
push:
7-
branches: [ master, main ]
8-
tags: [ 'v*' ]
16+
branches:
17+
- master
18+
- main
19+
920
pull_request:
10-
branches: [ master, main ]
21+
branches:
22+
- master
23+
- main
24+
25+
workflow_dispatch:
26+
inputs:
27+
ref:
28+
description: Git tag to push the image
29+
required: true
30+
type: string
1131

1232
jobs:
13-
docker:
14-
name: Build images
33+
prepare:
34+
name: Prepare
35+
runs-on: ubuntu-latest
36+
outputs:
37+
github_repository: ${{ steps.vars.outputs.github_repository }}
38+
publish_image: ${{ steps.vars.outputs.publish_image }}
39+
semver_value: ${{ steps.vars.outputs.semver_value }}
40+
steps:
41+
- id: vars
42+
name: Prepare outputs
43+
run: |
44+
function prepend() { while read line; do echo "${1}${line}"; done; }
45+
readonly NOTICE_VAR='::notice title=Setting variable::'
46+
47+
github_repository=${{ github.repository }}
48+
echo "github_repository=${github_repository,,}" | tee -a $GITHUB_OUTPUT | prepend "$NOTICE_VAR"
49+
50+
if [ "${{ github.event_name }}" = "release" ]; then
51+
echo "publish_image=true" | tee -a $GITHUB_OUTPUT | prepend "$NOTICE_VAR"
52+
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
53+
echo "publish_image=true" | tee -a $GITHUB_OUTPUT | prepend "$NOTICE_VAR"
54+
echo "semver_value=,value=${{ inputs.ref }}" | tee -a $GITHUB_OUTPUT | prepend "$NOTICE_VAR"
55+
fi
56+
57+
build:
58+
name: Build image
59+
if: github.event_name == 'pull_request'
1560
runs-on: ubuntu-latest
61+
needs:
62+
- prepare
1663
steps:
1764
- name: Check out code
1865
uses: actions/checkout@v4
19-
- name: Set up QEMU
20-
if: github.event_name != 'pull_request'
21-
uses: docker/setup-qemu-action@v3
2266
with:
23-
platforms: arm,arm64
24-
cache-image: false
67+
fetch-tags: true
68+
69+
- name: Docker meta
70+
id: meta
71+
uses: docker/metadata-action@v5
72+
with:
73+
images: ghcr.io/${{ github.repository }}
74+
2575
- name: Set up Docker Buildx
2676
uses: docker/setup-buildx-action@v3
77+
78+
- name: Build
79+
uses: docker/build-push-action@v6
80+
with:
81+
context: .
82+
platforms: linux/amd64
83+
push: false
84+
tags: ${{ steps.meta.outputs.tags }}
85+
labels: ${{ steps.meta.outputs.labels }}
86+
annotations: ${{ steps.meta.outputs.annotations }}
87+
88+
mbuild:
89+
name: Build image
90+
needs:
91+
- prepare
92+
if: github.event_name != 'pull_request'
93+
runs-on: ubuntu-latest
94+
strategy:
95+
fail-fast: false
96+
matrix:
97+
platform:
98+
- platform: linux/amd64
99+
- platform: linux/arm64
100+
qemu: arm64
101+
- platform: linux/arm/v7
102+
qemu: arm
103+
- platform: linux/arm/v6
104+
qemu: arm
105+
steps:
106+
- name: Prepare
107+
id: prepare
108+
run: |
109+
platform=${{ matrix.platform.platform }}
110+
echo "platform_pair=${platform//\//-}" | tee -a $GITHUB_OUTPUT
111+
112+
- name: Check out code
113+
if: github.event_name == 'workflow_dispatch'
114+
uses: actions/checkout@v4
115+
with:
116+
ref: ${{ inputs.ref }}
117+
fetch-tags: true
118+
119+
- name: Check out code
120+
if: github.event_name != 'workflow_dispatch'
121+
uses: actions/checkout@v4
122+
with:
123+
fetch-tags: true
124+
27125
- name: Docker meta
28126
id: meta
29127
uses: docker/metadata-action@v5
30128
with:
31129
images: ghcr.io/${{ github.repository }}
32-
# create latest tag for branch events
33-
flavor: |
34-
latest=${{ github.event_name == 'push' && github.ref_type == 'branch' }}
35-
tags: |
36-
type=ref,event=branch
37-
type=ref,event=pr
38-
type=semver,pattern={{version}}
39-
type=semver,pattern={{major}}.{{minor}}
40-
type=semver,pattern={{major}}.{{minor}}.{{patch}}
41-
env:
42-
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
130+
131+
- name: Set up QEMU
132+
uses: docker/setup-qemu-action@v3
133+
if: ${{ matrix.platform.qemu }}
134+
with:
135+
platforms: ${{ matrix.platform.qemu }}
136+
cache-image: false
137+
138+
- name: Set up Docker Buildx
139+
uses: docker/setup-buildx-action@v3
140+
43141
- name: Login to GitHub Container Registry
44-
if: github.event_name != 'pull_request'
142+
if: needs.prepare.outputs.publish_image
45143
uses: docker/login-action@v3
46144
with:
47145
registry: ghcr.io
48146
username: ${{ github.actor }}
49147
password: ${{ secrets.GITHUB_TOKEN }}
148+
50149
- name: Build
51-
if: github.event_name == 'pull_request'
150+
if: ${{ ! needs.prepare.outputs.publish_image }}
52151
uses: docker/build-push-action@v6
53152
with:
54153
context: .
55-
platforms: linux/amd64
154+
platforms: ${{ matrix.platform.platform }}
56155
push: false
57156
tags: ${{ steps.meta.outputs.tags }}
58157
labels: ${{ steps.meta.outputs.labels }}
59158
annotations: ${{ steps.meta.outputs.annotations }}
159+
60160
- name: Build and push
61-
if: github.event_name != 'pull_request'
161+
if: needs.prepare.outputs.publish_image
62162
uses: docker/build-push-action@v6
163+
id: build
63164
with:
64165
context: .
65-
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
66-
push: true
67-
tags: ${{ steps.meta.outputs.tags }}
166+
platforms: ${{ matrix.platform.platform }}
68167
labels: ${{ steps.meta.outputs.labels }}
69168
annotations: ${{ steps.meta.outputs.annotations }}
70-
cache-from: type=gha
71-
cache-to: type=gha,mode=max
169+
outputs: type=image,"name=ghcr.io/${{ needs.prepare.outputs.github_repository }}",push-by-digest=true,name-canonical=true,push=true
170+
171+
- name: Export digest
172+
if: needs.prepare.outputs.publish_image
173+
run: |
174+
mkdir -p ${{ runner.temp }}/digests
175+
digest='${{ steps.build.outputs.digest }}'
176+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
177+
178+
- name: Upload digest
179+
if: needs.prepare.outputs.publish_image
180+
uses: actions/upload-artifact@v4
181+
with:
182+
name: digests-${{ steps.prepare.outputs.platform_pair }}
183+
path: ${{ runner.temp }}/digests/*
184+
if-no-files-found: error
185+
retention-days: 1
186+
compression-level: 0
187+
188+
merge:
189+
name: Merge images
190+
runs-on: ubuntu-latest
191+
needs:
192+
- prepare
193+
- mbuild
194+
if: needs.prepare.outputs.publish_image
195+
steps:
196+
- name: Download digests
197+
uses: actions/download-artifact@v4
198+
with:
199+
path: ${{ runner.temp }}/digests
200+
pattern: digests-*
201+
merge-multiple: true
202+
203+
- name: Login to GHCR
204+
uses: docker/login-action@v3
205+
with:
206+
registry: ghcr.io
207+
username: ${{ github.actor }}
208+
password: ${{ secrets.GITHUB_TOKEN }}
209+
210+
- name: Set up Docker Buildx
211+
uses: docker/setup-buildx-action@v3
212+
213+
- name: Docker meta
214+
id: meta
215+
uses: docker/metadata-action@v5
216+
with:
217+
images: ghcr.io/${{ github.repository }}
218+
flavor: |
219+
latest=${{ github.event_name == 'workflow_dispatch' && 'false' || 'auto' }}
220+
tags: |
221+
type=semver,pattern={{version}}${{ needs.prepare.outputs.semver_value }}
222+
type=semver,pattern={{major}}.{{minor}}${{ needs.prepare.outputs.semver_value }}
223+
type=semver,pattern={{major}}.{{minor}}.{{patch}}${{ needs.prepare.outputs.semver_value }}
224+
225+
- name: Create manifest list and push
226+
working-directory: ${{ runner.temp }}/digests
227+
run: |
228+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
229+
$(printf 'ghcr.io/${{ needs.prepare.outputs.github_repository }}@sha256:%s ' *)
230+
231+
- name: Inspect image
232+
run: docker buildx imagetools inspect ghcr.io/${{ needs.prepare.outputs.github_repository }}:${{ steps.meta.outputs.version }}
233+
234+

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
FROM golang:alpine AS builder
22
ARG TARGETARCH
3+
ARG GOCACHE=/tmp
34

45
RUN apk --no-cache add --update make gcc git musl-dev
56

67
USER nobody:nogroup
78
WORKDIR /usr/local/src/carbonapi
89
COPY --chown=nobody:nogroup . .
910
RUN --network=none make clean
10-
RUN --mount=type=cache,id=go-cache,target=/.cache,sharing=locked,uid=65534,gid=65534 make nocairo
11-
RUN --mount=type=cache,id=go-cache,target=/.cache,sharing=locked,uid=65534,gid=65534 <<EOT
11+
RUN make nocairo
12+
RUN <<EOT
1213
if [ "${TARGETARCH:-unknown}" = "amd64" ]; then
1314
make test_nocairo
1415
else

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Copyright (c) 2013-2018 Damian Gryski <damian@gryski.com>
2-
2018 Google LLC
1+
Copyright (c) 2013-2018 Damian Gryski <damian@gryski.com> Google LLC
2+
Copyright (c) 2020- Go-Graphite project
33

44
All rights reserved.
55

0 commit comments

Comments
 (0)