@@ -94,18 +94,21 @@ jobs:
94
94
# Dynamically define job matrix.
95
95
# We need a separate matrix entry for each distribution, when the relevant input is true.
96
96
# https://stackoverflow.com/questions/65384420/how-do-i-make-a-github-action-matrix-element-conditional
97
+ # NOTE(bbezak): Both amd64 and aarch64 need to be built in a single workflow to create a multi-architecture manifest.
98
+ # For now include only RL9 in aarch64
97
99
- name : Generate build matrix
98
100
id : set-matrix
99
101
run : |
100
102
output="{'distro': ["
101
103
if [[ ${{ inputs.rocky-linux-9 }} == 'true' ]]; then
102
- output+="{'name': 'rocky', 'release': 9},"
104
+ output+="{'name': 'rocky', 'release': 9, 'arch': 'amd64'},"
105
+ output+="{'name': 'rocky', 'release': 9, 'arch': 'aarch64'},"
103
106
fi
104
107
if [[ ${{ inputs.ubuntu-jammy }} == 'true' ]]; then
105
- output+="{'name': 'ubuntu', 'release': 'jammy'},"
108
+ output+="{'name': 'ubuntu', 'release': 'jammy', 'arch': 'amd64' },"
106
109
fi
107
110
if [[ ${{ inputs.ubuntu-noble }} == 'true' ]]; then
108
- output+="{'name': 'ubuntu', 'release': 'noble'},"
111
+ output+="{'name': 'ubuntu', 'release': 'noble', 'arch': 'amd64' },"
109
112
fi
110
113
# remove trailing comma
111
114
output="${output%,}"
@@ -124,7 +127,9 @@ jobs:
124
127
container-image-build :
125
128
name : Build Kolla container images
126
129
if : github.repository == 'stackhpc/stackhpc-kayobe-config'
127
- runs-on : ${{ needs.runner-selection.outputs.runner_name_container_image_build }}
130
+ runs-on : ${{ matrix.distro.arch == 'aarch64'
131
+ && fromJson('["self-hosted","sms","arm64"]')
132
+ || needs.runner-selection.outputs.runner_name_container_image_build }}
128
133
timeout-minutes : 720
129
134
permissions : {}
130
135
strategy :
@@ -147,6 +152,10 @@ jobs:
147
152
sudo apt update
148
153
sudo apt install gh -y
149
154
155
+ - name : Purge workspace (Arm runner only)
156
+ if : runner.arch == 'ARM64'
157
+ run : sudo rm -rf "$GITHUB_WORKSPACE"/*
158
+
150
159
- name : Checkout
151
160
uses : actions/checkout@v4
152
161
with :
@@ -162,7 +171,8 @@ jobs:
162
171
163
172
- name : Install yq
164
173
run : |
165
- curl -sL https://github.com/mikefarah/yq/releases/download/v4.42.1/yq_linux_amd64.tar.gz | tar xz && sudo mv yq_linux_amd64 /usr/bin/yq
174
+ ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
175
+ curl -sL "https://github.com/mikefarah/yq/releases/download/v4.42.1/yq_linux_${ARCH}.tar.gz" | tar xz && sudo mv yq_linux_${ARCH} /usr/bin/yq
166
176
167
177
- name : Install Kayobe
168
178
run : |
@@ -211,9 +221,16 @@ jobs:
211
221
continue-on-error : true
212
222
run : |
213
223
args="${{ inputs.regexes }}"
224
+ if [[ "${{ matrix.distro.arch }}" == 'aarch64' ]]; then
225
+ args="$args -e kolla_base_arch=${{ matrix.distro.arch }}"
226
+ fi
214
227
args="$args -e kolla_base_distro=${{ matrix.distro.name }}"
215
228
args="$args -e kolla_base_distro_version=${{ matrix.distro.release }}"
216
- args="$args -e kolla_tag=${{ steps.write-kolla-tag.outputs.kolla-tag }}"
229
+ if [[ "${{ matrix.distro.name }}" == 'rocky' ]]; then
230
+ args="$args -e kolla_tag=${{ steps.write-kolla-tag.outputs.kolla-tag }}-${{ matrix.distro.arch }}"
231
+ else
232
+ args="$args -e kolla_tag=${{ steps.write-kolla-tag.outputs.kolla-tag }}"
233
+ fi
217
234
args="$args -e stackhpc_repo_mirror_auth_proxy_enabled=true"
218
235
source venvs/kayobe/bin/activate &&
219
236
source src/kayobe-config/kayobe-env --environment ci-builder &&
@@ -226,6 +243,10 @@ jobs:
226
243
run : sudo mv /var/log/kolla-build.log image-build-logs/kolla-build-overcloud.log
227
244
if : inputs.overcloud
228
245
246
+ - name : Copy build configs to output directory
247
+ run : sudo cp -rnL /opt/kayobe/etc/kolla/* image-build-logs/
248
+ if : inputs.overcloud
249
+
229
250
- name : Build kolla seed images
230
251
id : build_seed_images
231
252
continue-on-error : true
@@ -239,14 +260,14 @@ jobs:
239
260
kayobe seed container image build $args
240
261
env :
241
262
KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
242
- if : inputs.seed
263
+ if : inputs.seed && matrix.distro.arch == 'amd64'
243
264
244
265
- name : Copy seed container image build logs to output directory
245
266
run : sudo mv /var/log/kolla-build.log image-build-logs/kolla-build-seed.log
246
- if : inputs.seed
267
+ if : inputs.seed && matrix.distro.arch == 'amd64'
247
268
248
269
- name : Get built container images
249
- run : docker image ls --filter "reference=ark.stackhpc.com/stackhpc-dev/*:${{ steps.write-kolla-tag.outputs.kolla-tag }}" > ${{ matrix.distro.name }}-${{ matrix.distro.release }}-container-images
270
+ run : docker image ls --filter "reference=ark.stackhpc.com/stackhpc-dev/*:${{ steps.write-kolla-tag.outputs.kolla-tag }}* " > ${{ matrix.distro.name }}-${{ matrix.distro.release }}-container-images
250
271
251
272
- name : Fail if no images have been built
252
273
run : if [ $(wc -l < ${{ matrix.distro.name }}-${{ matrix.distro.release }}-container-images) -le 1 ]; then exit 1; fi
@@ -307,7 +328,7 @@ jobs:
307
328
- name : Upload output artifact
308
329
uses : actions/upload-artifact@v4
309
330
with :
310
- name : ${{ matrix.distro.name }}-${{ matrix.distro.release }}-logs
331
+ name : ${{ matrix.distro.name }}-${{ matrix.distro.release }}-${{ matrix.distro.arch }}- logs
311
332
path : image-build-logs
312
333
retention-days : 7
313
334
if : ${{ !cancelled() }}
@@ -331,6 +352,117 @@ jobs:
331
352
run : if [ $(wc -l < image-build-logs/image-scan-output/critical-images.txt) -gt 0 ]; then cat image-build-logs/image-scan-output/critical-images.txt && exit 1; fi
332
353
if : ${{ !inputs.push-dirty && !cancelled() }}
333
354
355
+ create-manifests :
356
+ # Only for Rocky Linux for now
357
+ name : Create Multiarch Docker Manifests
358
+ if : github.repository == 'stackhpc/stackhpc-kayobe-config' && inputs.push
359
+ runs-on : ${{ needs.runner-selection.outputs.runner_name_container_image_build }}
360
+ permissions : {}
361
+ needs :
362
+ - container-image-build
363
+ - runner-selection
364
+ steps :
365
+ - name : Install package dependencies
366
+ run : |
367
+ sudo apt update
368
+ sudo apt install -y git unzip python3-wheel python3-pip python3-venv curl jq wget openssh-server openssh-client
369
+ - name : Install gh
370
+ run : |
371
+ sudo mkdir -p -m 755 /etc/apt/keyrings && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null
372
+ sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
373
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
374
+ sudo apt update
375
+ sudo apt install gh -y
376
+ - name : Checkout Kayobe Config
377
+ uses : actions/checkout@v4
378
+ with :
379
+ path : src/kayobe-config
380
+
381
+ - name : Install Kayobe
382
+ run : |
383
+ mkdir -p venvs &&
384
+ pushd venvs &&
385
+ python3 -m venv kayobe &&
386
+ source kayobe/bin/activate &&
387
+ pip install -U pip &&
388
+ pip install -r ../src/kayobe-config/requirements.txt
389
+ # Required for Pulp auth proxy deployment and Docker registry login.
390
+ # Normally installed during host configure.
391
+ - name : Install Docker Python SDK
392
+ run : |
393
+ sudo pip install docker
394
+ - name : Configure localhost as a seed
395
+ run : |
396
+ cat > src/kayobe-config/etc/kayobe/environments/ci-builder/inventory/hosts << EOF
397
+ # A 'seed' host used for building images.
398
+ # Use localhost for container image builds.
399
+ [seed]
400
+ localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3
401
+ EOF
402
+ # See etc/kayobe/ansible/roles/pulp_auth_proxy/README.md for details.
403
+ # NOTE: We override pulp_auth_proxy_conf_path to a path shared by the
404
+ # runner and dind containers.
405
+ - name : Deploy an authenticating package repository mirror proxy
406
+ run : |
407
+ source venvs/kayobe/bin/activate &&
408
+ source src/kayobe-config/kayobe-env --environment ci-builder &&
409
+ kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/pulp-auth-proxy.yml -e pulp_auth_proxy_conf_path=/home/runner/_work/pulp_proxy
410
+ env :
411
+ KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
412
+
413
+ - name : Download artifacts
414
+ uses : actions/download-artifact@v4
415
+
416
+ - name : Combine pushed images lists
417
+ run : |
418
+ find . -name 'push-attempt-images.txt' -exec cat {} + > all-pushed-images.txt
419
+ - name : Log in to Docker registry
420
+ run : |
421
+ source venvs/kayobe/bin/activate &&
422
+ source src/kayobe-config/kayobe-env --environment ci-builder &&
423
+ kayobe playbook run ${KAYOBE_CONFIG_PATH}/ansible/docker-registry-login.yml
424
+ env :
425
+ KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
426
+
427
+ - name : Create and Push Docker Manifests
428
+ run : |
429
+ set -ex
430
+ mkdir -p logs
431
+ images=$(cat all-pushed-images.txt | sort | uniq)
432
+ # Filter out Ubuntu and Rocky Bifrost images
433
+ manifest_images=$(echo "$images" | grep -E '.*-(amd64|aarch64)$' | sed -E 's/-(amd64|aarch64)$//' | sort | uniq)
434
+ if [ -z "$manifest_images" ]; then
435
+ echo "No Rocky overcloud images found. Skipping manifest creation." | tee -a logs/manifest-creation.log
436
+ exit 0
437
+ fi
438
+ for base_image in $manifest_images; do
439
+ arch_images=""
440
+ for arch in amd64 aarch64; do
441
+ arch_image="${base_image}-${arch}"
442
+ # Check if the image exists in the registry
443
+ if docker manifest inspect "$arch_image" > /dev/null 2>&1; then
444
+ arch_images="$arch_images $arch_image"
445
+ fi
446
+ done
447
+ if [ -n "$arch_images" ]; then
448
+ echo "Creating manifest for $base_image with images:$arch_images" | tee -a logs/manifest-creation.log
449
+ docker manifest create "$base_image" $arch_images | tee -a logs/manifest-creation.log
450
+ docker manifest push "$base_image" | tee -a logs/manifest-creation.log
451
+ else
452
+ echo "No images found for $base_image, skipping." | tee -a logs/manifest-creation.log
453
+ fi
454
+ done
455
+
456
+ - name : Upload manifest logs
457
+ uses : actions/upload-artifact@v4
458
+ with :
459
+ name : manifest-logs
460
+ path : |
461
+ all-pushed-images.txt
462
+ logs/manifest-creation.log
463
+ retention-days : 7
464
+ if : ${{ !cancelled() }}
465
+
334
466
# NOTE(mgoddard): Trigger another CI workflow in the
335
467
# stackhpc-release-train repository.
336
468
- name : Trigger container image repository sync
0 commit comments