Skip to content

Ubuntu: Build multi-arch docker images for x86 and arm #174

Ubuntu: Build multi-arch docker images for x86 and arm

Ubuntu: Build multi-arch docker images for x86 and arm #174

---
name: Build and publish Ubuntu docker images
on:
workflow_dispatch:
push:
branches:
- master
paths:
- '.github/workflows/build_and_publish_ubuntu_docker.yaml'
- 'ros2_ubuntu/**'
pull_request:
paths:
- '.github/workflows/build_and_publish_ubuntu_docker.yaml'
- 'ros2_ubuntu/**'
schedule:
- cron: '1 2 * * MON'
concurrency:
# cancel previous runs of the same workflow, except for pushes on given branches
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/heads') }}
jobs:
# Fork pull requests only get a read-only GITHUB_TOKEN, so they cannot push.
config:
runs-on: ubuntu-latest
outputs:
push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
tag_suffix: ${{ github.event_name == 'pull_request' && format('-pr-{0}', github.event.pull_request.number) || '' }}
steps:
- run: echo "push=${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}"
build_images:
needs: config
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
# humble
- ros_distro: 'humble'
base_image: 'ubuntu:jammy'
ros-repo-packages: ""
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'humble'
base_image: 'ubuntu:jammy'
ros-repo-packages: ""
runner: ubuntu-24.04-arm
platform: linux/arm64
- ros_distro: 'humble'
base_image: 'ubuntu:jammy'
ros-repo-packages: "-testing"
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'humble'
base_image: 'ubuntu:jammy'
ros-repo-packages: "-testing"
runner: ubuntu-24.04-arm
platform: linux/arm64
# jazzy
- ros_distro: 'jazzy'
base_image: 'ubuntu:noble'
ros-repo-packages: ""
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'jazzy'
base_image: 'ubuntu:noble'
ros-repo-packages: ""
runner: ubuntu-24.04-arm
platform: linux/arm64
- ros_distro: 'jazzy'
base_image: 'ubuntu:noble'
ros-repo-packages: "-testing"
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'jazzy'
base_image: 'ubuntu:noble'
ros-repo-packages: "-testing"
runner: ubuntu-24.04-arm
platform: linux/arm64
# kilted
- ros_distro: 'kilted'
base_image: 'ubuntu:noble'
ros-repo-packages: ""
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'kilted'
base_image: 'ubuntu:noble'
ros-repo-packages: ""
runner: ubuntu-24.04-arm
platform: linux/arm64
- ros_distro: 'kilted'
base_image: 'ubuntu:noble'
ros-repo-packages: "-testing"
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'kilted'
base_image: 'ubuntu:noble'
ros-repo-packages: "-testing"
runner: ubuntu-24.04-arm
platform: linux/arm64
# lyrical
- ros_distro: 'lyrical'
base_image: 'ubuntu:resolute'
ros-repo-packages: ""
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'lyrical'
base_image: 'ubuntu:resolute'
ros-repo-packages: ""
runner: ubuntu-24.04-arm
platform: linux/arm64
- ros_distro: 'lyrical'
base_image: 'ubuntu:resolute'
ros-repo-packages: "-testing"
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'lyrical'
base_image: 'ubuntu:resolute'
ros-repo-packages: "-testing"
runner: ubuntu-24.04-arm
platform: linux/arm64
# rolling
- ros_distro: 'rolling'
base_image: 'ubuntu:resolute'
ros-repo-packages: "-testing"
runner: ubuntu-latest
platform: linux/amd64
- ros_distro: 'rolling'
base_image: 'ubuntu:resolute'
ros-repo-packages: "-testing"
runner: ubuntu-24.04-arm
platform: linux/arm64
steps:
- name: Set platform slug
run: echo "PLATFORM_PAIR=${PLATFORM//\//-}" >> "$GITHUB_ENV"
env:
PLATFORM: ${{ matrix.platform }}
- uses: actions/checkout@v7
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
if: needs.config.outputs.push == 'true'
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v7
with:
context: ros2_ubuntu
file: ros2_ubuntu/Dockerfile
platforms: ${{ matrix.platform }}
provenance: false
sbom: false
outputs: >-
${{ needs.config.outputs.push == 'true'
&& format(
'type=image,name=ghcr.io/{0}/ros,push-by-digest=true,name-canonical=true,push=true',
github.repository_owner
)
|| 'type=cacheonly' }}
cache-from: >-
type=gha,scope=ubuntu-${{ matrix.ros_distro }}-${{ matrix.ros-repo-packages }}-${{ env.PLATFORM_PAIR }}
cache-to: >-
type=gha,scope=ubuntu-${{ matrix.ros_distro }}-${{ matrix.ros-repo-packages }}-${{ env.PLATFORM_PAIR }},mode=max
build-args: |
FROM=${{ matrix.base_image }}
ROS_DISTRO=${{ matrix.ros_distro }}
ROS_REPO_PACKAGES=${{ matrix.ros-repo-packages }}
- name: Export digest
if: needs.config.outputs.push == 'true'
run: |
mkdir -p "${{ runner.temp }}/digests"
touch "${{ runner.temp }}/digests/${DIGEST#sha256:}"
env:
DIGEST: ${{ steps.build.outputs.digest }}
- uses: actions/upload-artifact@v4
if: needs.config.outputs.push == 'true'
with:
name: digests-${{ matrix.ros_distro }}-${{ matrix.ros-repo-packages }}-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
publish_manifests:
needs: [config, build_images]
if: needs.config.outputs.push == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
- ros_distro: humble
ros-repo-packages: ""
tag: humble-ubuntu
- ros_distro: jazzy
ros-repo-packages: ""
tag: jazzy-ubuntu
- ros_distro: kilted
ros-repo-packages: ""
tag: kilted-ubuntu
- ros_distro: lyrical
ros-repo-packages: ""
tag: lyrical-ubuntu
- ros_distro: humble
ros-repo-packages: "-testing"
tag: humble-ubuntu-testing
- ros_distro: jazzy
ros-repo-packages: "-testing"
tag: jazzy-ubuntu-testing
- ros_distro: kilted
ros-repo-packages: "-testing"
tag: kilted-ubuntu-testing
- ros_distro: lyrical
ros-repo-packages: "-testing"
tag: lyrical-ubuntu-testing
- ros_distro: rolling
ros-repo-packages: "-testing"
tag: rolling-ubuntu-testing
steps:
- uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-${{ matrix.ros_distro }}-${{ matrix.ros-repo-packages }}-*
merge-multiple: true
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest list
working-directory: ${{ runner.temp }}/digests
env:
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/ros
IMAGE_TAG: ${{ matrix.tag }}${{ needs.config.outputs.tag_suffix }}
run: |
docker buildx imagetools create \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
$(printf "${IMAGE_NAME}@sha256:%s " *)
- name: Inspect manifest list
env:
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/ros
IMAGE_TAG: ${{ matrix.tag }}${{ needs.config.outputs.tag_suffix }}
run: |
docker buildx imagetools inspect "${IMAGE_NAME}:${IMAGE_TAG}"
stack-build:
if: ${{ github.event_name == 'pull_request' }}
needs: publish_manifests
uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml
strategy:
fail-fast: false
matrix:
ROS_DISTRO: [rolling, humble, jazzy, kilted, lyrical]
ROS_REPO: [main, testing]
exclude:
- ROS_DISTRO: rolling
ROS_REPO: main
with:
target_cmake_args: -DROS2_CONTROL_STRICT_TIMING_TESTS=OFF
ros_distro: ${{ matrix.ROS_DISTRO }}
ros_repo: ${{ matrix.ROS_REPO }}
target_workspace: ros_controls.${{ matrix.ROS_DISTRO }}.repos
ref_for_scheduled_build: master
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}
compatibility-stack-build:
if: ${{ github.event_name == 'pull_request' }}
needs: publish_manifests
uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml
strategy:
fail-fast: false
matrix:
ROS_DISTRO: [kilted, humble, jazzy, lyrical]
ROS_REPO: [main, testing]
with:
target_cmake_args: -DROS2_CONTROL_STRICT_TIMING_TESTS=OFF
ros_distro: ${{ matrix.ROS_DISTRO }}
ros_repo: ${{ matrix.ROS_REPO }}
target_workspace: ros_controls.rolling-on-${{ matrix.ROS_DISTRO }}.repos
ref_for_scheduled_build: master
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}