From 090d6450307e452e0f8e9730fe12d29fe4ab7219 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Wed, 24 Dec 2025 19:53:42 -0500 Subject: [PATCH 1/4] feat(ci): Add support for multi-architecture builds and package image manifest. --- .../clp-build-runtime-image/action.yaml | 7 +- .github/workflows/clp-artifact-build.yaml | 148 ++++++++++++++---- 2 files changed, 124 insertions(+), 31 deletions(-) diff --git a/.github/actions/clp-build-runtime-image/action.yaml b/.github/actions/clp-build-runtime-image/action.yaml index 32e984bfa9..e53b7040bf 100644 --- a/.github/actions/clp-build-runtime-image/action.yaml +++ b/.github/actions/clp-build-runtime-image/action.yaml @@ -21,6 +21,10 @@ inputs: description: "Platform VERSION_ID / VERSION_CODENAME of the container (e.g. jammy, focal, etc.)" required: false + arch: + description: "Target architecture (amd64 or arm64)" + default: "amd64" + required: false runs: using: "composite" @@ -68,6 +72,7 @@ runs: with: context: "./" file: "${{steps.compute-meta.outputs.DOCKERFILE}}" + platforms: "linux/${{inputs.arch}}" push: true - tags: "${{steps.extract-gh-meta.outputs.tags}}" + tags: "${{steps.extract-gh-meta.outputs.tags}}-${{inputs.arch}}" labels: "${{steps.extract-gh-meta.outputs.labels}}" diff --git a/.github/workflows/clp-artifact-build.yaml b/.github/workflows/clp-artifact-build.yaml index b47b0369a7..d70e0ed0bb 100644 --- a/.github/workflows/clp-artifact-build.yaml +++ b/.github/workflows/clp-artifact-build.yaml @@ -16,7 +16,8 @@ on: env: BINARIES_ARTIFACT_NAME_PREFIX: "clp-core-binaries-" - DEPS_IMAGE_NAME_PREFIX: "clp-core-dependencies-x86-" + DEPS_IMAGE_NAME_PREFIX_AMD64: "clp-core-dependencies-x86-" + DEPS_IMAGE_NAME_PREFIX_ARM64: "clp-core-dependencies-arm64-" concurrency: group: "${{github.workflow}}-${{github.ref}}" @@ -28,7 +29,7 @@ concurrency: jobs: filter-relevant-changes: name: "filter-relevant-changes" - runs-on: &runner >- + runs-on: &runner-amd64 >- ${{ github.repository_owner == 'y-scope' && fromJSON('["self-hosted", "x64", "ubuntu-noble"]') @@ -104,7 +105,7 @@ jobs: name: "centos-stream-9-deps-image" if: "needs.filter-relevant-changes.outputs.centos_stream_9_image_changed == 'true'" needs: "filter-relevant-changes" - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -118,7 +119,7 @@ jobs: env: OS_NAME: "centos-stream-9" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" docker_context: "components/core" docker_file: "components/core/tools/docker-images/clp-env-base-${{env.OS_NAME}}\ /Dockerfile" @@ -130,7 +131,7 @@ jobs: name: "manylinux_2_28-x86_64-deps-image" if: "needs.filter-relevant-changes.outputs.manylinux_2_28_x86_64_image_changed == 'true'" needs: "filter-relevant-changes" - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -144,7 +145,7 @@ jobs: env: OS_NAME: "manylinux_2_28" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" docker_context: "components/core" docker_file: "components/core/tools/docker-images/clp-env-base-${{env.OS_NAME}}-x86_64\ /Dockerfile" @@ -156,7 +157,7 @@ jobs: name: "musllinux_1_2-x86_64-deps-image" if: "needs.filter-relevant-changes.outputs.musllinux_1_2_x86_64_image_changed == 'true'" needs: "filter-relevant-changes" - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -170,7 +171,7 @@ jobs: env: OS_NAME: "musllinux_1_2" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" docker_context: "components/core" docker_file: "components/core/tools/docker-images/clp-env-base-${{env.OS_NAME}}-x86_64\ /Dockerfile" @@ -178,11 +179,11 @@ jobs: ${{github.event_name != 'pull_request' && github.ref == 'refs/heads/main'}} token: "${{secrets.GITHUB_TOKEN}}" - ubuntu-jammy-deps-image: - name: "ubuntu-jammy-deps-image" + ubuntu-jammy-amd64-deps-image: + name: "ubuntu-jammy-amd64-deps-image" if: "needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'true'" needs: "filter-relevant-changes" - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -196,7 +197,38 @@ jobs: env: OS_NAME: "ubuntu-jammy" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" + docker_context: "components/core" + docker_file: "components/core/tools/docker-images/clp-env-base-${{env.OS_NAME}}\ + /Dockerfile" + push_deps_image: >- + ${{github.event_name != 'pull_request' && github.ref == 'refs/heads/main'}} + token: "${{secrets.GITHUB_TOKEN}}" + + ubuntu-jammy-arm64-deps-image: + name: "ubuntu-jammy-arm64-deps-image" + if: "needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'true'" + needs: "filter-relevant-changes" + runs-on: &runner-arm64 >- + ${{ + github.repository_owner == 'y-scope' + && fromJSON('["self-hosted", "arm64", "ubuntu-noble"]') + || 'ubuntu-24.04-arm' + }} + steps: + - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" + with: + submodules: "recursive" + + - name: "Work around actions/runner-images/issues/6775" + run: "chown $(id -u):$(id -g) -R ." + shell: "bash" + + - uses: "./.github/actions/clp-core-build-containers" + env: + OS_NAME: "ubuntu-jammy" + with: + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_ARM64}}${{env.OS_NAME}}" docker_context: "components/core" docker_file: "components/core/tools/docker-images/clp-env-base-${{env.OS_NAME}}\ /Dockerfile" @@ -217,7 +249,7 @@ jobs: use_shared_libs: [true, false] name: "centos-stream-9-${{matrix.use_shared_libs == true && 'dynamic' || 'static'}}-linked-bins" continue-on-error: true - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -231,7 +263,7 @@ jobs: env: OS_NAME: "centos-stream-9" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" use_published_image: >- ${{needs.filter-relevant-changes.outputs.centos_stream_9_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -257,7 +289,7 @@ jobs: name: >- manylinux_2_28-x86_64-${{matrix.use_shared_libs == true && 'dynamic' || 'static'}}-linked-bins continue-on-error: true - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -271,7 +303,7 @@ jobs: env: OS_NAME: "manylinux_2_28" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" use_published_image: >- ${{needs.filter-relevant-changes.outputs.manylinux_2_28_x86_64_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -297,7 +329,7 @@ jobs: name: >- musllinux_1_2-x86_64-${{matrix.use_shared_libs == true && 'dynamic' || 'static'}}-linked-bins continue-on-error: true - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -311,7 +343,7 @@ jobs: env: OS_NAME: "musllinux_1_2" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" use_published_image: >- ${{needs.filter-relevant-changes.outputs.musllinux_1_2_x86_64_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -330,7 +362,7 @@ jobs: || (!cancelled() && !failure() && needs.filter-relevant-changes.outputs.clp_changed == 'true') needs: - "filter-relevant-changes" - - "ubuntu-jammy-deps-image" + - "ubuntu-jammy-amd64-deps-image" strategy: matrix: include: @@ -342,7 +374,7 @@ jobs: OS_NAME: "ubuntu-jammy" name: "ubuntu-jammy-${{matrix.use_shared_libs == true && 'dynamic' || 'static'}}-linked-bins" continue-on-error: true - runs-on: *runner + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -354,7 +386,7 @@ jobs: - uses: "./.github/actions/run-on-image" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" use_published_image: >- ${{needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -389,7 +421,7 @@ jobs: # Run if the ancestor jobs were successful/skipped and building clp was successful. if: "!cancelled() && !failure() && needs.ubuntu-jammy-binaries.result == 'success'" needs: "ubuntu-jammy-binaries" - runs-on: *runner + runs-on: *runner-amd64 env: OS_NAME: "ubuntu-jammy" TMP_OUTPUT_DIR: "/tmp" @@ -455,8 +487,8 @@ jobs: || (!cancelled() && !failure() && needs.filter-relevant-changes.outputs.clp_changed == 'true') needs: - "filter-relevant-changes" - - "ubuntu-jammy-deps-image" - runs-on: *runner + - "ubuntu-jammy-amd64-deps-image" + runs-on: *runner-amd64 steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -491,7 +523,7 @@ jobs: env: OS_NAME: "ubuntu-jammy" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: "${{env.DEPS_IMAGE_NAME_PREFIX_AMD64}}${{env.OS_NAME}}" use_published_image: >- ${{needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -524,16 +556,36 @@ jobs: )}} package-image: - name: "package-image" + name: "package-image-${{matrix.arch}}" if: >- !cancelled() && !failure() && ( needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'false' || - needs.ubuntu-jammy-deps-image.result == 'success' + (needs.ubuntu-jammy-amd64-deps-image.result == 'success' + && needs.ubuntu-jammy-arm64-deps-image.result == 'success') ) needs: - "filter-relevant-changes" - - "ubuntu-jammy-deps-image" - runs-on: *runner + - "ubuntu-jammy-amd64-deps-image" + - "ubuntu-jammy-arm64-deps-image" + strategy: + matrix: + include: + - arch: "amd64" + runner: "runner-amd64" + deps_image_prefix_env: "DEPS_IMAGE_NAME_PREFIX_AMD64" + - arch: "arm64" + runner: "runner-arm64" + deps_image_prefix_env: "DEPS_IMAGE_NAME_PREFIX_ARM64" + runs-on: >- + ${{ + matrix.arch == 'amd64' + && (github.repository_owner == 'y-scope' + && fromJSON('["self-hosted", "x64", "ubuntu-noble"]') + || 'ubuntu-24.04') + || (github.repository_owner == 'y-scope' + && fromJSON('["self-hosted", "arm64", "ubuntu-noble"]') + || 'ubuntu-24.04-arm') + }} steps: - uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" with: @@ -548,7 +600,10 @@ jobs: env: OS_NAME: "ubuntu-jammy" with: - image_name: "${{env.DEPS_IMAGE_NAME_PREFIX}}${{env.OS_NAME}}" + image_name: >- + ${{matrix.arch == 'amd64' + && format('{0}{1}', env.DEPS_IMAGE_NAME_PREFIX_AMD64, 'ubuntu-jammy') + || format('{0}{1}', env.DEPS_IMAGE_NAME_PREFIX_ARM64, 'ubuntu-jammy')}} use_published_image: >- ${{needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'false' || (github.event_name != 'pull_request' && github.ref == 'refs/heads/main')}} @@ -562,3 +617,36 @@ jobs: image_registry: "ghcr.io" image_registry_username: "${{github.actor}}" image_registry_password: "${{secrets.GITHUB_TOKEN}}" + arch: "${{matrix.arch}}" + + package-image-multiarch-manifest: + name: "package-image-multiarch-manifest" + if: "github.event_name != 'pull_request' && github.ref == 'refs/heads/main'" + needs: "package-image" + runs-on: *runner-amd64 + steps: + - name: "Login to Image Registry" + uses: "docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772" + with: + registry: "ghcr.io" + username: "${{github.actor}}" + password: "${{secrets.GITHUB_TOKEN}}" + + - name: "Sanitize Repository Name" + id: "sanitization" + shell: "bash" + run: | + echo "REPOSITORY=$(echo '${{github.repository}}' | tr '[:upper:]' '[:lower:]')" \ + >> "$GITHUB_OUTPUT" + + - name: "Create and Push Multi-arch Manifest" + shell: "bash" + run: | + image_base="ghcr.io/${{steps.sanitization.outputs.REPOSITORY}}/clp-package" + tag="${{github.ref_name}}" + + docker manifest create "${image_base}:${tag}" \ + "${image_base}:${tag}-amd64" \ + "${image_base}:${tag}-arm64" + + docker manifest push "${image_base}:${tag}" From cb79af129fa42cdfff6f360c94de98953d65e520 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Fri, 26 Dec 2025 03:55:08 -0500 Subject: [PATCH 2/4] fix(ci): Simplify runner configuration and matrix strategy for ARM64 build. --- .github/workflows/clp-artifact-build.yaml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/clp-artifact-build.yaml b/.github/workflows/clp-artifact-build.yaml index d70e0ed0bb..93babbcaf8 100644 --- a/.github/workflows/clp-artifact-build.yaml +++ b/.github/workflows/clp-artifact-build.yaml @@ -209,7 +209,7 @@ jobs: name: "ubuntu-jammy-arm64-deps-image" if: "needs.filter-relevant-changes.outputs.ubuntu_jammy_image_changed == 'true'" needs: "filter-relevant-changes" - runs-on: &runner-arm64 >- + runs-on: >- ${{ github.repository_owner == 'y-scope' && fromJSON('["self-hosted", "arm64", "ubuntu-noble"]') @@ -569,13 +569,7 @@ jobs: - "ubuntu-jammy-arm64-deps-image" strategy: matrix: - include: - - arch: "amd64" - runner: "runner-amd64" - deps_image_prefix_env: "DEPS_IMAGE_NAME_PREFIX_AMD64" - - arch: "arm64" - runner: "runner-arm64" - deps_image_prefix_env: "DEPS_IMAGE_NAME_PREFIX_ARM64" + arch: ["amd64", "arm64"] runs-on: >- ${{ matrix.arch == 'amd64' From ffabab7ae6c74e83be2968eb997646f1b55e6d05 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Fri, 26 Dec 2025 05:08:19 -0500 Subject: [PATCH 3/4] fix(ci): Disable provenance for runtime image builds to support multi-arch manifest creation. --- .github/actions/clp-build-runtime-image/action.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/clp-build-runtime-image/action.yaml b/.github/actions/clp-build-runtime-image/action.yaml index e53b7040bf..cf7aae8bf9 100644 --- a/.github/actions/clp-build-runtime-image/action.yaml +++ b/.github/actions/clp-build-runtime-image/action.yaml @@ -73,6 +73,9 @@ runs: context: "./" file: "${{steps.compute-meta.outputs.DOCKERFILE}}" platforms: "linux/${{inputs.arch}}" + # Disable provenance to create a simple image instead of a manifest list. + # This allows `docker manifest create` to combine the per-arch images. + provenance: false push: true tags: "${{steps.extract-gh-meta.outputs.tags}}-${{inputs.arch}}" labels: "${{steps.extract-gh-meta.outputs.labels}}" From 5a035f846c0f0d0acef2ad7303e3498a5ebf2b54 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Tue, 6 Jan 2026 19:26:34 -0500 Subject: [PATCH 4/4] fix(ci): Add dependency check for multi-arch manifest packaging step. --- .github/workflows/clp-artifact-build.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clp-artifact-build.yaml b/.github/workflows/clp-artifact-build.yaml index 93babbcaf8..8dfb41a3c1 100644 --- a/.github/workflows/clp-artifact-build.yaml +++ b/.github/workflows/clp-artifact-build.yaml @@ -615,7 +615,10 @@ jobs: package-image-multiarch-manifest: name: "package-image-multiarch-manifest" - if: "github.event_name != 'pull_request' && github.ref == 'refs/heads/main'" + if: >- + github.event_name != 'pull_request' + && github.ref == 'refs/heads/main' + && needs.package-image.result == 'success' needs: "package-image" runs-on: *runner-amd64 steps: