chore(CI): enable multi arch docker image build (#37353)

This commit is contained in:
Rodrigo Nascimento 2025-11-05 20:24:20 -03:00 committed by GitHub
parent 64a4e8bbb7
commit 276ec516fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 188 additions and 29 deletions

View File

@ -13,6 +13,10 @@ inputs:
required: true
description: 'Deno version'
type: string
arch:
required: false
description: 'Architecture'
default: 'amd64'
service:
required: false
description: 'Container to build'
@ -46,7 +50,7 @@ runs:
password: ${{ inputs.CR_PAT }}
- name: Restore packages build
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: packages-build
path: /tmp
@ -58,7 +62,7 @@ runs:
- name: Restore meteor build
if: inputs.service == 'rocketchat'
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: build-${{ inputs.type }}
path: /tmp/build
@ -71,26 +75,64 @@ runs:
tar xzf Rocket.Chat.tar.gz
rm Rocket.Chat.tar.gz
- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: |
{
"debug": true,
"features": {
"containerd-snapshotter": true
}
}
- uses: docker/setup-buildx-action@v3
with:
buildkitd-flags: --oci-worker-gc --oci-worker-gc-keepstorage=4000
- name: Build Docker images
shell: bash
run: |
set -o xtrace
export DENO_VERSION="${{ inputs.deno-version }}"
docker compose -f docker-compose-ci.yml build ${{ inputs.service }}
- name: Publish Docker images to GitHub Container Registry
if: inputs.publish-image == 'true' && github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
shell: bash
run: |
set -o xtrace
if [[ "${{ inputs.publish-image }}" == 'true' ]]; then
LOAD_OR_PUSH="--push"
else
LOAD_OR_PUSH="--load"
fi
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${{ inputs.service }}" '.services[$s].image')
docker buildx bake \
-f docker-compose-ci.yml \
${LOAD_OR_PUSH} \
--allow=fs.read=/tmp/build \
--set "*.tags+=${IMAGE}-gha-run-${{ github.run_id }}" \
--set "*.labels.org.opencontainers.image.description=Build run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--set *.platform=linux/${{ inputs.arch }} \
--set *.cache-from=type=gha \
--set *.cache-to=type=gha,mode=max \
--provenance=false \
--sbom=false \
--metadata-file "/tmp/meta.json" \
"${{ inputs.service }}"
echo "Contents of /tmp/meta.json:"
cat /tmp/meta.json
mkdir -p /tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }}
DIGEST=$(jq -r '.["${{ inputs.service }}"].["containerimage.digest"]' "/tmp/meta.json")
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')
echo "${IMAGE_NO_TAG}@${DIGEST}" > "/tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }}/digest.txt"
docker tag ${IMAGE} ${IMAGE}-gha-run-${{ github.run_id }}
docker push --all-tags ${IMAGE_NO_TAG}
- uses: actions/upload-artifact@v4
if: inputs.publish-image == 'true'
with:
name: digests-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
path: /tmp/digests
retention-days: 5
- name: Clean up temporary files
if: inputs.service == 'rocketchat'

View File

@ -129,7 +129,7 @@ runs:
run: meteor reset
- name: Restore packages build
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: packages-build
path: /tmp

View File

@ -46,7 +46,7 @@ runs:
apps/meteor/ee/server/services/node_modules
packages/apps-engine/node_modules
packages/apps-engine/.deno-cache
key: node-modules-${{ hashFiles('yarn.lock') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}
key: node-modules-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('yarn.lock') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}
#
# Could use this command to list all paths to save:
# find . -name 'node_modules' -prune | grep -v "/\.meteor/" | grep -v "/meteor/packages/"

View File

@ -267,21 +267,23 @@ jobs:
build-gh-docker:
name: 🚢 Build Docker
needs: [build, release-versions]
runs-on: ubuntu-24.04
runs-on: ubuntu-24.04${{ matrix.arch == 'arm64' && '-arm' || '' }}
env:
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}-${{ matrix.arch }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}
strategy:
fail-fast: false
matrix:
arch: ['amd64', 'arm64']
service: ${{ fromJson(needs.release-versions.outputs.services) }}
type: ['production']
include:
# for rocketchat monolith and on develop branch builds we create a coverage image to run tests against it
# and keep the baseline of the coverage for other PRs
- service: rocketchat
- arch: amd64
service: rocketchat
type: coverage
steps:
@ -298,9 +300,79 @@ jobs:
node-version: ${{ needs.release-versions.outputs.node-version }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service }}
type: ${{ matrix.type }}
build-gh-docker-publish:
name: 🚢 Publish Docker Images (ghcr.io)
needs: [build-gh-docker, release-versions]
runs-on: ubuntu-24.04
env:
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}
steps:
- uses: actions/checkout@v4
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
with:
sparse-checkout: |
docker-compose-ci.yml
sparse-checkout-cone-mode: false
ref: ${{ github.ref }}
- name: Login to GitHub Container Registry
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}
- name: Download digests
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: actions/download-artifact@v6
with:
pattern: digests-*
path: /tmp/digests
merge-multiple: true
- name: Create and push multi-arch manifests
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
run: |
set -o xtrace
shopt -s nullglob
for service_dir in /tmp/digests/*; do
[[ -d "$service_dir" ]] || continue
service="$(basename "$service_dir")"
echo "Creating manifest for $service"
mapfile -t refs < <(
find "$service_dir" -type f -name 'digest.txt' -print0 \
| xargs -0 -I{} sh -c "tr -d '\r' < '{}' | sed '/^[[:space:]]*$/d'"
)
echo "Digest for ${service}: ${refs[@]}"
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
if [ "$service" == "rocketchat-cov" ]; then
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "rocketchat" '.services[$s].image')-cov
else
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$service" '.services[$s].image')
fi
echo $IMAGE
docker buildx imagetools create \
--debug \
--annotation "manifest-descriptor:org.opencontainers.image.description=Build run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--tag "${IMAGE}" \
--tag "${IMAGE}-gha-run-${{ github.run_id }}" \
${refs[@]}
done
checks:
needs: [release-versions, packages-build]
@ -335,7 +407,7 @@ jobs:
test-api:
name: 🔨 Test API (CE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]
uses: ./.github/workflows/ci-test-e2e.yml
with:
@ -351,7 +423,7 @@ jobs:
test-ui:
name: 🔨 Test UI (CE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]
uses: ./.github/workflows/ci-test-e2e.yml
with:
@ -376,7 +448,7 @@ jobs:
test-api-ee:
name: 🔨 Test API (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]
uses: ./.github/workflows/ci-test-e2e.yml
with:
@ -395,7 +467,7 @@ jobs:
test-ui-ee:
name: 🔨 Test UI (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]
uses: ./.github/workflows/ci-test-e2e.yml
with:
@ -422,7 +494,7 @@ jobs:
test-ui-ee-watcher:
name: 🔨 Test UI (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]
uses: ./.github/workflows/ci-test-e2e.yml
with:
@ -490,7 +562,7 @@ jobs:
name: 🚀 Publish build assets
runs-on: ubuntu-24.04
if: github.event_name == 'release' || github.ref == 'refs/heads/develop'
needs: [build-gh-docker, release-versions]
needs: [build-gh-docker-publish, release-versions]
steps:
- uses: actions/checkout@v5
@ -587,8 +659,13 @@ jobs:
- name: Pull Docker image
run: docker pull ${{ steps.gh-docker.outputs.gh-image-name }}
- name: Publish Docker image
- name: Publish Docker images
run: |
set -euo pipefail
sudo apt-get update -y
sudo apt-get install -y skopeo
if [[ '${{ matrix.service }}' == 'rocketchat' ]]; then
IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat"
else
@ -624,17 +701,25 @@ jobs:
echo "Tags: ${TAGS[*]}"
# get first tag as primary
PRIMARY="${TAGS[0]}"
SRC="${{ steps.gh-docker.outputs.gh-image-name }}"
DEST_REPO="docker.io/${IMAGE_NAME}"
if (( ${#TAGS[@]} > 0 )); then
for t in "${TAGS[@]:0}"; do
echo "Copying $SRC to ${DEST_REPO}:${t}"
docker tag $SRC "${DEST_REPO}:${t}"
# build --additional-tag for all other tags
EXTRA_ARGS=()
if (( ${#TAGS[@]} > 1 )); then
for t in "${TAGS[@]:1}"; do
EXTRA_ARGS+=( --additional-tag "${DEST_REPO}:${t}" )
done
fi
docker push --all-tags $DEST_REPO
echo "Copying $SRC to ${DEST_REPO}:${PRIMARY} with extras ${EXTRA_ARGS[*]}"
skopeo copy --all \
"docker://${SRC}" \
"docker://${DEST_REPO}:${PRIMARY}" \
"${EXTRA_ARGS[@]}"
notify-services:
name: 🚀 Notify external services

View File

@ -6,6 +6,10 @@ services:
build:
dockerfile: ${GITHUB_WORKSPACE}/apps/meteor/.docker/Dockerfile.alpine
context: /tmp/build
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
DENO_VERSION: ${DENO_VERSION}
image: ghcr.io/${LOWERCASE_REPOSITORY}/rocket.chat:${DOCKER_TAG}${DOCKER_TAG_SUFFIX_ROCKETCHAT}
@ -40,6 +44,10 @@ services:
build:
dockerfile: ee/apps/authorization-service/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: authorization-service
DENO_VERSION: ${DENO_VERSION}
@ -58,6 +66,10 @@ services:
build:
dockerfile: ee/apps/account-service/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: account-service
image: ghcr.io/${LOWERCASE_REPOSITORY}/account-service:${DOCKER_TAG}
@ -75,6 +87,10 @@ services:
build:
dockerfile: ee/apps/presence-service/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: presence-service
DENO_VERSION: ${DENO_VERSION}
@ -93,6 +109,10 @@ services:
build:
dockerfile: ee/apps/ddp-streamer/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: ddp-streamer
image: ghcr.io/${LOWERCASE_REPOSITORY}/ddp-streamer-service:${DOCKER_TAG}
@ -116,6 +136,10 @@ services:
build:
dockerfile: ee/apps/stream-hub-service/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: stream-hub-service
image: ghcr.io/${LOWERCASE_REPOSITORY}/stream-hub-service:${DOCKER_TAG}
@ -134,6 +158,10 @@ services:
build:
dockerfile: ee/apps/queue-worker/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: queue-worker
image: ghcr.io/${LOWERCASE_REPOSITORY}/queue-worker-service:${DOCKER_TAG}
@ -151,6 +179,10 @@ services:
build:
dockerfile: ee/apps/omnichannel-transcript/Dockerfile
context: .
x-bake:
platforms:
- linux/amd64
- linux/arm64
args:
SERVICE: omnichannel-transcript
image: ghcr.io/${LOWERCASE_REPOSITORY}/omnichannel-transcript-service:${DOCKER_TAG}