@@ -94,18 +94,21 @@ jobs:
9494 # Dynamically define job matrix.
9595 # We need a separate matrix entry for each distribution, when the relevant input is true.
9696 # 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
9799 - name : Generate build matrix
98100 id : set-matrix
99101 run : |
100102 output="{'distro': ["
101103 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'},"
103106 fi
104107 if [[ ${{ inputs.ubuntu-jammy }} == 'true' ]]; then
105- output+="{'name': 'ubuntu', 'release': 'jammy'},"
108+ output+="{'name': 'ubuntu', 'release': 'jammy', 'arch': 'amd64' },"
106109 fi
107110 if [[ ${{ inputs.ubuntu-noble }} == 'true' ]]; then
108- output+="{'name': 'ubuntu', 'release': 'noble'},"
111+ output+="{'name': 'ubuntu', 'release': 'noble', 'arch': 'amd64' },"
109112 fi
110113 # remove trailing comma
111114 output="${output%,}"
@@ -124,7 +127,9 @@ jobs:
124127 container-image-build :
125128 name : Build Kolla container images
126129 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 }}
128133 timeout-minutes : 720
129134 permissions : {}
130135 strategy :
@@ -147,6 +152,10 @@ jobs:
147152 sudo apt update
148153 sudo apt install gh -y
149154
155+ - name : Purge workspace (Arm runner only)
156+ if : runner.arch == 'ARM64'
157+ run : sudo rm -rf "$GITHUB_WORKSPACE"/*
158+
150159 - name : Checkout
151160 uses : actions/checkout@v4
152161 with :
@@ -162,7 +171,8 @@ jobs:
162171
163172 - name : Install yq
164173 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
166176
167177 - name : Install Kayobe
168178 run : |
@@ -211,9 +221,16 @@ jobs:
211221 continue-on-error : true
212222 run : |
213223 args="${{ inputs.regexes }}"
224+ if [[ "${{ matrix.distro.arch }}" == 'aarch64' ]]; then
225+ args="$args -e kolla_base_arch=${{ matrix.distro.arch }}"
226+ fi
214227 args="$args -e kolla_base_distro=${{ matrix.distro.name }}"
215228 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
217234 args="$args -e stackhpc_repo_mirror_auth_proxy_enabled=true"
218235 source venvs/kayobe/bin/activate &&
219236 source src/kayobe-config/kayobe-env --environment ci-builder &&
@@ -226,6 +243,10 @@ jobs:
226243 run : sudo mv /var/log/kolla-build.log image-build-logs/kolla-build-overcloud.log
227244 if : inputs.overcloud
228245
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+
229250 - name : Build kolla seed images
230251 id : build_seed_images
231252 continue-on-error : true
@@ -239,14 +260,14 @@ jobs:
239260 kayobe seed container image build $args
240261 env :
241262 KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
242- if : inputs.seed
263+ if : inputs.seed && matrix.distro.arch == 'amd64'
243264
244265 - name : Copy seed container image build logs to output directory
245266 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'
247268
248269 - 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
250271
251272 - name : Fail if no images have been built
252273 run : if [ $(wc -l < ${{ matrix.distro.name }}-${{ matrix.distro.release }}-container-images) -le 1 ]; then exit 1; fi
@@ -307,7 +328,7 @@ jobs:
307328 - name : Upload output artifact
308329 uses : actions/upload-artifact@v4
309330 with :
310- name : ${{ matrix.distro.name }}-${{ matrix.distro.release }}-logs
331+ name : ${{ matrix.distro.name }}-${{ matrix.distro.release }}-${{ matrix.distro.arch }}- logs
311332 path : image-build-logs
312333 retention-days : 7
313334 if : ${{ !cancelled() }}
@@ -331,6 +352,121 @@ jobs:
331352 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
332353 if : ${{ !inputs.push-dirty && !cancelled() }}
333354
355+ - name : Prune Docker cache on ARM runner
356+ if : always() && runner.arch == 'ARM64'
357+ run : docker system prune -af
358+
359+ create-manifests :
360+ # Only for Rocky Linux for now
361+ name : Create Multiarch Docker Manifests
362+ if : github.repository == 'stackhpc/stackhpc-kayobe-config' && inputs.push
363+ runs-on : ${{ needs.runner-selection.outputs.runner_name_container_image_build }}
364+ permissions : {}
365+ needs :
366+ - container-image-build
367+ - runner-selection
368+ steps :
369+ - name : Install package dependencies
370+ run : |
371+ sudo apt update
372+ sudo apt install -y git unzip python3-wheel python3-pip python3-venv curl jq wget openssh-server openssh-client
373+ - name : Install gh
374+ run : |
375+ 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
376+ sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
377+ 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
378+ sudo apt update
379+ sudo apt install gh -y
380+ - name : Checkout Kayobe Config
381+ uses : actions/checkout@v4
382+ with :
383+ path : src/kayobe-config
384+
385+ - name : Install Kayobe
386+ run : |
387+ mkdir -p venvs &&
388+ pushd venvs &&
389+ python3 -m venv kayobe &&
390+ source kayobe/bin/activate &&
391+ pip install -U pip &&
392+ pip install -r ../src/kayobe-config/requirements.txt
393+ # Required for Pulp auth proxy deployment and Docker registry login.
394+ # Normally installed during host configure.
395+ - name : Install Docker Python SDK
396+ run : |
397+ sudo pip install docker
398+ - name : Configure localhost as a seed
399+ run : |
400+ cat > src/kayobe-config/etc/kayobe/environments/ci-builder/inventory/hosts << EOF
401+ # A 'seed' host used for building images.
402+ # Use localhost for container image builds.
403+ [seed]
404+ localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3
405+ EOF
406+ # See etc/kayobe/ansible/roles/pulp_auth_proxy/README.md for details.
407+ # NOTE: We override pulp_auth_proxy_conf_path to a path shared by the
408+ # runner and dind containers.
409+ - name : Deploy an authenticating package repository mirror proxy
410+ run : |
411+ source venvs/kayobe/bin/activate &&
412+ source src/kayobe-config/kayobe-env --environment ci-builder &&
413+ kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/pulp-auth-proxy.yml -e pulp_auth_proxy_conf_path=/home/runner/_work/pulp_proxy
414+ env :
415+ KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
416+
417+ - name : Download artifacts
418+ uses : actions/download-artifact@v4
419+
420+ - name : Combine pushed images lists
421+ run : |
422+ find . -name 'push-attempt-images.txt' -exec cat {} + > all-pushed-images.txt
423+ - name : Log in to Docker registry
424+ run : |
425+ source venvs/kayobe/bin/activate &&
426+ source src/kayobe-config/kayobe-env --environment ci-builder &&
427+ kayobe playbook run ${KAYOBE_CONFIG_PATH}/ansible/docker-registry-login.yml
428+ env :
429+ KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
430+
431+ - name : Create and Push Docker Manifests
432+ run : |
433+ set -ex
434+ mkdir -p logs
435+ images=$(cat all-pushed-images.txt | sort | uniq)
436+ # Filter out Ubuntu and Rocky Bifrost images
437+ manifest_images=$(echo "$images" | grep -E '.*-(amd64|aarch64)$' | sed -E 's/-(amd64|aarch64)$//' | sort | uniq)
438+ if [ -z "$manifest_images" ]; then
439+ echo "No Rocky overcloud images found. Skipping manifest creation." | tee -a logs/manifest-creation.log
440+ exit 0
441+ fi
442+ for base_image in $manifest_images; do
443+ arch_images=""
444+ for arch in amd64 aarch64; do
445+ arch_image="${base_image}-${arch}"
446+ # Check if the image exists in the registry
447+ if docker manifest inspect "$arch_image" > /dev/null 2>&1; then
448+ arch_images="$arch_images $arch_image"
449+ fi
450+ done
451+ if [ -n "$arch_images" ]; then
452+ echo "Creating manifest for $base_image with images:$arch_images" | tee -a logs/manifest-creation.log
453+ docker manifest create "$base_image" $arch_images | tee -a logs/manifest-creation.log
454+ docker manifest push "$base_image" | tee -a logs/manifest-creation.log
455+ else
456+ echo "No images found for $base_image, skipping." | tee -a logs/manifest-creation.log
457+ fi
458+ done
459+
460+ - name : Upload manifest logs
461+ uses : actions/upload-artifact@v4
462+ with :
463+ name : manifest-logs
464+ path : |
465+ all-pushed-images.txt
466+ logs/manifest-creation.log
467+ retention-days : 7
468+ if : ${{ !cancelled() }}
469+
334470 # NOTE(mgoddard): Trigger another CI workflow in the
335471 # stackhpc-release-train repository.
336472 - name : Trigger container image repository sync
0 commit comments