Repository: kedacore/keda

Issue:
Enable support on s390x for KEDA

### Discussed in https://github.com/kedacore/keda/discussions/5584

<div type='discussions-op-text'>

<sup>Originally posted by **dilipgb** March  8, 2024</sup>
Hi, we are from IBM Z team working on enabling knative on s390x architecture. Since Knative started using KEDA as the event based autoscaler for kafka we are looking to enable support for KEDA. I have successful in building images for s390x locally and patched with knative. Our tests are successful but looking for images to be available to end users via official releases. I'm raising this question to understand what are community thoughts and any guidelines from community about enablement?</div>

Discussion:
@JorTurFer: I think that we can support s390x and I like the idea, but we need to ensure that we have resources to test and cover KEDA on that architecture. I'm wondering if IBM can provide us a s390x machine that we can use and configure by us to support this new architecture @dilipgb

I'm also afraid about what will happen if we lose the capability of testing that arch, should we drop the support? 

I've seen this page to request a machine for OSS -> https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/
Should we just fulfil the process? Actually, I'm willing to request it to support this new architecture if it's just fulfilling the form @dilipgb: @JorTurFer the machine assigned to you will be permanent and will not be scheduled to delete. Don't worry about losing the machine. Yes we need to fill the form and submit it, the OSS team in IBM will review request and provide the virtual machine (we can follow up on the request internally once we have the ticket number). Our team is committed to work closely in future too and collabrate in case of issues in future related to s390x architecture. @JorTurFer: I've just requested the resources :) 
![Image](https://github.com/user-attachments/assets/264d00b7-6371-45aa-b8fc-fe72bfef341d)

I don't have any ticket number, but I guess that it's a process that needs to be reviewed by humans and someone will contact me by email (I've not received any email confirmation either)@bj2122: Hi @JorTurFer , Could you please update the status on the machine request you raised with IBM@JorTurFer: Hello
I receive the confirmation this week but I've been quite busy, I'll handle it during this week, sorry@JorTurFer: I've create the machine and I'm currently checking how to connect it with KEDA's repos, do you have any guide or so?@dilipgb: @JorTurFer we can discuss this in adhoc meeting among our teams and you, then create proposal and discuss in coming community call? What do you suggest?@JorTurFer: Currently, I'm trying to register an agent using this repo -> https://github.com/anup-kodlekere/gaplib. The problem is that some things aren't working properly, and I'm trying to figure out what and why

@JorTurFer: I've figured out how to start the github runners and now  I'm preparing a PR with the support in KEDA core. I've found that [k8s doesn't support s390x platform anymore](https://groups.google.com/g/kubernetes-sig-architecture/c/3y5MR_B6240/m/y69ZSzsAAgAJ).

I'm wondering if IBM offers testing tools like kind by their own. We do need at least a kind cluster to run smoke tests or a real k8s cluster that can we use to run the whole e2e suite, but this is a requirement for us because otherwise we can't guarantee that the container starts and works. Do you have any info about this @dilipgb ?@dilipgb: @JorTurFer yes we can set up the kubeadm cluster in IBM Cloud and we have automation scripts create clusters on fly. Vishnu  (github id: vishnubijukumaribm) from our team can help in setting these things and providing access.

Also I wanted to clarify the process to run the tests. Do we need to run tests on each PR? Can we have nightly jobs/scheduled jobs in github? Conditionally we will have workflow for release branch PRs when branch cut happens for release.

This helps in 2 ways for us. 
1. No PR will be blocked because of s390x specific issues (in case). Devs can focus on features and we run tests in scheduled way and  our team will be doing fixes needed in case of failure. 
2. Running tests when we cut a release branch ensures we are not shipping faulty s390x packages for KEDA.@JorTurFer: > Do we need to run tests on each PR? Can we have nightly jobs/scheduled jobs in github?

No, e2e test are executed on each PR only using AMD64 arch using a real k8s cluster running on azure, but we don't expect to test them in all the platforms. Currently, we are executing the e2e suite on merge to main and also scheduled every night and is here when we execute also the ARM64 smoke tests and when we have to execute the s390x smoke tests.

> Conditionally we will have workflow for release branch PRs when branch cut happens for release

We don't execute the e2e tests on release process because we use a commit already tested from main branch

> 1. No PR will be blocked because of s390x specific issues (in case). Devs can focus on features and we run tests in scheduled way and  our team will be doing fixes needed in case of failure.

Currently, PRs aren't blocked because of specific arch issues if the unit tests executed on the arch passes, the only arch used for e2e tests during PR is AMD64 (but all the arch execute unit/integration tests)

> 2. Running tests when we cut a release branch ensures we are not shipping faulty s390x packages for KEDA.

This isn't supported currently, but smoke tests will be executed on each merge on main. 
**NOTE**: smoke tests don't execute the whole e2e suite (which require some cloud federations for some flows) but only a super small subset of the tests:
https://github.com/kedacore/keda/blob/30b6b9a513bf54dee39200ae3abe18ee643c670d/tests/run-smoke-tests.sh#L8-L12

I'm going to add @zroubalik @wozniakjan to ensure that they are aware with this and they agree :) 

[I've drafted a PR](https://github.com/kedacore/keda/pull/6623) to test the gh runners on s390x and basically we can cover the [unit/integration tests](https://github.com/kedacore/keda/actions/runs/13885608454/job/38849926945?pr=6623) and the [docker image generation](https://github.com/kedacore/keda/actions/runs/13885608454/job/38849927214?pr=6623). If we can cover the smoke tests too, I'd say that we are quite well to support the arch because I (want to) assume that platform limitations will happen just on packages initialisation, so if some package doesn't have support for s390x, unit/integration tests should fail.

devcontainer doesn't run on s390x because of lack of support with `delve` pkg, but I guess that nobody uses s390x for local development and I definitively, I'm opened to drop the devcontainer support on it of my colleges are willing too (I don't want to block an arch just because of the devcontainers)@dilipgb: ok thanks. It make sense to me now. We can follow the same setup as ARM64 for s390x I guess. Thanks for clarifying.@JorTurFer: > ok thanks. It make sense to me now. We can follow the same setup as ARM64 for s390x I guess. Thanks for clarifying.

Yeah, I think so, the problem is that we use kind for smoke tests on ARM64 and [s390x doesn't have supported kind binaries](https://github.com/kubernetes-sigs/kind/issues/3754). Does IBM support kind binaries for s390x that we can use? @dilipgb: > > ok thanks. It make sense to me now. We can follow the same setup as ARM64 for s390x I guess. Thanks for clarifying.
> 
> Yeah, I think so, the problem is that we use kind for smoke tests on ARM64 and [s390x doesn't have supported kind binaries](https://github.com/kubernetes-sigs/kind/issues/3754). Does IBM support kind binaries for s390x that we can use?

No. We are using kubeadm. I will check internally once, if there is a KinD images built and supported.@vishnubijukumar: Hi @JorTurFer  I’ve sent you the scripts to create and destroy Kubernetes cluster on s390x vm on [kubernetes.slack.com](http://kubernetes.slack.com/). Also the smoke tests are passed with kubernetes_workload, prometheus and cron.

<img width="838" alt="Image" src="https://github.com/user-attachments/assets/44babff9-5596-4c67-adc1-77a4038cdfa4" />@dilipgb: Thanks @JorTurFer for staying on top of this and getting it to the closure. I really appreciate your guidance as well as helping our team to get KEDA support added for s390x.@JorTurFer: Thanks a lot for your help! ❤ 

Solution patch:
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index bbd00cb16..c36ce274f 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -41,12 +41,16 @@ RUN apt-get update \
     && go install golang.org/x/lint/golint@latest \
     && go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest \
     && go install github.com/mgechev/revive@latest \
-    && go install github.com/go-delve/delve/cmd/dlv@latest \
     && go install honnef.co/go/tools/cmd/staticcheck@latest \
     && go install golang.org/x/tools/gopls@latest \
     # Protocol Buffer Compiler
     && PROTOC_VERSION=29.2 \
-    && if [ $(dpkg --print-architecture) = "amd64" ]; then PROTOC_ARCH="x86_64"; else PROTOC_ARCH="aarch_64" ; fi \
+    && case $(dpkg --print-architecture) in \
+        "amd64") PROTOC_ARCH="x86_64" ;; \
+        "arm64") PROTOC_ARCH="aarch_64" ;; \
+        "s390x") PROTOC_ARCH="s390_64" ;; \
+        *) echo "Unsupported architecture"; exit 1 ;; \
+    esac \
     && curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-$PROTOC_ARCH.zip" \
     && unzip "protoc-${PROTOC_VERSION}-linux-$PROTOC_ARCH.zip" -d $HOME/.local \
     && mv $HOME/.local/bin/protoc /usr/local/bin/protoc \
diff --git a/.github/workflows/main-build.yml b/.github/workflows/main-build.yml
index 83170ad11..ca11fa929 100644
--- a/.github/workflows/main-build.yml
+++ b/.github/workflows/main-build.yml
@@ -49,6 +49,13 @@ jobs:
       - name: Test
         run: make test
 
+      # https://github.com/sigstore/cosign-installer
+      - name: Install Cosign
+        uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
+
+      - name: Check Cosign install!
+        run: cosign version
+
       - name: Login to GitHub Container Registry
         uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
         with:
@@ -62,20 +69,25 @@ jobs:
       - name: Set up Docker Buildx
         uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
 
-      - name: Publish on GitHub Container Registry
+      - name: Publish main on GitHub Container Registry
         run: make publish-multiarch
 
-      # https://github.com/sigstore/cosign-installer
-      - name: Install Cosign
-        uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
+      - name: Sign KEDA images published on GitHub Container Registry
+        # This step uses the identity token to provision an ephemeral certificate
+        # against the sigstore community Fulcio instance.
+        run: make sign-images
 
-      - name: Check Cosign install!
-        run: cosign version
+      - name: Publish sha on GitHub Container Registry
+        run: make publish-multiarch
+        env:
+          VERSION: ${{ github.sha }}
 
       - name: Sign KEDA images published on GitHub Container Registry
         # This step uses the identity token to provision an ephemeral certificate
         # against the sigstore community Fulcio instance.
         run: make sign-images
+        env:
+          VERSION: ${{ github.sha }}
 
   validate:
     needs: build
@@ -86,6 +98,10 @@ jobs:
     needs: build
     uses: kedacore/keda/.github/workflows/template-arm64-smoke-tests.yml@main
 
+  validate-s390x:
+    needs: build
+    uses: kedacore/keda/.github/workflows/template-s390x-smoke-tests.yml@main
+
   validate-k8s-versions:
     needs: build
     uses: kedacore/keda/.github/workflows/template-versions-smoke-tests.yml@main
@@ -110,7 +126,7 @@ jobs:
       security-events: write
     strategy:
       matrix:
-        runner: [ARM64, ubuntu-latest]
+        runner: [ARM64, ubuntu-latest, s390x]
     uses: kedacore/keda/.github/workflows/template-trivy-scan.yml@main
     with:
       runs-on: ${{ matrix.runner }}
@@ -127,7 +143,7 @@ jobs:
       security-events: write
     strategy:
       matrix:
-        runner: [ARM64, ubuntu-latest]
+        runner: [ARM64, ubuntu-latest, s390x]
     uses: kedacore/keda/.github/workflows/template-trivy-scan.yml@main
     with:
       runs-on: ${{ matrix.runner }}
diff --git a/.github/workflows/nightly-e2e.yml b/.github/workflows/nightly-e2e.yml
index ba5a845b4..e8186589b 100644
--- a/.github/workflows/nightly-e2e.yml
+++ b/.github/workflows/nightly-e2e.yml
@@ -14,5 +14,8 @@ jobs:
   validate-arm64:
     uses: kedacore/keda/.github/workflows/template-arm64-smoke-tests.yml@main
 
+  validate-s390x:
+    uses: kedacore/keda/.github/workflows/template-s390x-smoke-tests.yml@main
+
   validate-k8s-versions:
     uses: kedacore/keda/.github/workflows/template-versions-smoke-tests.yml@main
diff --git a/.github/workflows/pr-e2e-checker.yml b/.github/workflows/pr-e2e-checker.yml
index 53b5d6a20..db92f8ba7 100644
--- a/.github/workflows/pr-e2e-checker.yml
+++ b/.github/workflows/pr-e2e-checker.yml
@@ -8,6 +8,9 @@ on:
 env:
   SKIP_E2E_TAG: skip-e2e
   E2E_CHECK_NAME: e2e tests
+  ARM_SMOKE_CHECK_NAME: ARM smoke tests
+  S390X_SMOKE_CHECK_NAME: S390x smoke tests
+
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@@ -37,3 +40,43 @@ jobs:
           conclusion: success
           output: |
             {"summary": "skipped by maintainer"}
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Enqueue e2e
+        id: create-arm
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          status: queued
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Skip e2e
+        if: ${{ contains(github.event.pull_request.labels.*.name, env.SKIP_E2E_TAG )}}
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          check_id: ${{ steps.create-arm.outputs.check_id }}
+          conclusion: success
+          output: |
+            {"summary": "skipped by maintainer"}
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Enqueue e2e
+        id: create-s390x
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          status: queued
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Skip e2e
+        if: ${{ contains(github.event.pull_request.labels.*.name, env.SKIP_E2E_TAG )}}
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          check_id: ${{ steps.create-s390x.outputs.check_id }}
+          conclusion: success
+          output: |
+            {"summary": "skipped by maintainer"}
diff --git a/.github/workflows/pr-e2e-creator.yml b/.github/workflows/pr-e2e-creator.yml
index f26368316..9fd47617a 100644
--- a/.github/workflows/pr-e2e-creator.yml
+++ b/.github/workflows/pr-e2e-creator.yml
@@ -8,6 +8,8 @@ on:
 env:
   SKIP_E2E_TAG: skip-e2e
   E2E_CHECK_NAME: e2e tests
+  ARM_SMOKE_CHECK_NAME: ARM smoke tests
+  S390X_SMOKE_CHECK_NAME: S390x smoke tests
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@@ -37,3 +39,43 @@ jobs:
           conclusion: success
           output: |
             {"summary": "skipped by maintainer"}
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Enqueue e2e
+        id: create-arm
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          status: queued
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Skip e2e
+        if: ${{ contains(github.event.pull_request.labels.*.name, env.SKIP_E2E_TAG )}}
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          check_id: ${{ steps.create-arm.outputs.check_id }}
+          conclusion: success
+          output: |
+            {"summary": "skipped by maintainer"}
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Enqueue e2e
+        id: create-s390x
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          status: queued
+
+      - uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        name: Skip e2e
+        if: ${{ contains(github.event.pull_request.labels.*.name, env.SKIP_E2E_TAG )}}
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ github.event.pull_request.head.sha }}
+          check_id: ${{ steps.create-s390x.outputs.check_id }}
+          conclusion: success
+          output: |
+            {"summary": "skipped by maintainer"}
diff --git a/.github/workflows/pr-e2e.yml b/.github/workflows/pr-e2e.yml
index a6d776ce9..432e9746a 100644
--- a/.github/workflows/pr-e2e.yml
+++ b/.github/workflows/pr-e2e.yml
@@ -5,6 +5,8 @@ on:
 
 env:
   E2E_CHECK_NAME: e2e tests
+  ARM_SMOKE_CHECK_NAME: ARM smoke tests
+  S390X_SMOKE_CHECK_NAME: S390x smoke tests
 
 jobs:
   triage:
@@ -81,6 +83,24 @@ jobs:
           status: in_progress
           details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
 
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          status: in_progress
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          status: in_progress
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 
       - name: Register workspace path
@@ -126,6 +146,24 @@ jobs:
           conclusion: failure
           details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
 
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          status: failure
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          status: failure
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
       - name: Exit on failure
         if: steps.regex-validation.outcome != 'success'
         run: exit 1
@@ -141,11 +179,11 @@ jobs:
           registry: ghcr.io
 
       - name: Publish on GitHub Container Registry
-        run: make publish
+        run: make publish-multiarch
         env:
           E2E_IMAGE_TAG: ${{ needs.triage.outputs.image_tag }}
 
-  run-test:
+  run-e2e-test:
     needs: [triage, build-test-images]
     runs-on: e2e
     name: Execute e2e tests
@@ -260,3 +298,184 @@ jobs:
           name: e2e-test-logs
           path: "${{ github.workspace }}/**/*.log"
           if-no-files-found: ignore
+
+  run-arm-smoke-test:
+    needs: [triage, build-test-images]
+    runs-on: ARM64
+    name: Execute ARM smoke tests
+    if: needs.triage.outputs.run-e2e == 'true'
+    steps:
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          status: in_progress
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Setup Go
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
+        with:
+          go-version: "1.23"
+
+      - name: Install prerequisites
+        run: |
+          sudo apt update
+          sudo apt install curl make ca-certificates gcc libc-dev wget -y
+        env:
+          DEBIAN_FRONTEND: noninteractive
+
+      - name: Check out code
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+        with:
+          fetch-depth: 1
+
+      - name: Create k8s ${{ inputs.kubernetesVersion }} Kind Cluster
+        uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0
+        with:
+          node_image: kindest/node:v1.32.0@sha256:c48c62eac5da28cdadcf560d1d8616cfa6783b58f0d94cf63ad1bf49600cb027
+          cluster_name: smoke-tests-cluster-pr
+
+      - name: Run smoke test
+        run: make smoke-test
+        id: test
+
+      - name: React to comment with success
+        uses: dkershner6/reaction-action@97ede302a1b145b3739dec3ca84a489a34ef48b5 # v2
+        if: steps.test.outcome == 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          commentId: ${{ github.event.comment.id }}
+          reaction: "+1"
+
+      - name: Set status success
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        if: steps.test.outcome == 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          conclusion: success
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: React to comment with failure
+        uses: dkershner6/reaction-action@97ede302a1b145b3739dec3ca84a489a34ef48b5 # v2
+        if: steps.test.outcome != 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          commentId: ${{ github.event.comment.id }}
+          reaction: "-1"
+
+      - name: Set status failure
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        if: steps.test.outcome != 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.ARM_SMOKE_CHECK_NAME }}
+          conclusion: failure
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Upload test logs
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+        with:
+          name: arm-smoke-test-logs
+          path: "${{ github.workspace }}/**/*.log"
+          if-no-files-found: ignore
+
+  run-s390x-smoke-test:
+    needs: [triage, build-test-images]
+    runs-on: s390x
+    name: Execute s390x smoke tests
+    if: needs.triage.outputs.run-e2e == 'true'
+    steps:
+      - name: Set status in-progress
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          status: in_progress
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Setup Go
+        uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5
+        with:
+          go-version: "1.23"
+
+      - name: Install prerequisites
+        run: |
+          apt update
+          apt install curl make ca-certificates gcc libc-dev wget -y
+        env:
+          DEBIAN_FRONTEND: noninteractive
+
+      - name: Check out code
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+        with:
+          fetch-depth: 1
+
+      - name: Install Kubernetes
+        run: |
+          go install sigs.k8s.io/kind@v0.29.0
+          kind create cluster --name kind-s390x --image vishnubijukumar/kindest-node-s390x:v0.29.0
+          curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/s390x/kubectl"
+          chmod +x kubectl
+          mkdir -p ~/.local/bin
+          mv ./kubectl ~/.local/bin/kubectl
+          kubectl version
+
+      - name: Run smoke test
+        run: make smoke-test
+        id: test
+
+      - name: React to comment with success
+        uses: dkershner6/reaction-action@97ede302a1b145b3739dec3ca84a489a34ef48b5 # v2
+        if: steps.test.outcome == 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          commentId: ${{ github.event.comment.id }}
+          reaction: "+1"
+
+      - name: Set status success
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        if: steps.test.outcome == 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          conclusion: success
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: React to comment with failure
+        uses: dkershner6/reaction-action@97ede302a1b145b3739dec3ca84a489a34ef48b5 # v2
+        if: steps.test.outcome != 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          commentId: ${{ github.event.comment.id }}
+          reaction: "-1"
+
+      - name: Set status failure
+        uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2
+        if: steps.test.outcome != 'success'
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          sha: ${{ needs.triage.outputs.commit_sha }}
+          name: ${{ env.S390X_SMOKE_CHECK_NAME }}
+          conclusion: failure
+          details_url: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
+
+      - name: Remove Kubernetes
+        run: |
+          kind delete cluster --name kind-s390x
+        if: ${{ always() }}
+        env:
+          DEBIAN_FRONTEND: noninteractive
+
+      - name: Upload test logs
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+        with:
+          name: s390x-smoke-test-logs
+          path: "${{ github.workspace }}/**/*.log"
+          if-no-files-found: ignore
diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml
index dd95a4714..9c542e2df 100644
--- a/.github/workflows/pr-validation.yml
+++ b/.github/workflows/pr-validation.yml
@@ -18,6 +18,8 @@ jobs:
             name: arm64
           - runner: ubuntu-latest
             name: amd64
+          - runner: s390x
+            name: s390x
     steps:
       - name: Check out code
         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -93,6 +95,8 @@ jobs:
             name: arm64
           - runner: ubuntu-latest
             name: amd64
+          - runner: s390x
+            name: s390x
     steps:
       - name: Check out code
         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -127,6 +131,8 @@ jobs:
             name: arm64
           - runner: ubuntu-latest
             name: amd64
+          - runner: s390x
+            name: s390x
     steps:
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 
diff --git a/.github/workflows/template-s390x-smoke-tests.yml b/.github/workflows/template-s390x-smoke-tests.yml
new file mode 100644
index 000000000..47b25f9f2
--- /dev/null
+++ b/.github/workflows/template-s390x-smoke-tests.yml
@@ -0,0 +1,54 @@
+name: Reusable workflow to run smoke tests on s390x
+
+on:
+  workflow_call:
+
+jobs:
+  smoke-tests-s390x:
+    name: Validate k8s
+    runs-on: s390x
+    steps:
+      - name: Setup Go
+        uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5
+        with:
+          go-version: "1.23"
+
+      - name: Install prerequisites
+        run: |
+          apt update
+          apt install curl make ca-certificates gcc libc-dev wget -y
+        env:
+          DEBIAN_FRONTEND: noninteractive
+
+      - name: Check out code
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+        with:
+          fetch-depth: 1
+
+      - name: Install Kubernetes
+        run: |
+          go install sigs.k8s.io/kind@v0.29.0
+          kind create cluster --name kind-s390x --image vishnubijukumar/kindest-node-s390x:v0.29.0
+          curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/s390x/kubectl"
+          chmod +x kubectl
+          mkdir -p ~/.local/bin
+          mv ./kubectl ~/.local/bin/kubectl
+          kubectl version
+
+      - name: Run smoke test
+        run: make smoke-test
+
+      - name: Upload test logs
+        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
+        if: ${{ always() }}
+        with:
+          name: smoke-test-logs ${{ inputs.runs-on }}-${{ inputs.kubernetesVersion }}
+          path: "${{ github.workspace }}/**/*.log"
+          if-no-files-found: ignore
+
+      - name: Remove Kubernetes
+        run: |
+          kind delete cluster --name kind-s390x
+        if: ${{ always() }}
+        env:
+          DEBIAN_FRONTEND: noninteractive
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 445a3e2ff..52c5963dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,7 +61,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
 
 ### New
 
-- TODO ([#XXX](https://github.com/kedacore/keda/issues/XXX))
+- Enable support on s390x for KEDA ([#6543](https://github.com/kedacore/keda/issues/6543))
 
 #### Experimental
 
diff --git a/Makefile b/Makefile
index 117ce76af..45d6980f9 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ ARCH       ?=amd64
 CGO        ?=0
 TARGET_OS  ?=linux
 
-BUILD_PLATFORMS ?= linux/amd64,linux/arm64
+BUILD_PLATFORMS ?= linux/amd64,linux/arm64,linux/s390x
 OUTPUT_TYPE     ?= registry
 
 GIT_VERSION ?= $(shell git describe --always --abbrev=7)



Test patch:
diff --git a/tests/run-smoke-tests.sh b/tests/run-smoke-tests.sh
index bbf9bc39c..9738b7e98 100755
--- a/tests/run-smoke-tests.sh
+++ b/tests/run-smoke-tests.sh
@@ -4,10 +4,11 @@ set -u
 DIR=$(dirname "$0")
 cd $DIR
 
-# use only e2e test which support running on ARM
+export E2E_INSTALL_KAFKA="false"
+
+# use only e2e test which support running on ARM and s390x
 test_files=(
     "scalers/kubernetes_workload/kubernetes_workload_test.go"
-    "scalers/activemq/activemq_test.go"
     "scalers/cron/cron_test.go"
 )