From a346480e80b526ddb86cf51b838269452a4810ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Mon, 29 Jun 2026 16:04:09 +0200 Subject: [PATCH 01/15] chore(ci): add podman and oc-mirror to e2e-runner image Bump OC client to 4.22.3 and install oc-mirror alongside oc for the upcoming disconnected CI job. Co-authored-by: Cursor --- .ci/images/Dockerfile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.ci/images/Dockerfile b/.ci/images/Dockerfile index 4f6bdd8d65..8993ac59ef 100644 --- a/.ci/images/Dockerfile +++ b/.ci/images/Dockerfile @@ -9,7 +9,7 @@ ENV CI=1 \ _MITSHM=0 \ NODE_PATH=/usr/local/lib/node_modules \ HELM_VERSION="v3.17.2" \ - OC_VERSION="4.19.17" \ + OC_VERSION="4.22.3" \ OCM_VERSION="0.1.76" \ GO_VERSION="1.19" \ GO_SHA256="464b6b66591f6cf055bc5df90a9750bf5fbc9d038722bb84a9d56a2bea974be6" \ @@ -57,6 +57,9 @@ RUN curl -fsSL -o /tmp/helm.tar.gz "https://get.helm.sh/helm-${HELM_VERSION}-lin tar -xzvf /tmp/helm.tar.gz -C /tmp && mv /tmp/linux-amd64/helm /usr/local/bin/helm && \ curl -fsSL -o /tmp/openshift-client-linux.tar.gz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OC_VERSION}/openshift-client-linux-${OC_VERSION}.tar.gz" && \ tar -xzvf /tmp/openshift-client-linux.tar.gz -C /usr/local/bin oc kubectl && \ + curl -fsSL -o /tmp/oc-mirror.tar.gz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OC_VERSION}/oc-mirror.tar.gz" && \ + tar -xzvf /tmp/oc-mirror.tar.gz -C /usr/local/bin oc-mirror && \ + chmod +x /usr/local/bin/oc-mirror && \ curl -Lo /usr/local/bin/ocm "https://github.com/openshift-online/ocm-cli/releases/download/v${OCM_VERSION}/ocm-linux-amd64" && \ chmod +x /usr/local/bin/ocm && \ curl -fsSL "https://github.com/mikefarah/yq/releases/download/v4.43.1/yq_linux_amd64.tar.gz" | tar -xz && \ @@ -79,9 +82,10 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2 unzip awscliv2.zip && \ ./aws/install -# Install skopeo +# Install skopeo and podman RUN apt-get update -y && \ - apt-get install -y skopeo + apt-get install -y --no-install-recommends skopeo podman && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install PostgreSQL CLI (psql only) RUN apt-get update && \ From 0c1869f98e9483b13fa7de49339c79c4f1041f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:15:16 +0200 Subject: [PATCH 02/15] chore(ci): make e2e-runner Dockerfile multi-arch (amd64 + arm64) Parameterize all architecture-hardcoded tool downloads to support building the e2e-runner image for both linux/amd64 and linux/arm64. Changes: - Pin base image to manifest list digest (supports both platforms) - Add ARG TARGETARCH for dynamic arch resolution - Helm, oc, oc-mirror, ocm-cli, yq, opm: use TARGETARCH in URLs - AWS CLI: use $(uname -m) for native x86_64/aarch64 mapping - umoci: upgrade v0.4.7 -> v0.6.0 (first version with arm64 binaries) - Operator SDK: already multi-arch, unchanged - Azure/GCloud/apt packages: already arch-agnostic, unchanged - Remove unused Go env vars (GO_VERSION, GO_SHA256, GOPATH) - local-run.sh: remove --platform=linux/amd64 from podman pull Tested: both images build and all tools verified on both architectures. Assisted-by: OpenCode --- .ci/images/Dockerfile | 56 ++++++++++++++++++++++-------------------- e2e-tests/local-run.sh | 2 +- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/.ci/images/Dockerfile b/.ci/images/Dockerfile index 8993ac59ef..1c2002486f 100644 --- a/.ci/images/Dockerfile +++ b/.ci/images/Dockerfile @@ -1,6 +1,10 @@ -# Base image from Microsoft Playwright -# Playwright v1.59.1-noble includes Node 24.14.1 -FROM mcr.microsoft.com/playwright:v1.61.1-noble@sha256:824f1a789072e648c62541c2cfa4479c4061a290d5c27766d67dc1dcbc19b321 +# Base image from Microsoft Playwright (multi-arch: amd64 + arm64) +# Playwright v1.61.1-noble includes Node 24.14.1 +# Pinned to manifest list digest to support both platforms +FROM mcr.microsoft.com/playwright:v1.61.1-noble@sha256:5b8f294aff9041b7191c34a4bab3ac270157a28774d4b0660e9743297b697e48 + +# Automatically set by buildx/podman based on --platform (amd64 or arm64) +ARG TARGETARCH # Set environment variables for the container ENV CI=1 \ @@ -11,10 +15,7 @@ ENV CI=1 \ HELM_VERSION="v3.17.2" \ OC_VERSION="4.22.3" \ OCM_VERSION="0.1.76" \ - GO_VERSION="1.19" \ - GO_SHA256="464b6b66591f6cf055bc5df90a9750bf5fbc9d038722bb84a9d56a2bea974be6" \ - GOPATH="/go" \ - PATH="$GOPATH/bin:/usr/local/go/bin:$PATH" + UMOCI_VERSION="v0.6.0" # Copy Yarn configuration files to correctly use the project-defined Yarn version COPY .yarn /root/.yarn @@ -52,18 +53,22 @@ RUN echo "whoami: $(whoami)" && \ # Check where Node.js loads required modules node -p 'module.paths' -# Install Helm, OpenShift CLI, ocm-cli, and yq -RUN curl -fsSL -o /tmp/helm.tar.gz "https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" && \ - tar -xzvf /tmp/helm.tar.gz -C /tmp && mv /tmp/linux-amd64/helm /usr/local/bin/helm && \ - curl -fsSL -o /tmp/openshift-client-linux.tar.gz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OC_VERSION}/openshift-client-linux-${OC_VERSION}.tar.gz" && \ +# Install Helm, OpenShift CLI, oc-mirror, ocm-cli, and yq +# OC client: amd64 has no arch suffix (default), arm64 needs "-arm64". +# oc-mirror: arm64 lives under "openshift-v4/aarch64/" mirror tree. +RUN OC_ARCH_SUFFIX=$([ "${TARGETARCH}" = "arm64" ] && echo "-arm64" || echo "") && \ + OC_MIRROR_TREE=$([ "${TARGETARCH}" = "arm64" ] && echo "openshift-v4/aarch64" || echo "openshift-v4") && \ + curl -fsSL -o /tmp/helm.tar.gz "https://get.helm.sh/helm-${HELM_VERSION}-linux-${TARGETARCH}.tar.gz" && \ + tar -xzvf /tmp/helm.tar.gz -C /tmp && mv /tmp/linux-${TARGETARCH}/helm /usr/local/bin/helm && \ + curl -fsSL -o /tmp/openshift-client-linux.tar.gz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OC_VERSION}/openshift-client-linux${OC_ARCH_SUFFIX}-${OC_VERSION}.tar.gz" && \ tar -xzvf /tmp/openshift-client-linux.tar.gz -C /usr/local/bin oc kubectl && \ - curl -fsSL -o /tmp/oc-mirror.tar.gz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OC_VERSION}/oc-mirror.tar.gz" && \ + curl -fsSL -o /tmp/oc-mirror.tar.gz "https://mirror.openshift.com/pub/${OC_MIRROR_TREE}/clients/ocp/${OC_VERSION}/oc-mirror.tar.gz" && \ tar -xzvf /tmp/oc-mirror.tar.gz -C /usr/local/bin oc-mirror && \ chmod +x /usr/local/bin/oc-mirror && \ - curl -Lo /usr/local/bin/ocm "https://github.com/openshift-online/ocm-cli/releases/download/v${OCM_VERSION}/ocm-linux-amd64" && \ + curl -Lo /usr/local/bin/ocm "https://github.com/openshift-online/ocm-cli/releases/download/v${OCM_VERSION}/ocm-linux-${TARGETARCH}" && \ chmod +x /usr/local/bin/ocm && \ - curl -fsSL "https://github.com/mikefarah/yq/releases/download/v4.43.1/yq_linux_amd64.tar.gz" | tar -xz && \ - mv yq_linux_amd64 /usr/local/bin/yq && \ + curl -fsSL "https://github.com/mikefarah/yq/releases/download/v4.43.1/yq_linux_${TARGETARCH}.tar.gz" | tar -xz && \ + mv yq_linux_${TARGETARCH} /usr/local/bin/yq && \ rm -rf /tmp/* /var/tmp/* # Install Azure CLI @@ -77,30 +82,29 @@ RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages. apt-get install google-cloud-cli google-cloud-sdk-gke-gcloud-auth-plugin -y && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -# Install AWS CLI -RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ +# Install AWS CLI (uname -m returns x86_64 on amd64, aarch64 on arm64 — matching AWS URL naming) +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "awscliv2.zip" && \ unzip awscliv2.zip && \ ./aws/install # Install skopeo and podman RUN apt-get update -y && \ - apt-get install -y --no-install-recommends skopeo podman && \ - apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + apt-get install -y --no-install-recommends skopeo podman # Install PostgreSQL CLI (psql only) RUN apt-get update && \ apt-get install -y --no-install-recommends postgresql-client && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -# Install umoci -RUN curl -LO "https://github.com/opencontainers/umoci/releases/download/v0.4.7/umoci.amd64" && \ - chmod +x umoci.amd64 && \ - mv umoci.amd64 /usr/local/bin/umoci +# Install umoci (v0.6.0+ provides multi-arch binaries) +RUN curl -LO "https://github.com/opencontainers/umoci/releases/download/${UMOCI_VERSION}/umoci.linux.${TARGETARCH}" && \ + chmod +x "umoci.linux.${TARGETARCH}" && \ + mv "umoci.linux.${TARGETARCH}" /usr/local/bin/umoci # Install opm -RUN curl -LO "https://github.com/operator-framework/operator-registry/releases/download/v1.47.0/linux-amd64-opm" && \ - chmod +x linux-amd64-opm && \ - mv linux-amd64-opm /usr/local/bin/opm +RUN curl -LO "https://github.com/operator-framework/operator-registry/releases/download/v1.47.0/linux-${TARGETARCH}-opm" && \ + chmod +x "linux-${TARGETARCH}-opm" && \ + mv "linux-${TARGETARCH}-opm" /usr/local/bin/opm # Install Operator SDK CLI (required to install OLM on K8s clusters) RUN export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) && \ diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index 5f301bf1ed..f660bbc698 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -359,7 +359,7 @@ fi # Pull runner image first (can take a while) log::section "Pulling runner container image" -podman pull "$RUNNER_IMAGE" --platform=linux/amd64 +podman pull "$RUNNER_IMAGE" export VAULT_ADDR='https://vault.ci.openshift.org' From dce41c3f12b31c9a87376c36f108309a564c7638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:19:58 +0200 Subject: [PATCH 03/15] chore(ci): add multi-arch build to e2e-runner workflow Add matrix strategy (ubuntu-24.04 + ubuntu-24.04-arm) to build the e2e-runner image natively on both amd64 and arm64 runners. A merge job assembles the per-arch digests into a multi-arch manifest list. - build-image: matrix builds per-arch images, pushes arch-specific tags, exports digest as artifact - merge: downloads digests, creates multi-arch manifest with docker buildx imagetools create, tags with branch and branch-sha Assisted-by: OpenCode --- .github/workflows/push-e2e-runner.yaml | 114 +++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 6 deletions(-) diff --git a/.github/workflows/push-e2e-runner.yaml b/.github/workflows/push-e2e-runner.yaml index 5c86ec2614..c9c5d352b8 100644 --- a/.github/workflows/push-e2e-runner.yaml +++ b/.github/workflows/push-e2e-runner.yaml @@ -25,12 +25,17 @@ env: jobs: build-image: - name: Build & Push e2e-runner Image + name: Build e2e-runner (${{ matrix.os }}) + env: + HAS_QUAY_AUTH: ${{ secrets.QUAY_USERNAME != '' && secrets.QUAY_TOKEN != '' }} strategy: fail-fast: false matrix: - os: [ubuntu-24.04] + os: + - ubuntu-24.04 + - ubuntu-24.04-arm runs-on: ${{ matrix.os }} + timeout-minutes: 120 permissions: contents: read packages: write @@ -44,10 +49,22 @@ jobs: - name: Prepare Environment Variables env: INPUT_BRANCH: ${{ inputs.branch }} + MATRIX_OS: ${{ matrix.os }} run: | - echo "PLATFORM=linux/amd64" >> $GITHUB_ENV + # Derive platform from runner OS + if [ "$MATRIX_OS" == "ubuntu-24.04" ]; then + platform="linux/amd64" + elif [ "$MATRIX_OS" == "ubuntu-24.04-arm" ]; then + platform="linux/arm64" + else + echo "::error::Unknown runner OS: $MATRIX_OS" + exit 1 + fi + echo "PLATFORM=$platform" >> $GITHUB_ENV + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_ARCH=${platform#*/}" >> $GITHUB_ENV - # create image tag from the correct branch (either from a push or a workflow_dispatch trigger) + # Create image tag from the correct branch (either from a push or a workflow_dispatch trigger) if [[ "$INPUT_BRANCH" ]] && [[ "$INPUT_BRANCH" != "NONE" ]]; then echo "Switch to $INPUT_BRANCH" git checkout "$INPUT_BRANCH" @@ -59,6 +76,13 @@ jobs: echo "Use IMAGE_TAG = $IMAGE_TAG" echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV + - name: Check Quay credentials + run: | + if [ "$HAS_QUAY_AUTH" != "true" ]; then + echo "::error::Missing QUAY_USERNAME or QUAY_TOKEN secrets" + exit 1 + fi + - name: Get the last commit short SHA uses: ./.github/actions/get-sha @@ -73,12 +97,90 @@ jobs: password: ${{ secrets.QUAY_TOKEN }} - name: Build and Push Image + id: build-push uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: . file: .ci/images/Dockerfile push: true tags: | - ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }} - ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.SHORT_SHA }} + ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.PLATFORM_ARCH }} + ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.SHORT_SHA }}-${{ env.PLATFORM_ARCH }} platforms: ${{ env.PLATFORM }} + + - name: Export digest + env: + DIGEST: ${{ steps.build-push.outputs.digest }} + run: | + mkdir -p /tmp/digests + digest="$DIGEST" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + name: Create multi-arch manifest + runs-on: ubuntu-latest + needs: build-image + permissions: + contents: read + packages: write + + steps: + - name: Checkout Repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + + - name: Prepare Environment Variables + env: + INPUT_BRANCH: ${{ inputs.branch }} + run: | + if [[ "$INPUT_BRANCH" ]] && [[ "$INPUT_BRANCH" != "NONE" ]]; then + git checkout "$INPUT_BRANCH" + IMAGE_TAG="$INPUT_BRANCH" + else + IMAGE_TAG=$(git rev-parse --abbrev-ref HEAD) + fi + echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV + + - name: Get the last commit short SHA + uses: ./.github/actions/get-sha + + - name: Download digests + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + + - name: Login to Quay + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + for tag in \ + "${REGISTRY}/${REGISTRY_IMAGE}:${IMAGE_TAG}" \ + "${REGISTRY}/${REGISTRY_IMAGE}:${IMAGE_TAG}-${SHORT_SHA}"; do + echo "Creating multi-arch manifest for: $tag" + docker buildx imagetools create -t "$tag" \ + $(printf "${REGISTRY}/${REGISTRY_IMAGE}@sha256:%s " *) + done + + - name: Inspect image + run: | + docker buildx imagetools inspect "${REGISTRY}/${REGISTRY_IMAGE}:${IMAGE_TAG}" From 0929eaf2f8ca8c9eabca7a7d089939cbe9b9cfca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:36:19 +0200 Subject: [PATCH 04/15] fix(ci): clean up AWS CLI install artifacts in e2e-runner Dockerfile Remove the downloaded zip and extracted aws/ directory after install to reduce image size. Assisted-by: OpenCode --- .ci/images/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/images/Dockerfile b/.ci/images/Dockerfile index 1c2002486f..0a2be7f866 100644 --- a/.ci/images/Dockerfile +++ b/.ci/images/Dockerfile @@ -85,7 +85,8 @@ RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages. # Install AWS CLI (uname -m returns x86_64 on amd64, aarch64 on arm64 — matching AWS URL naming) RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "awscliv2.zip" && \ unzip awscliv2.zip && \ - ./aws/install + ./aws/install && \ + rm -rf awscliv2.zip aws/ # Install skopeo and podman RUN apt-get update -y && \ From 183e3bc1242780a50cb64a1a1f896405c119ee78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:36:43 +0200 Subject: [PATCH 05/15] fix(ci): add apt cleanup to skopeo/podman install step Add apt-get clean and list removal to match all other apt-get install blocks in the Dockerfile and reduce layer size. Assisted-by: OpenCode --- .ci/images/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/images/Dockerfile b/.ci/images/Dockerfile index 0a2be7f866..07c505f35f 100644 --- a/.ci/images/Dockerfile +++ b/.ci/images/Dockerfile @@ -90,7 +90,8 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "aws # Install skopeo and podman RUN apt-get update -y && \ - apt-get install -y --no-install-recommends skopeo podman + apt-get install -y --no-install-recommends skopeo podman && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install PostgreSQL CLI (psql only) RUN apt-get update && \ From 2f11186b15480747b1a7d46da0d2a80b5fbba66a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:37:37 +0200 Subject: [PATCH 06/15] fix(ci): pin merge job runner to ubuntu-24.04 Pin the merge job to ubuntu-24.04 for consistency with the build jobs instead of using ubuntu-latest. Assisted-by: OpenCode --- .github/workflows/push-e2e-runner.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push-e2e-runner.yaml b/.github/workflows/push-e2e-runner.yaml index c9c5d352b8..f75a22c3ce 100644 --- a/.github/workflows/push-e2e-runner.yaml +++ b/.github/workflows/push-e2e-runner.yaml @@ -126,7 +126,7 @@ jobs: merge: name: Create multi-arch manifest - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: build-image permissions: contents: read From ed064789103615c6fef8db29c7a77f57adcf5c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 11:48:03 +0200 Subject: [PATCH 07/15] chore(ci): run e2e-runner build as PR check on Dockerfile changes Add pull_request trigger so the e2e-runner image is built (without pushing) on PRs that modify .ci/images/Dockerfile or .yarnrc.yml. This catches build failures before merge. - Add pull_request trigger with same path filters - Guard push-only steps (login, digest export, merge) with event check - Widen branch glob from 'release-1.*' to 'release-*' for future majors - Use PR number in concurrency group and image tag Assisted-by: OpenCode --- .github/workflows/push-e2e-runner.yaml | 36 ++++++++++++++------------ 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/.github/workflows/push-e2e-runner.yaml b/.github/workflows/push-e2e-runner.yaml index f75a22c3ce..95c20c93a7 100644 --- a/.github/workflows/push-e2e-runner.yaml +++ b/.github/workflows/push-e2e-runner.yaml @@ -1,10 +1,14 @@ name: Build & Push e2e-runner Image to Quay.io on: + pull_request: + paths: + - '.ci/images/Dockerfile' + - '.yarnrc.yml' push: branches: - main - - 'release-1.*' + - 'release-*' paths: - '.ci/images/Dockerfile' - '.yarnrc.yml' @@ -16,7 +20,7 @@ on: default: 'NONE' concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.event.number || github.ref }} cancel-in-progress: true env: @@ -49,26 +53,21 @@ jobs: - name: Prepare Environment Variables env: INPUT_BRANCH: ${{ inputs.branch }} - MATRIX_OS: ${{ matrix.os }} + PR_NUMBER: ${{ github.event.number }} run: | - # Derive platform from runner OS - if [ "$MATRIX_OS" == "ubuntu-24.04" ]; then - platform="linux/amd64" - elif [ "$MATRIX_OS" == "ubuntu-24.04-arm" ]; then - platform="linux/arm64" - else - echo "::error::Unknown runner OS: $MATRIX_OS" - exit 1 - fi - echo "PLATFORM=$platform" >> $GITHUB_ENV - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - echo "PLATFORM_ARCH=${platform#*/}" >> $GITHUB_ENV + # Detect platform from runner's native architecture + arch=$(dpkg --print-architecture) + echo "PLATFORM=linux/${arch}" >> $GITHUB_ENV + echo "PLATFORM_PAIR=linux-${arch}" >> $GITHUB_ENV + echo "PLATFORM_ARCH=${arch}" >> $GITHUB_ENV # Create image tag from the correct branch (either from a push or a workflow_dispatch trigger) if [[ "$INPUT_BRANCH" ]] && [[ "$INPUT_BRANCH" != "NONE" ]]; then echo "Switch to $INPUT_BRANCH" git checkout "$INPUT_BRANCH" IMAGE_TAG="$INPUT_BRANCH" + elif [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then + IMAGE_TAG="pr-${PR_NUMBER}" else echo "Use current branch $GITHUB_REF" IMAGE_TAG=$(git rev-parse --abbrev-ref HEAD) @@ -77,6 +76,7 @@ jobs: echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - name: Check Quay credentials + if: github.event_name != 'pull_request' run: | if [ "$HAS_QUAY_AUTH" != "true" ]; then echo "::error::Missing QUAY_USERNAME or QUAY_TOKEN secrets" @@ -90,6 +90,7 @@ jobs: uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Login to Quay + if: github.event_name != 'pull_request' uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ${{ env.REGISTRY }} @@ -102,13 +103,14 @@ jobs: with: context: . file: .ci/images/Dockerfile - push: true + push: ${{ github.event_name != 'pull_request' }} tags: | ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.PLATFORM_ARCH }} ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.SHORT_SHA }}-${{ env.PLATFORM_ARCH }} platforms: ${{ env.PLATFORM }} - name: Export digest + if: github.event_name != 'pull_request' env: DIGEST: ${{ steps.build-push.outputs.digest }} run: | @@ -117,6 +119,7 @@ jobs: touch "/tmp/digests/${digest#sha256:}" - name: Upload digest + if: github.event_name != 'pull_request' uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: digests-${{ env.PLATFORM_PAIR }} @@ -126,6 +129,7 @@ jobs: merge: name: Create multi-arch manifest + if: github.event_name != 'pull_request' runs-on: ubuntu-24.04 needs: build-image permissions: From 676d9ee228d23424d83efe3445114f1310c3a52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 12:46:14 +0200 Subject: [PATCH 08/15] chore(e2e): add --runner-image flag to local-run.sh Add -i/--runner-image CLI parameter to override the e2e runner container image. Defaults to quay.io/rhdh-community/rhdh-e2e-runner:main. Local images (localhost/ prefix) skip the podman pull step. Assisted-by: OpenCode --- e2e-tests/local-run.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index f660bbc698..0268614d74 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -23,6 +23,8 @@ Options: -r, --repo IMAGE_REPO Image repository (e.g., rhdh/rhdh-hub-rhel9) -t, --tag TAG_NAME Image tag (e.g., next, latest, 1.5) -p, --pr PR_NUMBER PR number (sets repo to rhdh-community/rhdh, tag to pr-) + -i, --runner-image IMG Override the e2e runner container image + (default: quay.io/rhdh-community/rhdh-e2e-runner:main) -s, --skip-tests Deploy only, skip running tests -h, --help Show this help message @@ -45,6 +47,9 @@ Examples: # Run on GKE ./local-run.sh -j periodic-ci-gke-helm-nightly -r rhdh/rhdh-hub-rhel9 -t next -s + # Use a locally built runner image + ./local-run.sh --runner-image localhost/rhdh-e2e-runner:test + EOF exit 0 } @@ -73,6 +78,10 @@ while [[ $# -gt 0 ]]; do CLI_TAG_NAME="pr-$2" shift 2 ;; + -i | --runner-image) + RUNNER_IMAGE="$2" + shift 2 + ;; -s | --skip-tests) CLI_SKIP_TESTS="true" shift @@ -359,7 +368,12 @@ fi # Pull runner image first (can take a while) log::section "Pulling runner container image" -podman pull "$RUNNER_IMAGE" +# Skip pull for local images (localhost/ prefix) +if [[ "$RUNNER_IMAGE" != localhost/* ]]; then + podman pull "$RUNNER_IMAGE" +else + log::info "Using local image: $RUNNER_IMAGE (skipping pull)" +fi export VAULT_ADDR='https://vault.ci.openshift.org' From 1e5842afeb95a1fc32cdb5f70e7610554a0cc5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 13:06:21 +0200 Subject: [PATCH 09/15] fix(e2e): fix TTY flag in local-run.sh and vault arch in container-init.sh - local-run.sh: remove -t from podman run flags. The -t (allocate TTY) is incompatible with piping through tee, causing a spurious exit code 127 when bash misparses continuation lines. The -i flag alone is sufficient. - container-init.sh: use dpkg --print-architecture instead of hardcoded amd64 for the vault binary download, so arm64 containers get the native binary instead of relying on QEMU emulation. Assisted-by: OpenCode --- e2e-tests/container-init.sh | 3 ++- e2e-tests/local-run.sh | 9 ++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/e2e-tests/container-init.sh b/e2e-tests/container-init.sh index fd2900637d..7b208b2b52 100644 --- a/e2e-tests/container-init.sh +++ b/e2e-tests/container-init.sh @@ -23,7 +23,8 @@ set -e if ! command -v vault &> /dev/null; then VAULT_VERSION="${VAULT_VERSION:-1.15.4}" log::info "Installing vault ${VAULT_VERSION}..." - curl -fsSL "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip" -o /tmp/vault.zip + VAULT_ARCH=$(dpkg --print-architecture) + curl -fsSL "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_${VAULT_ARCH}.zip" -o /tmp/vault.zip unzip -q /tmp/vault.zip -d /usr/local/bin/ rm /tmp/vault.zip fi diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index 0268614d74..737cc288ab 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -368,12 +368,7 @@ fi # Pull runner image first (can take a while) log::section "Pulling runner container image" -# Skip pull for local images (localhost/ prefix) -if [[ "$RUNNER_IMAGE" != localhost/* ]]; then - podman pull "$RUNNER_IMAGE" -else - log::info "Using local image: $RUNNER_IMAGE (skipping pull)" -fi +podman pull "$RUNNER_IMAGE" export VAULT_ADDR='https://vault.ci.openshift.org' @@ -450,7 +445,7 @@ echo "" CONTAINER_EXIT_CODE=0 podman run -v "$WORK_DIR":/tmp/rhdh \ -v "$SCRIPT_DIR/container-init.sh":/tmp/container-init.sh:ro \ - -it -u root --privileged \ + -i -u root --privileged \ --mount type=tmpfs,destination=/tmp/secrets \ -e VAULT_ADDR="$VAULT_ADDR" \ -e VAULT_TOKEN="$VAULT_TOKEN" \ From 6e54304813c9cd65fb056e74803d8bc093b84484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Tue, 30 Jun 2026 13:08:20 +0200 Subject: [PATCH 10/15] fix(e2e): skip podman pull for local runner images Re-add the localhost/ prefix check that was lost during rebase. When using --runner-image localhost/..., skip the pull step since the image is already available locally. Assisted-by: OpenCode --- e2e-tests/local-run.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index 737cc288ab..e29155cec8 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -366,9 +366,16 @@ if [[ "$CLI_MODE" == "false" ]]; then echo "" fi -# Pull runner image first (can take a while) +# Pull runner image (always attempt; fall back to local copy if pull fails) log::section "Pulling runner container image" -podman pull "$RUNNER_IMAGE" +if ! podman pull "$RUNNER_IMAGE" 2>/dev/null; then + if podman image exists "$RUNNER_IMAGE" 2>/dev/null; then + log::info "Pull failed but image exists locally: $RUNNER_IMAGE" + else + log::error "Failed to pull image and no local copy: $RUNNER_IMAGE" + exit 1 + fi +fi export VAULT_ADDR='https://vault.ci.openshift.org' From 53b1e693f8d166dedfe4a94687ac35bf4c266cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Wed, 1 Jul 2026 07:36:50 +0200 Subject: [PATCH 11/15] fix(e2e): show podman pull errors instead of suppressing stderr Remove 2>/dev/null from podman pull so auth, network, and tag errors are visible to the user when a pull fails. Assisted-by: OpenCode --- e2e-tests/local-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index e29155cec8..b0ae9385b0 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -368,7 +368,7 @@ fi # Pull runner image (always attempt; fall back to local copy if pull fails) log::section "Pulling runner container image" -if ! podman pull "$RUNNER_IMAGE" 2>/dev/null; then +if ! podman pull "$RUNNER_IMAGE"; then if podman image exists "$RUNNER_IMAGE" 2>/dev/null; then log::info "Pull failed but image exists locally: $RUNNER_IMAGE" else From 760700874e13e9dc65775d5f10199982e92ad342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Wed, 1 Jul 2026 07:37:10 +0200 Subject: [PATCH 12/15] fix(ci): add timeout-minutes to e2e-runner merge job Add timeout-minutes: 20 to the merge job to prevent hangs on registry hiccups. Aligns with the build-image job which already has an explicit timeout. Assisted-by: OpenCode --- .github/workflows/push-e2e-runner.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push-e2e-runner.yaml b/.github/workflows/push-e2e-runner.yaml index 95c20c93a7..f115211872 100644 --- a/.github/workflows/push-e2e-runner.yaml +++ b/.github/workflows/push-e2e-runner.yaml @@ -131,6 +131,7 @@ jobs: name: Create multi-arch manifest if: github.event_name != 'pull_request' runs-on: ubuntu-24.04 + timeout-minutes: 20 needs: build-image permissions: contents: read From cc3d81e7ba5d95ef134cc5b9c7f9332469918535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Wed, 1 Jul 2026 07:37:32 +0200 Subject: [PATCH 13/15] fix(e2e): respect RUNNER_IMAGE env var in local-run.sh Use ${RUNNER_IMAGE:-default} so an exported env var is not silently clobbered by the hardcoded default. The --runner-image CLI flag still takes precedence over both. Assisted-by: OpenCode --- e2e-tests/local-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index b0ae9385b0..7efc85a025 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -2,7 +2,7 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -RUNNER_IMAGE="quay.io/rhdh-community/rhdh-e2e-runner:main" +RUNNER_IMAGE="${RUNNER_IMAGE:-quay.io/rhdh-community/rhdh-e2e-runner:main}" RUN_CONFIG_FILE="$SCRIPT_DIR/.local-test/run-config.env" # Source logging library From 7f72f469136d675e77869ad09d01a0d864d02179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Wed, 1 Jul 2026 07:37:55 +0200 Subject: [PATCH 14/15] fix(e2e): add comment explaining why -t is omitted from podman run Document that -t (TTY allocation) is intentionally omitted because stdout is piped through tee and CI has no TTY. Prevents future contributors from adding it back. Assisted-by: OpenCode --- e2e-tests/local-run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e-tests/local-run.sh b/e2e-tests/local-run.sh index 7efc85a025..674dbddd79 100755 --- a/e2e-tests/local-run.sh +++ b/e2e-tests/local-run.sh @@ -450,6 +450,7 @@ log::info "Container log: $CONTAINER_LOG" echo "" CONTAINER_EXIT_CODE=0 +# no -t: stdout is piped to tee and CI has no TTY podman run -v "$WORK_DIR":/tmp/rhdh \ -v "$SCRIPT_DIR/container-init.sh":/tmp/container-init.sh:ro \ -i -u root --privileged \ From 524341efa35d06ef48e1b05bece6ab0ccc1a8733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Dr=C3=A1pela?= Date: Wed, 1 Jul 2026 07:41:41 +0200 Subject: [PATCH 15/15] chore(ci): set 1-week expiry on per-arch e2e-runner tags Add quay.expires-after=1w label to per-arch images so intermediate tags (main-amd64, main-arm64, etc.) are automatically cleaned up by Quay after one week. The multi-arch manifest tags are unaffected. Assisted-by: OpenCode --- .github/workflows/push-e2e-runner.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/push-e2e-runner.yaml b/.github/workflows/push-e2e-runner.yaml index f115211872..2d249926fe 100644 --- a/.github/workflows/push-e2e-runner.yaml +++ b/.github/workflows/push-e2e-runner.yaml @@ -107,6 +107,8 @@ jobs: tags: | ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.PLATFORM_ARCH }} ${{ env.REGISTRY }}/${{ env.REGISTRY_IMAGE }}:${{ env.IMAGE_TAG }}-${{ env.SHORT_SHA }}-${{ env.PLATFORM_ARCH }} + labels: | + quay.expires-after=1w platforms: ${{ env.PLATFORM }} - name: Export digest