Skip to content
111 changes: 111 additions & 0 deletions .github/workflows/ci-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: Build CI Image

on:
pull_request:
paths:
- "containers/ci/**"
- ".github/workflows/ci-image.yml"

push:
branches:
- main
paths:
- "containers/ci/**"
- ".github/workflows/ci-image.yml"

workflow_dispatch:
inputs:
publish_candidate:
description: "Publish CI image candidate from main to GHCR"
required: true
type: boolean
default: false

permissions:
contents: read

env:
REGISTRY: ghcr.io
IMAGE_NAME: openamrobot/ci-ros2-jazzy

jobs:
# Untrusted PR code can build, but has read-only repository permissions
# and never receives registry credentials or packages: write.
build:
name: Validate CI image
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04

permissions:
contents: read

steps:
- name: Check out repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

- name: Validate Docker image without publishing
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
file: containers/ci/Dockerfile
platforms: linux/amd64
push: false

# Only trusted main-branch code may publish to GHCR.
publish:
name: Publish CI image
if: >-
(github.event_name == 'push' &&
github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' &&
github.ref == 'refs/heads/main' &&
inputs.publish_candidate == true)
runs-on: ubuntu-24.04

permissions:
contents: read
packages: write

steps:
- name: Check out repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

- name: Log in to GHCR
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and publish image
id: build
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
file: containers/ci/Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event_name == 'push' && 'latest' || format('candidate-{0}', github.sha) }}

- name: Record published image digest
env:
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
run: |
echo "Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
echo "Digest: $IMAGE_DIGEST"
echo "Pinned reference: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@$IMAGE_DIGEST"
{
echo "### ROS 2 CI image publication"
echo "Run ID: ${{ github.run_id }}"
echo "Source SHA: ${{ github.sha }}"
echo "Digest: $IMAGE_DIGEST"
echo "Pinned: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@$IMAGE_DIGEST\`"
} >> "$GITHUB_STEP_SUMMARY"
56 changes: 56 additions & 0 deletions containers/ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
FROM ros:jazzy-ros-base@sha256:066420e07f60aa18262f2479981def87ebcfcec42eefb0c0c57c4a46098348ca

ARG DEBIAN_FRONTEND=noninteractive

# LiDAR driver policy:
# Do not install the legacy ros-jazzy-rplidar-ros package in this baseline.
# OpenAMRobot 2.0 targets RPLIDAR S3 using sllidar_ros2.
# The S3 source driver is being pinned via openamrobot-manifest PR #18;
# its installation and hardware validation are separate from this baseline.
# camera_ros is intentionally retained for the existing robot: the
# openamrobot_perception/package.xml declares an exec_depend on camera_ros,
# and its IMX708 real-robot launch runs camera_ros/camera_node.
# OpenAMRobot 2.0's Gemini 336L/Orbbec path has separate driver integration.
#
# Common CI and ROS workspace tooling
RUN apt-get update && apt-get install -y --no-install-recommends \
python3-colcon-common-extensions \
python3-rosdep \
python3-vcstool \
git \
curl \
\
# Platform ROS dependencies \
ros-jazzy-nav2-bringup \
ros-jazzy-nav2-common \
ros-jazzy-slam-toolbox \
ros-jazzy-nav2-bt-navigator \
ros-jazzy-nav2-behaviors \
ros-jazzy-nav2-controller \
ros-jazzy-nav2-lifecycle-manager \
ros-jazzy-nav2-map-server \
ros-jazzy-nav2-amcl \
ros-jazzy-nav2-planner \
ros-jazzy-nav2-smoother \
ros-jazzy-nav2-waypoint-follower \
ros-jazzy-nav2-velocity-smoother \
ros-jazzy-nav2-collision-monitor \
ros-jazzy-opennav-docking \
ros-jazzy-laser-filters \
ros-jazzy-rviz2 \
ros-jazzy-twist-mux \
ros-jazzy-camera-ros \
ros-jazzy-joint-state-publisher \
ros-jazzy-joint-state-publisher-gui \
ros-jazzy-xacro \
ros-jazzy-ros-gz-sim \
ros-jazzy-ros-gz-bridge \
ros-jazzy-apriltag-msgs \
ros-jazzy-apriltag-ros \
ros-jazzy-nav2-msgs \
ros-jazzy-robot-localization \
ros-jazzy-topic-tools \
ros-jazzy-rmw-cyclonedds-cpp \
&& rm -rf /var/lib/apt/lists/*

ENV RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
Loading