From dea0cbb482932237f05d43fb58c3dba9c5311e29 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Thu, 20 Nov 2025 09:21:30 -0800 Subject: [PATCH 1/5] X-Smart-Branch-Parent: main From 4067ff65c1d8529e45a3485a867bf41c93f87692 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Thu, 20 Nov 2025 09:21:26 -0800 Subject: [PATCH 2/5] X-Smart-Squash: Squashed 26 commits: 4829124 Add arm64 build and test images 591a0a4 matrix f308f72 format 2bd6ed1 arm runners c874046 include 029d72f failfastfalse d088cd2 arch tags c02366d create multiarch manifest 254e179 space 782ab48 handle 5432a37 fix 14f0332 target 2cfd390 flip 48f9992 amd64 01eddcb push arch 9a6b3ff quotes 407c401 update 4e30669 - 5e4456d flav 439998c order dd0bbdd use TARGETARCH instead of uname -m 0f6a1ea Update pylint versions 245511b Apply suggestions from code review 93fa297 fix format d6827c7 oc version e7836f2 PR comment: don't write arch.env file --- .../actions/build-and-push-image/action.yaml | 7 +- .../build-and-push-image.sh | 13 +- .../create-multiarch-manifest/action.yml | 37 +++++ .github/workflows/build.yaml | 133 +++++++++++++++--- Makefile | 20 ++- images/stackrox-build.Dockerfile | 32 +++-- images/stackrox-test.Dockerfile | 114 +++++++++------ 7 files changed, 274 insertions(+), 82 deletions(-) create mode 100644 .github/actions/create-multiarch-manifest/action.yml diff --git a/.github/actions/build-and-push-image/action.yaml b/.github/actions/build-and-push-image/action.yaml index 7c31d33f..614b9b0b 100644 --- a/.github/actions/build-and-push-image/action.yaml +++ b/.github/actions/build-and-push-image/action.yaml @@ -4,6 +4,9 @@ inputs: image-flavor: description: A flavor used to tag the apollo-ci image. required: true + arch: + description: Arch for image build (amd64 or arm64) + required: true outputs: image-tag: description: The full image tag that was built and pushed @@ -11,9 +14,9 @@ outputs: runs: using: composite steps: - - name: Build and push image + - name: Build and push ${{ inputs.arch }} image id: build-and-push run: | .github/actions/build-and-push-image/build-and-push-image.sh \ - "${{ inputs.image-flavor }}" + "${{ inputs.image-flavor }}" "${{ inputs.arch }}" shell: bash diff --git a/.github/actions/build-and-push-image/build-and-push-image.sh b/.github/actions/build-and-push-image/build-and-push-image.sh index 30f48f07..9bc11e59 100755 --- a/.github/actions/build-and-push-image/build-and-push-image.sh +++ b/.github/actions/build-and-push-image/build-and-push-image.sh @@ -4,13 +4,22 @@ set -euo pipefail build_and_push_image() { local image_flavor="$1" + local target_arch="$2" + local tag_suffix="" + + # Default to amd64 if no architecture specified (backward compatibility) + if [ -z "${target_arch}" ]; then + target_arch="amd64" + else + tag_suffix="-${target_arch}" + fi docker login -u "$QUAY_STACKROX_IO_RW_USERNAME" --password-stdin <<<"$QUAY_STACKROX_IO_RW_PASSWORD" quay.io - TAG="$(scripts/get_tag.sh "${image_flavor}")" + TAG="$(scripts/get_tag.sh "$image_flavor")${tag_suffix}" IMAGE="quay.io/stackrox-io/apollo-ci:${TAG}" - make "${image_flavor}-image" + make TARGETARCH="$target_arch" "$image_flavor"-image retry 5 true docker push "${IMAGE}" diff --git a/.github/actions/create-multiarch-manifest/action.yml b/.github/actions/create-multiarch-manifest/action.yml new file mode 100644 index 00000000..c62b3ede --- /dev/null +++ b/.github/actions/create-multiarch-manifest/action.yml @@ -0,0 +1,37 @@ +name: Create and push a multiarch manifest +description: | + This action will create a multiarch manifest and push it to a remote registry. + +inputs: + base-image: + description: + The base image to used for the manifest + required: true + image-flavor: + description: + The image flavor tag to be used for the manifest + required: true + suffix: + description: + Optional suffix for the tags used and the manifest + default: '' + archs: + description: + Architectures to be included in the final manifest, separated by a space + default: 'amd64 arm64' +runs: + using: composite + steps: + - shell: bash + run: | + image_flavor="${{ inputs.image-flavor }}" + tag="$(scripts/get_tag.sh ${image_flavor})" + read -ra archs <<< "${{ inputs.archs }}" + declare -a images=() + for arch in "${archs[@]}"; do + images+=("${{ inputs.base-image }}:${tag}-${arch}${{ inputs.suffix }}") + done + + docker manifest create "${{ inputs.base-image }}:${tag}${{ inputs.suffix }}" "${images[@]}" + docker manifest push "${{ inputs.base-image }}:${tag}${{ inputs.suffix }}" + diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 25472a3f..30e14c2e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,13 +15,110 @@ env: jobs: - build-and-push-builder-images: + # Multi-architecture builds for core StackRox images + build-and-push-stackrox-build: + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: ubuntu-24.04 + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - uses: ./.github/actions/build-and-push-image + id: build-and-push-image + with: + image-flavor: "stackrox-build" + arch: ${{ matrix.arch }} + - name: Save image info + run: | + mkdir -p image-info + echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/stackrox-build-${{ matrix.arch }}.txt" + - name: Upload image info + uses: actions/upload-artifact@v4 + with: + name: image-info-stackrox-build-${{ matrix.arch }} + path: image-info/stackrox-build-${{ matrix.arch }}.txt + retention-days: 1 + + build-and-push-stackrox-test: + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: ubuntu-24.04 + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + needs: + - build-and-push-stackrox-build + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - uses: ./.github/actions/build-and-push-image + id: build-and-push-image + with: + image-flavor: "stackrox-test" + arch: ${{ matrix.arch }} + - name: Save image info + run: | + mkdir -p image-info + echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/stackrox-test-${{ matrix.arch }}.txt" + - name: Upload image info + uses: actions/upload-artifact@v4 + with: + name: image-info-stackrox-test-${{ matrix.arch }} + path: image-info/stackrox-test-${{ matrix.arch }}.txt + retention-days: 1 + + # Create multi-architecture manifests + build-and-push-multiarch: + runs-on: ubuntu-latest + needs: + - build-and-push-stackrox-build + - build-and-push-stackrox-test + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: Login to quay.io/stackrox-io + uses: docker/login-action@v3 + with: + registry: quay.io + username: ${{ secrets.QUAY_STACKROX_IO_RW_USERNAME }} + password: ${{ secrets.QUAY_STACKROX_IO_RW_PASSWORD }} + + - uses: ./.github/actions/create-multiarch-manifest + with: + base-image: quay.io/stackrox-io/apollo-ci + image-flavor: stackrox-build + + - uses: ./.github/actions/create-multiarch-manifest + with: + base-image: quay.io/stackrox-io/apollo-ci + image-flavor: stackrox-test + + # Single-architecture builds for other images + build-and-push-single-arch-images: runs-on: ubuntu-latest strategy: matrix: image-flavor: - scanner-build - - stackrox-build - stackrox-ui-test - jenkins-plugin fail-fast: false @@ -35,6 +132,7 @@ jobs: id: build-and-push-image with: image-flavor: "${{ matrix.image-flavor }}" + arch: "amd64" - name: Save image info run: | mkdir -p image-info @@ -46,15 +144,10 @@ jobs: path: image-info/${{ matrix.image-flavor }}.txt retention-days: 1 - build-and-push-test-images: - needs: build-and-push-builder-images + build-and-push-scanner-test: runs-on: ubuntu-latest - strategy: - matrix: - image-flavor: - - stackrox-test - - scanner-test - fail-fast: false + needs: + - build-and-push-single-arch-images steps: - name: Checkout uses: actions/checkout@v3 @@ -64,23 +157,24 @@ jobs: - uses: ./.github/actions/build-and-push-image id: build-and-push-image with: - image-flavor: "${{ matrix.image-flavor }}" + image-flavor: "scanner-test" + arch: "amd64" - name: Save image info run: | mkdir -p image-info - echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/${{ matrix.image-flavor }}.txt" + echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/scanner-test.txt" - name: Upload image info uses: actions/upload-artifact@v4 with: - name: image-info-${{ matrix.image-flavor }} - path: image-info/${{ matrix.image-flavor }}.txt + name: image-info-scanner-test + path: image-info/scanner-test.txt retention-days: 1 test-cci-export: runs-on: ubuntu-latest needs: - - build-and-push-builder-images - - build-and-push-test-images + - build-and-push-single-arch-images + - build-and-push-scanner-test steps: - name: Checkout uses: actions/checkout@v3 @@ -95,8 +189,11 @@ jobs: comment-build-images: runs-on: ubuntu-latest needs: - - build-and-push-builder-images - - build-and-push-test-images + - build-and-push-stackrox-build + - build-and-push-stackrox-test + - build-and-push-multiarch + - build-and-push-single-arch-images + - build-and-push-scanner-test steps: - name: Download all image info artifacts uses: actions/download-artifact@v4 diff --git a/Makefile b/Makefile index e101256c..85bb1f52 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,22 @@ endif QUAY_REPO=stackrox-io STACKROX_BUILD_TAG=$(shell scripts/get_tag.sh "stackrox-build") +TARGETARCH?=amd64 + +ifeq ($(TARGETARCH),amd64) + TARGETARCH_ALT = x86_64 +else ifeq ($(TARGETARCH),arm64) + TARGETARCH_ALT = aarch64 +else + TARGETARCH_ALT = $(TARGETARCH) +endif .PHONY: stackrox-build-image stackrox-build-image: $(DOCKER) build \ - --platform linux/amd64 \ + --platform linux/$(TARGETARCH) \ -t quay.io/$(QUAY_REPO)/apollo-ci:$(STACKROX_BUILD_TAG) \ + -t quay.io/$(QUAY_REPO)/apollo-ci:$(STACKROX_BUILD_TAG)-$(TARGETARCH) \ -f images/stackrox-build.Dockerfile \ images/ @@ -18,9 +28,11 @@ STACKROX_TEST_TAG=$(shell scripts/get_tag.sh "stackrox-test") .PHONY: stackrox-test-image stackrox-test-image: $(DOCKER) build \ - --platform linux/amd64 \ + --platform linux/$(TARGETARCH) \ -t quay.io/$(QUAY_REPO)/apollo-ci:$(STACKROX_TEST_TAG) \ - --build-arg BASE_TAG=$(STACKROX_BUILD_TAG) \ + -t quay.io/$(QUAY_REPO)/apollo-ci:$(STACKROX_TEST_TAG)-$(TARGETARCH) \ + --build-arg BASE_TAG=$(STACKROX_BUILD_TAG)-$(TARGETARCH) \ + --build-arg TARGETARCH_ALT=$(TARGETARCH_ALT) \ -f images/stackrox-test.Dockerfile \ images/ @@ -40,7 +52,7 @@ test-cci-export: $(DOCKER) build \ --platform linux/amd64 \ -t test-cci-export \ - --build-arg BASE_TAG=$(STACKROX_TEST_TAG) \ + --build-arg BASE_TAG=$(STACKROX_TEST_TAG)-amd64 \ -f images/test.cci-export.Dockerfile \ images/ $(DOCKER) run \ diff --git a/images/stackrox-build.Dockerfile b/images/stackrox-build.Dockerfile index 477493e5..5dc547af 100644 --- a/images/stackrox-build.Dockerfile +++ b/images/stackrox-build.Dockerfile @@ -2,6 +2,8 @@ FROM registry.access.redhat.com/ubi8:latest +ARG TARGETARCH + SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN touch /i-am-rox-ci-image @@ -56,27 +58,37 @@ RUN dnf update -y && \ rm -rf /var/cache/dnf /var/cache/yum ARG GOLANG_VERSION=1.24.4 -ARG GOLANG_SHA256=77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717 -ENV GOPATH /go -ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH -RUN url="https://dl.google.com/go/go${GOLANG_VERSION}.linux-amd64.tar.gz" && \ - wget --no-verbose -O go.tgz "$url" && \ +ENV GOPATH=/go +ENV PATH=$GOPATH/bin:/usr/local/go/bin:$PATH +RUN set -e; case "$TARGETARCH" in \ + "amd64" ) GOLANG_SHA256="77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717";; \ + "arm64") GOLANG_SHA256="d5501ee5aca0f258d5fe9bfaed401958445014495dc115f202d43d5210b45241";; \ + *) echo "Unsupported $TARGETARCH"; exit 1;; \ + esac && \ + wget --no-verbose -O go.tgz "https://dl.google.com/go/go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz" && \ echo "${GOLANG_SHA256} *go.tgz" | sha256sum -c - && \ tar -C /usr/local -xzf go.tgz && \ rm go.tgz && \ mkdir -p "$GOPATH/src" "$GOPATH/bin" && \ chmod -R 777 "$GOPATH" -ARG FETCH_VERSION=0.3.5 -ARG FETCH_SHA256=8d4d99e903b30dbd24290e9a056a982ea2326a05ded24c63be64df16e7e0d9f0 -RUN wget --no-verbose -O fetch https://github.com/gruntwork-io/fetch/releases/download/v${FETCH_VERSION}/fetch_linux_amd64 && \ +ARG FETCH_VERSION=0.4.6 +RUN set -e; case "$TARGETARCH" in \ + "amd64" ) FETCH_SHA256="a67ed3141d6deb7e7841f40505cba11eb7a37abbab78374712a42373e7854209";; \ + "arm64") FETCH_SHA256="4b9115a1f1a90c7088bff9ffc7d2de3547ef1d21709528e878af09a4c348dea3";; \ + *) echo "Unsupported $TARGETARCH"; exit 1;; \ + esac && \ + wget --no-verbose -O fetch https://github.com/gruntwork-io/fetch/releases/download/v${FETCH_VERSION}/fetch_linux_${TARGETARCH} && \ echo "${FETCH_SHA256} fetch" | sha256sum -c - && \ install fetch /usr/bin && \ rm fetch ARG OSSLS_VERSION=0.11.1 -ARG OSSLS_SHA256=f1bf3012961c1d90ba307a46263f29025028d35c209b9a65e5c7d502c470c95f -RUN fetch --repo="https://github.com/stackrox/ossls" --tag="${OSSLS_VERSION}" --release-asset="ossls_linux_amd64" . && \ +RUN set -e; case "$TARGETARCH" in \ + "amd64" ) OSSLS_SHA256="f1bf3012961c1d90ba307a46263f29025028d35c209b9a65e5c7d502c470c95f";; \ + *) echo "Unsupported $TARGETARCH, skipping."; exit 0;; \ + esac && \ + fetch --repo="https://github.com/stackrox/ossls" --tag="${OSSLS_VERSION}" --release-asset="ossls_linux_amd64" . && \ echo "${OSSLS_SHA256} *ossls_linux_amd64" | sha256sum -c - && \ install ossls_linux_amd64 /usr/bin/ossls && \ rm ossls_linux_amd64 && \ diff --git a/images/stackrox-test.Dockerfile b/images/stackrox-test.Dockerfile index c585a1d4..11defc35 100644 --- a/images/stackrox-test.Dockerfile +++ b/images/stackrox-test.Dockerfile @@ -1,8 +1,15 @@ # Provides the tooling required to build StackRox images and test StackRox # binaries and images. Builds upon stackrox-build.Dockerfile. - ARG BASE_TAG -FROM quay.io/stackrox-io/apollo-ci:${BASE_TAG} as base +FROM docker:28.0.0 AS static-docker-source + +FROM quay.io/stackrox-io/apollo-ci:${BASE_TAG} AS base + +ARG TARGETARCH +ARG TARGETARCH_ALT + +COPY --from=static-docker-source /usr/local/bin/docker /usr/local/bin/docker +COPY --from=static-docker-source /usr/local/libexec/docker/cli-plugins/docker-buildx /usr/local/libexec/docker/cli-plugins/docker-buildx # This line makes sure that piped commands in RUN instructions exit early. # This should not affect use in CircleCI because Circle doesn't use @@ -23,8 +30,21 @@ RUN set -ex \ # an initial BASH_ENV as a foundation for cci-export(). ENV BASH_ENV /etc/initial-bash.env +# Install cloud-sdk repo from https://cloud.google.com/sdk/docs/install#rpm, which +# is not configured by default on arm64 +RUN set -ex \ + && cat < /etc/yum.repos.d/google-cloud-sdk.repo +[google-cloud-cli] +name=Google Cloud CLI +baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-${TARGETARCH_ALT} +enabled=1 +gpgcheck=1 +repo_gpgcheck=0 +gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg +EOF + # Install Postgres repo -RUN dnf --disablerepo="*" install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm +RUN dnf --disablerepo="*" install -y "https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-${TARGETARCH_ALT}/pgdg-redhat-repo-latest.noarch.rpm" # Install all the packages RUN dnf update -y \ @@ -39,7 +59,7 @@ RUN dnf update -y \ lsof \ lz4 \ openssl \ - python3-devel \ + python3.12-devel python3.12-setuptools python3.12-pip \ unzip \ xmlstarlet \ xz \ @@ -51,6 +71,11 @@ RUN dnf update -y \ && dnf clean all \ && rm -rf /var/cache/dnf /var/cache/yum +## Symlink python to python3 +RUN update-alternatives --install /usr/bin/pip3 pip3 /usr/bin/pip3.12 1 +RUN update-alternatives --install /usr/bin/pip-3 pip-3 /usr/bin/pip3.12 1 +RUN ln -s /usr/bin/python3.12 /usr/bin/python + # Use updated auth plugin for GCP ENV USE_GKE_GCLOUD_AUTH_PLUGIN=True RUN gke-gcloud-auth-plugin --version @@ -60,25 +85,15 @@ RUN set -ex \ && npm install -g bats@1.10.0 bats-support@0.3.0 bats-assert@2.0.0 tap-junit \ && bats -v -# Install docker binary -ARG DOCKER_VERSION=20.10.6 -RUN set -ex \ - && DOCKER_URL="https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz" \ - && echo Docker URL: $DOCKER_URL \ - && wget --no-verbose -O /tmp/docker.tgz "${DOCKER_URL}" \ - && ls -lha /tmp/docker.tgz \ - && tar -xz -C /tmp -f /tmp/docker.tgz \ - && install /tmp/docker/docker /usr/local/bin \ - && rm -rf /tmp/docker /tmp/docker.tgz \ - && command -v docker \ - && (docker version --format '{{.Client.Version}}' || true) - - # Symlink python to python3 - RUN ln -s /usr/bin/python3 /usr/bin/python - -# oc -RUN set -ex \ - && wget --no-verbose -O oc.tgz https://github.com/okd-project/okd/releases/download/4.11.0-0.okd-2022-12-02-145640/openshift-client-linux-4.11.0-0.okd-2022-12-02-145640.tar.gz \ +# Install oc +ARG OC_VERSION=4.11.0-0.okd-2023-01-14-152430 +RUN set -e; \ + case "$TARGETARCH" in \ + "amd64") OC_ARCH="";; \ + "arm64") OC_ARCH="arm64-";; \ + *) echo "Unsupported $TARGETARCH"; exit 1;; \ + esac \ + && wget --no-verbose -O oc.tgz https://github.com/okd-project/okd/releases/download/${OC_VERSION}/openshift-client-linux-${OC_ARCH}${OC_VERSION}.tar.gz \ && mkdir "oc-dir" \ && tar -C "oc-dir" -xf oc.tgz \ && install oc-dir/oc /usr/local/bin \ @@ -87,10 +102,10 @@ RUN set -ex \ # helm RUN set -ex \ - && wget --no-verbose -O helm.tgz https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz \ + && wget --no-verbose -O helm.tgz https://get.helm.sh/helm-v3.11.2-linux-${TARGETARCH}.tar.gz \ && tar -xf helm.tgz \ - && install linux-amd64/helm /usr/local/bin \ - && rm -rf helm.tgz linux-amd64 \ + && install linux-${TARGETARCH}/helm /usr/local/bin \ + && rm -rf helm.tgz linux-${TARGETARCH} \ && command -v helm # Install gradle @@ -106,8 +121,7 @@ RUN set -ex \ && command -v gradle # Install aws cli -RUN set -ex \ - && wget --no-verbose -O "awscliv2.zip" "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-2.7.17.zip" \ +RUN wget --no-verbose -O "awscliv2.zip" "https://awscli.amazonaws.com/awscli-exe-linux-${TARGETARCH_ALT}-2.7.17.zip" \ && unzip awscliv2.zip \ && ./aws/install \ && rm awscliv2.zip \ @@ -116,13 +130,15 @@ RUN set -ex \ # Install yq v4.16.2 RUN set -ex \ - && wget --no-verbose "https://github.com/mikefarah/yq/releases/download/v4.16.2/yq_linux_amd64" \ - && sha256sum --check --status <<< "5c911c4da418ae64af5527b7ee36e77effb85de20c2ce732ed14c7f72743084d yq_linux_amd64" \ - && mv yq_linux_amd64 /usr/bin/yq \ + && wget --no-verbose "https://github.com/mikefarah/yq/releases/download/v4.16.2/yq_linux_${TARGETARCH}" \ + && mv yq_linux_${TARGETARCH} /usr/bin/yq \ && chmod +x /usr/bin/yq # Install hub-comment -RUN set -ex \ +RUN set -ex; case "$TARGETARCH" in \ + "amd64");; \ + *) echo "Unsupported ${TARGETARCH}, skipping."; exit 0;; \ + esac \ && wget --quiet https://github.com/joshdk/hub-comment/releases/download/0.1.0-rc6/hub-comment_linux_amd64 \ && sha256sum --check --status <<< "2a2640f44737873dfe30da0d5b8453419d48a494f277a70fd9108e4204fc4a53 hub-comment_linux_amd64" \ && mv hub-comment_linux_amd64 /usr/bin/hub-comment \ @@ -130,33 +146,39 @@ RUN set -ex \ # Install shellcheck ARG SHELLCHECK_VERSION=0.10.0 -ARG SHELLCHECK_SHA256=6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87 -RUN set -ex \ - && wget --quiet "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ - && sha256sum --check --status <<< "${SHELLCHECK_SHA256} shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ - && tar -xJf "shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ +RUN set -ex; case "$TARGETARCH" in \ + "amd64") SHELLCHECK_SHA256="6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87";; \ + "arm64") SHELLCHECK_SHA256="324a7e89de8fa2aed0d0c28f3dab59cf84c6d74264022c00c22af665ed1a09bb";; \ + *) echo "Unsupported $TARGETARCH"; exit 1;; \ + esac \ + && wget --quiet "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.${TARGETARCH_ALT}.tar.xz" \ + && sha256sum --check --status <<< "${SHELLCHECK_SHA256} shellcheck-v${SHELLCHECK_VERSION}.linux.${TARGETARCH_ALT}.tar.xz" \ + && tar -xJf "shellcheck-v${SHELLCHECK_VERSION}.linux.${TARGETARCH_ALT}.tar.xz" \ && cp "shellcheck-v${SHELLCHECK_VERSION}/shellcheck" /usr/bin/shellcheck \ - && rm "shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ + && rm "shellcheck-v${SHELLCHECK_VERSION}.linux.${TARGETARCH_ALT}.tar.xz" \ && rm -rf "shellcheck-v${SHELLCHECK_VERSION}" \ && shellcheck --version # Install hashicorp vault ARG VAULT_VERSION=1.12.1 -ARG VAULT_SHA256=839fa81eacd250e0b0298e518751a792cd5d7194650af78cf5da74d7b7b1e5fb -RUN set -ex \ - && wget --quiet "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip" \ - && sha256sum --check --status <<< "${VAULT_SHA256} vault_${VAULT_VERSION}_linux_amd64.zip" \ - && unzip "vault_${VAULT_VERSION}_linux_amd64.zip" \ +RUN set -ex; case "$TARGETARCH" in \ + "amd64") VAULT_SHA256="839fa81eacd250e0b0298e518751a792cd5d7194650af78cf5da74d7b7b1e5fb";; \ + "arm64") VAULT_SHA256="f583cdd21ed1fdc99ec50f5400e79ebc723ed3ce92d2d1d42490cff9143ed693";; \ + *) echo "Unsupported $TARGETARCH"; exit 1;; \ + esac \ + && wget --quiet "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip" \ + && sha256sum --check --status <<< "${VAULT_SHA256} vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip" \ + && unzip "vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip" \ && strip "vault" \ && mv "vault" /usr/bin/vault \ - && rm "vault_${VAULT_VERSION}_linux_amd64.zip" \ + && rm "vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip" \ && vault --version # Add python development tooling. If these versions have to change check for # dependent repos. e.g. stackrox/stackrox has .openshift-ci/dev-requirements.txt # for local development style & lint. -ARG PYCODESTYLE_VERSION=2.10.0 -ARG PYLINT_VERSION=2.13.9 +ARG PYCODESTYLE_VERSION=2.13.0 +ARG PYLINT_VERSION=3.3.7 RUN set -ex \ && pip3 install pycodestyle=="${PYCODESTYLE_VERSION}" \ pylint=="${PYLINT_VERSION}" From 483d8546d3221f06800f05ea0ac6c6e177576488 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Thu, 20 Nov 2025 09:41:31 -0800 Subject: [PATCH 3/5] fix single arch tagging --- .github/actions/build-and-push-image/action.yaml | 4 ++-- .github/actions/build-and-push-image/build-and-push-image.sh | 2 +- .github/workflows/build.yaml | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/actions/build-and-push-image/action.yaml b/.github/actions/build-and-push-image/action.yaml index 614b9b0b..eb1d5748 100644 --- a/.github/actions/build-and-push-image/action.yaml +++ b/.github/actions/build-and-push-image/action.yaml @@ -5,8 +5,8 @@ inputs: description: A flavor used to tag the apollo-ci image. required: true arch: - description: Arch for image build (amd64 or arm64) - required: true + description: Arch for image build (amd64 or arm64). Leave empty for single-arch amd64 mode without suffix. + required: false outputs: image-tag: description: The full image tag that was built and pushed diff --git a/.github/actions/build-and-push-image/build-and-push-image.sh b/.github/actions/build-and-push-image/build-and-push-image.sh index 9bc11e59..0026b87a 100755 --- a/.github/actions/build-and-push-image/build-and-push-image.sh +++ b/.github/actions/build-and-push-image/build-and-push-image.sh @@ -7,7 +7,7 @@ build_and_push_image() { local target_arch="$2" local tag_suffix="" - # Default to amd64 if no architecture specified (backward compatibility) + # Default to amd64 if no architecture specified and do not add arch suffix. if [ -z "${target_arch}" ]; then target_arch="amd64" else diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 30e14c2e..4ea65930 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -132,7 +132,6 @@ jobs: id: build-and-push-image with: image-flavor: "${{ matrix.image-flavor }}" - arch: "amd64" - name: Save image info run: | mkdir -p image-info From f83eb7e84482b2794a4dfd385aa71353e1ef102a Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Thu, 20 Nov 2025 13:27:48 -0800 Subject: [PATCH 4/5] single arch for scanner test image --- .github/workflows/build.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4ea65930..e969e8e2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -157,7 +157,6 @@ jobs: id: build-and-push-image with: image-flavor: "scanner-test" - arch: "amd64" - name: Save image info run: | mkdir -p image-info From 37030f510fef202cf11ea257f4d5e4065dea6fd2 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Fri, 21 Nov 2025 09:14:57 -0800 Subject: [PATCH 5/5] cleanup --- .../create-multiarch-manifest/action.yml | 17 ++- .github/actions/save-image-info/action.yaml | 23 ++++ .github/workflows/build.yaml | 113 ++++++++---------- 3 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 .github/actions/save-image-info/action.yaml diff --git a/.github/actions/create-multiarch-manifest/action.yml b/.github/actions/create-multiarch-manifest/action.yml index c62b3ede..ca7c5172 100644 --- a/.github/actions/create-multiarch-manifest/action.yml +++ b/.github/actions/create-multiarch-manifest/action.yml @@ -19,10 +19,17 @@ inputs: description: Architectures to be included in the final manifest, separated by a space default: 'amd64 arm64' +outputs: + image-tag: + description: + The full multiarch manifest tag that was created and pushed + value: ${{ steps.create-and-push-manifest.outputs.image-tag}} + runs: using: composite steps: - - shell: bash + - id: create-and-push-manifest + shell: bash run: | image_flavor="${{ inputs.image-flavor }}" tag="$(scripts/get_tag.sh ${image_flavor})" @@ -32,6 +39,10 @@ runs: images+=("${{ inputs.base-image }}:${tag}-${arch}${{ inputs.suffix }}") done - docker manifest create "${{ inputs.base-image }}:${tag}${{ inputs.suffix }}" "${images[@]}" - docker manifest push "${{ inputs.base-image }}:${tag}${{ inputs.suffix }}" + image_tag="${{ inputs.base-image }}:${tag}${{ inputs.suffix }}" + + docker manifest create "${image_tag}" "${images[@]}" + docker manifest push "${image_tag}" + + echo "image-tag=${image_tag}" >> "${GITHUB_OUTPUT}" diff --git a/.github/actions/save-image-info/action.yaml b/.github/actions/save-image-info/action.yaml new file mode 100644 index 00000000..a144107e --- /dev/null +++ b/.github/actions/save-image-info/action.yaml @@ -0,0 +1,23 @@ +name: Save image info +description: Save image tag to artifact for later reference +inputs: + image-tag: + description: The image tag to save + required: true + name: + description: Base name for both artifact and file (e.g., 'stackrox-build-amd64') + required: true +runs: + using: composite + steps: + - name: Save image info + run: | + mkdir -p image-info + echo "${{ inputs.image-tag }}" > "image-info/${{ inputs.name }}.txt" + shell: bash + - name: Upload image info + uses: actions/upload-artifact@v4 + with: + name: image-info-${{ inputs.name }} + path: image-info/${{ inputs.name }}.txt + retention-days: 1 \ No newline at end of file diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e969e8e2..0a2d8b68 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,8 +15,7 @@ env: jobs: - # Multi-architecture builds for core StackRox images - build-and-push-stackrox-build: + multiarch-build-images: strategy: fail-fast: false matrix: @@ -28,7 +27,7 @@ jobs: runs-on: ${{ matrix.runner }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -37,18 +36,12 @@ jobs: with: image-flavor: "stackrox-build" arch: ${{ matrix.arch }} - - name: Save image info - run: | - mkdir -p image-info - echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/stackrox-build-${{ matrix.arch }}.txt" - - name: Upload image info - uses: actions/upload-artifact@v4 - with: - name: image-info-stackrox-build-${{ matrix.arch }} - path: image-info/stackrox-build-${{ matrix.arch }}.txt - retention-days: 1 + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.build-and-push-image.outputs.image-tag }} + name: stackrox-build-${{ matrix.arch }} - build-and-push-stackrox-test: + multiarch-test-images: strategy: fail-fast: false matrix: @@ -59,10 +52,10 @@ jobs: runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} needs: - - build-and-push-stackrox-build + - multiarch-build-images steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -71,26 +64,19 @@ jobs: with: image-flavor: "stackrox-test" arch: ${{ matrix.arch }} - - name: Save image info - run: | - mkdir -p image-info - echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/stackrox-test-${{ matrix.arch }}.txt" - - name: Upload image info - uses: actions/upload-artifact@v4 - with: - name: image-info-stackrox-test-${{ matrix.arch }} - path: image-info/stackrox-test-${{ matrix.arch }}.txt - retention-days: 1 + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.build-and-push-image.outputs.image-tag }} + name: stackrox-test-${{ matrix.arch }} - # Create multi-architecture manifests - build-and-push-multiarch: + multiarch-manifests: runs-on: ubuntu-latest needs: - - build-and-push-stackrox-build - - build-and-push-stackrox-test + - multiarch-build-images + - multiarch-test-images steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -103,17 +89,26 @@ jobs: password: ${{ secrets.QUAY_STACKROX_IO_RW_PASSWORD }} - uses: ./.github/actions/create-multiarch-manifest + id: stackrox-build-manifest with: base-image: quay.io/stackrox-io/apollo-ci image-flavor: stackrox-build + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.stackrox-build-manifest.outputs.image-tag }} + name: stackrox-build-multiarch - uses: ./.github/actions/create-multiarch-manifest + id: stackrox-test-manifest with: base-image: quay.io/stackrox-io/apollo-ci image-flavor: stackrox-test + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.stackrox-test-manifest.outputs.image-tag }} + name: stackrox-test-multiarch - # Single-architecture builds for other images - build-and-push-single-arch-images: + amd64-build-images: runs-on: ubuntu-latest strategy: matrix: @@ -124,7 +119,7 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -132,24 +127,18 @@ jobs: id: build-and-push-image with: image-flavor: "${{ matrix.image-flavor }}" - - name: Save image info - run: | - mkdir -p image-info - echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/${{ matrix.image-flavor }}.txt" - - name: Upload image info - uses: actions/upload-artifact@v4 - with: - name: image-info-${{ matrix.image-flavor }} - path: image-info/${{ matrix.image-flavor }}.txt - retention-days: 1 + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.build-and-push-image.outputs.image-tag }} + name: ${{ matrix.image-flavor }} - build-and-push-scanner-test: + amd64-test-images: runs-on: ubuntu-latest needs: - - build-and-push-single-arch-images + - amd64-build-images steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -157,25 +146,19 @@ jobs: id: build-and-push-image with: image-flavor: "scanner-test" - - name: Save image info - run: | - mkdir -p image-info - echo "${{ steps.build-and-push-image.outputs.image-tag }}" > "image-info/scanner-test.txt" - - name: Upload image info - uses: actions/upload-artifact@v4 - with: - name: image-info-scanner-test - path: image-info/scanner-test.txt - retention-days: 1 + - uses: ./.github/actions/save-image-info + with: + image-tag: ${{ steps.build-and-push-image.outputs.image-tag }} + name: scanner-test test-cci-export: runs-on: ubuntu-latest needs: - - build-and-push-single-arch-images - - build-and-push-scanner-test + - amd64-build-images + - amd64-test-images steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} @@ -187,11 +170,11 @@ jobs: comment-build-images: runs-on: ubuntu-latest needs: - - build-and-push-stackrox-build - - build-and-push-stackrox-test - - build-and-push-multiarch - - build-and-push-single-arch-images - - build-and-push-scanner-test + - multiarch-build-images + - multiarch-test-images + - multiarch-manifests + - amd64-build-images + - amd64-test-images steps: - name: Download all image info artifacts uses: actions/download-artifact@v4