Skip to content

Commit e2a5501

Browse files
authored
Miguel/chore/arm runner for arm images (#52)
1 parent d2dc2f0 commit e2a5501

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+7829
-4395
lines changed

.github/workflows/build-image.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Build Docker Image
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
build-docker-image:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout code
11+
uses: actions/checkout@v4
12+
13+
- name: Set up QEMU
14+
uses: docker/setup-qemu-action@v3
15+
16+
- name: Set up Docker Buildx
17+
uses: docker/setup-buildx-action@v3
18+
19+
- name: Build and export
20+
uses: docker/build-push-action@v6
21+
with:
22+
context: .
23+
tags: thor-pipeline:${{ github.sha }}
24+
outputs: type=docker,dest=/tmp/thor-pipeline.tar
25+
26+
- name: Upload artifact
27+
uses: actions/upload-artifact@v4
28+
with:
29+
name: thor-pipeline-image-${{ github.sha }}
30+
path: /tmp/thor-pipeline.tar

.github/workflows/on-master-commit.yaml

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,10 @@ jobs:
3030
name: Go Module Check
3131
uses: ./.github/workflows/go-mod-check.yaml
3232

33-
run-e2e-tests:
34-
name: E2E Tests
35-
uses: ./.github/workflows/test-e2e.yaml
36-
permissions:
37-
contents: read
38-
secrets: inherit
39-
40-
run-smoke-tests:
41-
name: Smoke Tests
42-
uses: ./.github/workflows/test-smoke.yaml
43-
permissions:
44-
contents: read
45-
secrets: inherit
46-
needs: [run-e2e-tests]
33+
thor-docker-test-suite:
34+
uses: ./.github/workflows/thor-docker-test-suite.yaml
35+
secrets:
36+
DRAUPNIR_TOKEN: ${{ secrets.DRAUPNIR_TOKEN }}
4737

4838
run-rosetta-tests:
4939
name: Rosetta Tests
@@ -76,7 +66,7 @@ jobs:
7666
secrets: inherit
7767
needs:
7868
- run-unit-tests
79-
- run-e2e-tests
69+
- thor-docker-test-suite
8070
- generate-tags
8171
- lint
8272
- license-check
@@ -89,7 +79,6 @@ jobs:
8979
tags: |
9080
type=raw,value=${{ needs.generate-tags.outputs.clean_ref_name }}-${{ needs.generate-tags.outputs.tag_date }}-${{ needs.generate-tags.outputs.short_sha }}
9181
type=raw,value=${{ needs.generate-tags.outputs.clean_ref_name }}-latest
92-
trigger_internal_ci: true
9382
9483
notify-slack:
9584
name: Notify Slack
@@ -100,25 +89,23 @@ jobs:
10089
- lint
10190
- module-check
10291
- run-unit-tests
103-
- run-e2e-tests
92+
- thor-docker-test-suite
10493
if: github.ref_name == 'master' && always() && (
10594
needs.publish-docker-image.result != 'success' ||
10695
needs.run-unit-tests.result != 'success' ||
10796
needs.lint.result != 'success' ||
108-
needs.run-e2e-tests.result != 'success' ||
97+
needs.thor-docker-test-suite.result != 'success' ||
10998
needs.license-check.result != 'success' ||
11099
needs.module-check.result != 'success')
111100
runs-on: ubuntu-latest
112101
steps:
113102
- name: Checkout code
114103
uses: actions/checkout@v4
115-
116104
- name: Get the commit message
117105
id: commit_message
118106
# This is a workaround to get the first line of the commit message. Passing the entire message can cause the payload (JSON) to be invalid.
119107
run: |
120108
echo "commit_message=$(git show-branch --no-name HEAD)" >> "$GITHUB_ENV"
121-
122109
- name: Notify Slack
123110
uses: slackapi/slack-github-action@v1.25.0
124111
env:
@@ -130,7 +117,7 @@ jobs:
130117
"docker-publish-status": "${{ needs.publish-docker-image.result != 'success' && ':alert: Failure' || ':white_check_mark: Success' }}",
131118
"commit-message": "${{ env.commit_message }}",
132119
"commit-url": "${{ github.event.head_commit.url }}",
133-
"e2e-test-status": "${{ needs.run-e2e-tests.result != 'success' && ':alert: Failure' || ':white_check_mark: Success' }}",
120+
"e2e-test-status": "${{ needs.thor-docker-test-suite.result != 'success' && ':alert: Failure' || ':white_check_mark: Success' }}",
134121
"branch": "${{ github.ref }}",
135122
"repository": "${{ github.repository }}",
136123
"commit-author": "${{ github.event.head_commit.author.name }}",

.github/workflows/on-pull-request.yaml

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,11 @@ jobs:
2626
name: Go Module Check
2727
uses: ./.github/workflows/go-mod-check.yaml
2828

29-
run-e2e-tests:
30-
name: E2E Tests
31-
uses: ./.github/workflows/test-e2e.yaml
32-
permissions:
33-
contents: read
34-
secrets: inherit
29+
thor-docker-test-suite:
30+
uses: ./.github/workflows/thor-docker-test-suite.yaml
31+
secrets:
32+
DRAUPNIR_TOKEN: ${{ secrets.DRAUPNIR_TOKEN }}
3533

36-
run-smoke-tests:
37-
name: Smoke Tests
38-
uses: ./.github/workflows/test-smoke.yaml
39-
permissions:
40-
contents: read
41-
secrets: inherit
42-
needs: [run-e2e-tests]
43-
4434
run-rosetta-tests:
4535
name: Rosetta Tests
4636
uses: ./.github/workflows/test-rosetta.yaml

.github/workflows/publish-docker-images.yaml

Lines changed: 180 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,7 @@ on:
1515
type: string
1616
required: true
1717
description: 'The images to publish'
18-
trigger_internal_ci:
19-
description: 'Trigger the internal CI'
20-
required: false
21-
type: boolean
22-
default: false
2318
workflow_dispatch:
24-
inputs:
25-
trigger_internal_ci:
26-
description: 'Trigger the internal CI'
27-
required: true
28-
type: boolean
29-
default: false
3019

3120
permissions:
3221
contents: read
@@ -35,20 +24,23 @@ permissions:
3524
jobs:
3625
build-and-push-image:
3726
name: Build and Push Docker Image
38-
runs-on: ubuntu-22.04
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
include:
31+
- runs_on: ubuntu-22.04
32+
platform: linux/amd64
33+
- runs_on: ubuntu-22.04-arm
34+
platform: linux/arm64
35+
runs-on: ${{ matrix.runs_on }}
3936

4037
environment: ${{ inputs.environment }}
4138
steps:
4239

4340
- name: Checkout Repo
4441
uses: actions/checkout@v4
4542

46-
- name: Set up QEMU
47-
if: ${{ github.event_name != 'pull_request' }}
48-
uses: docker/setup-qemu-action@v3
49-
5043
- name: Set up Docker Buildx
51-
if: ${{ github.event_name != 'pull_request' }}
5244
uses: docker/setup-buildx-action@v3
5345

5446
- name: Log in to Docker Hub
@@ -76,26 +68,192 @@ jobs:
7668
# use the branch + sha if workflow_dispatch
7769
tags: ${{ inputs.tags || format('type=raw,value={0}-{1}', github.ref_name, github.sha) }}
7870

79-
- name: Push to Registry(s)
71+
- name: Compute cache scopes
72+
# BuildKit GHA cache scopes to avoid cross-arch/branch clobbering.
73+
# Shared scope depends on TARGET branch (PRs use github.base_ref):
74+
# - default(master) -> shared-default
75+
# - release/* -> shared-release-<release-branch>
76+
# Writes per event:
77+
# - pull_request : read shared+branch, write branch
78+
# - workflow_dispatch : if TARGET is master/release/* write shared+branch; else like PR
79+
# - push (master/release/*): read shared, write shared+branch
80+
id: cache
81+
shell: bash
82+
env:
83+
REPO: ${{ github.repository }}
84+
PLATFORM: ${{ matrix.platform }}
85+
REF: ${{ github.ref_name }}
86+
EVENT: ${{ github.event_name }}
87+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
88+
BASE_REF: ${{ github.base_ref }}
89+
run: |
90+
set -euo pipefail
91+
# Determine TARGET branch for shared cache (master or a specific release/*)
92+
TARGET_REF="${REF}"
93+
if [ "${EVENT}" = "pull_request" ] && [ -n "${BASE_REF}" ]; then
94+
TARGET_REF="${BASE_REF}"
95+
fi
96+
if [ "${TARGET_REF}" = "${DEFAULT_BRANCH}" ]; then
97+
SHARED_SUFFIX="default"
98+
elif [[ "${TARGET_REF}" == release/* ]]; then
99+
SANITIZED_TARGET=$(echo "${TARGET_REF}" | sed 's|/|-|g')
100+
SHARED_SUFFIX="release-${SANITIZED_TARGET}"
101+
else
102+
SHARED_SUFFIX="default"
103+
fi
104+
SHARED="${REPO}-${PLATFORM}-shared-${SHARED_SUFFIX}"
105+
BRANCH="${REPO}-${PLATFORM}-${REF}"
106+
case "${EVENT}" in
107+
pull_request)
108+
FROM=$(printf '%s\n' "type=gha,scope=${SHARED}" "type=gha,scope=${BRANCH}")
109+
TO=$(printf '%s\n' "type=gha,mode=max,scope=${BRANCH}")
110+
;;
111+
workflow_dispatch)
112+
if [ "${TARGET_REF}" = "${DEFAULT_BRANCH}" ] || [[ "${TARGET_REF}" == release/* ]]; then
113+
FROM=$(printf '%s\n' "type=gha,scope=${SHARED}")
114+
TO=$(printf '%s\n' "type=gha,mode=max,scope=${SHARED}" "type=gha,mode=max,scope=${BRANCH}")
115+
else
116+
FROM=$(printf '%s\n' "type=gha,scope=${SHARED}" "type=gha,scope=${BRANCH}")
117+
TO=$(printf '%s\n' "type=gha,mode=max,scope=${BRANCH}")
118+
fi
119+
;;
120+
*)
121+
FROM=$(printf '%s\n' "type=gha,scope=${SHARED}")
122+
TO=$(printf '%s\n' "type=gha,mode=max,scope=${SHARED}" "type=gha,mode=max,scope=${BRANCH}")
123+
;;
124+
esac
125+
echo "from<<EOF" >> "$GITHUB_OUTPUT"; echo "${FROM}" >> "$GITHUB_OUTPUT"; echo "EOF" >> "$GITHUB_OUTPUT"
126+
echo "to<<EOF" >> "$GITHUB_OUTPUT"; echo "${TO}" >> "$GITHUB_OUTPUT"; echo "EOF" >> "$GITHUB_OUTPUT"
127+
128+
- name: Compute arch-suffixed tags
129+
id: tags
130+
shell: bash
131+
env:
132+
META_TAGS: ${{ steps.meta.outputs.tags }}
133+
run: |
134+
set -euo pipefail
135+
case "${{ matrix.platform }}" in
136+
linux/amd64) ARCH="amd64" ;;
137+
linux/arm64) ARCH="arm64" ;;
138+
*) echo "Unsupported platform: ${{ matrix.platform }}" >&2; exit 1 ;;
139+
esac
140+
TMP_FILE="$(mktemp)"
141+
printf '%s\n' "${META_TAGS}" | awk -v a="$ARCH" 'NF{print $0 "-" a}' > "$TMP_FILE"
142+
if [ ! -s "$TMP_FILE" ]; then
143+
echo "No arch-suffixed tags produced" >&2
144+
exit 1
145+
fi
146+
echo "tags<<EOF" >> "$GITHUB_OUTPUT"
147+
cat "$TMP_FILE" >> "$GITHUB_OUTPUT"
148+
echo "EOF" >> "$GITHUB_OUTPUT"
149+
rm -f "$TMP_FILE"
150+
151+
- name: Build and push (${{ matrix.platform }})
152+
id: build
153+
if: ${{ github.event_name != 'pull_request' || matrix.platform == 'linux/amd64' }}
80154
uses: docker/build-push-action@v6
81155
with:
82156
context: .
83-
platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
157+
platforms: ${{ matrix.platform }}
84158
push: ${{ github.event_name != 'pull_request' }}
85159
load: ${{ github.event_name == 'pull_request' }}
86160
provenance: ${{ github.event_name != 'pull_request' }}
87161
sbom: ${{ github.event_name != 'pull_request' }}
88-
tags: ${{ steps.meta.outputs.tags }}
162+
tags: ${{ steps.tags.outputs.tags }}
89163
labels: ${{ steps.meta.outputs.labels }}
164+
cache-from: ${{ steps.cache.outputs.from }}
165+
cache-to: ${{ steps.cache.outputs.to }}
166+
167+
- name: Compute safe platform name
168+
id: platform
169+
shell: bash
170+
run: |
171+
SAFE=$(echo "${{ matrix.platform }}" | tr '/' '_')
172+
echo "safe=${SAFE}" >> $GITHUB_OUTPUT
173+
174+
- name: Export digest
175+
if: ${{ github.event_name != 'pull_request' }}
176+
shell: bash
177+
run: |
178+
PLATFORM="${{ matrix.platform }}"
179+
SAFE="${PLATFORM//\//_}"
180+
echo "${{ steps.build.outputs.digest }}" > "digest-${SAFE}.txt"
181+
182+
- name: Upload digest artifact
183+
if: ${{ github.event_name != 'pull_request' }}
184+
uses: actions/upload-artifact@v4
185+
with:
186+
name: digest-${{ steps.platform.outputs.safe }}
187+
path: digest-${{ steps.platform.outputs.safe }}.txt
90188

91189
- name: Scan for vulnerabilities
92190
uses: crazy-max/ghaction-container-scan@v3
93-
if: ${{ github.event_name == 'pull_request' || github.ref_name == 'master' }}
191+
if: ${{ (github.event_name == 'pull_request' && matrix.platform == 'linux/amd64') || (github.ref_name == 'master' && matrix.platform == 'linux/amd64') }}
94192
with:
95-
image: ${{ fromJSON(steps.meta.outputs.json).tags[0] }}
193+
image: ${{ github.event_name == 'pull_request' && steps.tags.outputs.tags || fromJSON(steps.meta.outputs.json).tags[0] }}
96194
annotations: true
97195
severity: LOW
98196
dockerfile: ./Dockerfile
99197
env:
100198
# See https://github.com/aquasecurity/trivy/discussions/7538
101199
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
200+
201+
merge-manifest:
202+
name: Create multi-arch manifest
203+
needs: [build-and-push-image]
204+
if: ${{ github.event_name != 'pull_request' }}
205+
runs-on: ubuntu-22.04
206+
steps:
207+
- name: Checkout Repo
208+
uses: actions/checkout@v4
209+
210+
- name: Log in to the Container registry
211+
uses: docker/login-action@v3
212+
with:
213+
registry: ghcr.io
214+
username: ${{ github.actor }}
215+
password: ${{ secrets.GITHUB_TOKEN }}
216+
217+
- name: Log in to Docker Hub
218+
uses: docker/login-action@v3
219+
if: ${{ inputs.environment == 'docker-publish' }}
220+
with:
221+
username: ${{ secrets.DOCKERHUB_USERNAME }}
222+
password: ${{ secrets.DOCKERHUB_TOKEN }}
223+
224+
- name: Set up Docker Buildx
225+
uses: docker/setup-buildx-action@v3
226+
227+
- name: Extract metadata (tags, labels) for Docker
228+
id: meta
229+
uses: docker/metadata-action@v5
230+
with:
231+
# default to ghcr.io for workflow_dispatch
232+
images: ${{ inputs.images || format('ghcr.io/{0}', github.repository) }}
233+
# use the branch + sha if workflow_dispatch
234+
tags: ${{ inputs.tags || format('type=raw,value={0}-{1}', github.ref_name, github.sha) }}
235+
236+
- name: Download digests
237+
uses: actions/download-artifact@v4
238+
with:
239+
pattern: digest-*
240+
path: ./digests
241+
merge-multiple: true
242+
243+
- name: Create and push manifest list
244+
env:
245+
TAGS: ${{ steps.meta.outputs.tags }}
246+
IMAGE: ${{ inputs.images || format('ghcr.io/{0}', github.repository) }}
247+
shell: bash
248+
run: |
249+
AMD64_DIGEST=$(cat digests/digest-linux_amd64.txt)
250+
ARM64_DIGEST=$(cat digests/digest-linux_arm64.txt)
251+
TAG_ARGS=""
252+
while IFS= read -r tag; do
253+
[ -z "$tag" ] && continue
254+
TAG_ARGS="$TAG_ARGS -t $tag"
255+
done <<< "$TAGS"
256+
docker buildx imagetools create \
257+
$TAG_ARGS \
258+
"$IMAGE@${AMD64_DIGEST}" \
259+
"$IMAGE@${ARM64_DIGEST}"

0 commit comments

Comments
 (0)