Skip to content

Commit 30847df

Browse files
Improve docker workflows and add rhel + debian stack build (#682)
* Split upstream and target workspace * Add stack build for debian and rhel * Use working-directory instead of base paths arguments * Add ccache * Skip mujoco and gz packages * fix(rhel8): enable powertools before installing ccache * Don't trigger stack builds if images will change * Fix step gate * Also skip ros2_control_demo_example_9 * Checkout repo in job * Add concurrency settings * Fix action input parser * Also skip ros2_control_demos meta package * Enable caching and dont replace default tags on PRs * Fix push event * Set the labels from the build-push-action instead * Run stack builds only on pull_requests * Deactivate provenance and sbom * Also exlcude ign_ packages * Cleanup labels in dockerfiles because setting it from the build action * Disable cache-from on schedule * Add ign_ros2_control to skip packages
1 parent f9bb74b commit 30847df

22 files changed

+729
-62
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: "Stack Build Gate"
2+
description: "Determine whether stack build should be skipped on pull requests based on changed paths."
3+
inputs:
4+
blocked_paths:
5+
description: "Multiline list of paths/globs that should block stack build when changed."
6+
required: true
7+
outputs:
8+
skip_stack_build:
9+
description: "true when stack build should be skipped"
10+
value: ${{ steps.compute.outputs.skip_stack_build }}
11+
runs:
12+
using: "composite"
13+
steps:
14+
# blocked_paths is passed as multiline text from callers. We cannot inject it directly
15+
# into the YAML mapping expected by dorny/paths-filter, so we normalize it here into
16+
# a valid YAML list under the "blocked" filter.
17+
- name: Prepare filters
18+
if: ${{ github.event_name == 'pull_request' }}
19+
id: prepare
20+
shell: bash
21+
run: |
22+
FILTERS="blocked:"
23+
while IFS= read -r raw_line; do
24+
line="${raw_line#${raw_line%%[![:space:]]*}}"
25+
if [[ -z "$line" ]]; then
26+
continue
27+
fi
28+
if [[ "$line" == -* ]]; then
29+
line="${line#-}"
30+
line="${line#${line%%[![:space:]]*}}"
31+
fi
32+
if [[ "$line" =~ ^\'.*\'$ ]]; then
33+
line="${line#\'}"
34+
line="${line%\'}"
35+
elif [[ "$line" =~ ^\".*\"$ ]]; then
36+
line="${line#\"}"
37+
line="${line%\"}"
38+
fi
39+
FILTERS+=$'\n'" - ${line}"
40+
done <<< "${{ inputs.blocked_paths }}"
41+
42+
{
43+
echo "filters<<EOF"
44+
echo "$FILTERS"
45+
echo "EOF"
46+
} >> "$GITHUB_OUTPUT"
47+
48+
- name: Check changed files
49+
if: ${{ github.event_name == 'pull_request' }}
50+
id: filter
51+
uses: dorny/paths-filter@v3
52+
with:
53+
filters: ${{ steps.prepare.outputs.filters }}
54+
- name: Compute gate result
55+
id: compute
56+
shell: bash
57+
run: |
58+
if [[ "${{ github.event_name }}" == "pull_request" && "${{ steps.filter.outputs.blocked }}" == "true" ]]; then
59+
echo "skip_stack_build=true" >> "$GITHUB_OUTPUT"
60+
else
61+
echo "skip_stack_build=false" >> "$GITHUB_OUTPUT"
62+
fi

.github/workflows/build_and_publish_debian_docker.yaml

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@ name: Build and publish debian docker images
33

44
on:
55
workflow_dispatch:
6+
push:
7+
branches:
8+
- master
9+
paths:
10+
- '.github/workflows/build_and_publish_debian_docker.yaml'
11+
- 'ros2_debian/**'
612
pull_request:
713
paths:
814
- '.github/workflows/build_and_publish_debian_docker.yaml'
915
- 'ros2_debian/**'
1016
schedule:
1117
- cron: '0 1 * * MON'
1218

19+
concurrency:
20+
# cancel previous runs of the same workflow, except for pushes on given branches
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/heads') }}
23+
1324
jobs:
1425
build_images:
1526
runs-on: ubuntu-latest
@@ -36,17 +47,49 @@ jobs:
3647
steps:
3748
- uses: actions/checkout@v6
3849
- uses: docker/setup-buildx-action@v3
50+
- name: Set image tag
51+
id: image_meta
52+
run: |
53+
tag_suffix=""
54+
if [ "${{ github.event_name }}" = "pull_request" ]; then
55+
tag_suffix="-pr-${{ github.event.pull_request.number }}"
56+
fi
57+
echo "image_tag=${{ matrix.ros_distro }}-debian${tag_suffix}" >> "$GITHUB_OUTPUT"
3958
- uses: docker/login-action@v3
4059
with:
4160
registry: ghcr.io
4261
username: ${{ github.repository_owner }}
4362
password: ${{ secrets.GITHUB_TOKEN }}
44-
- uses: docker/build-push-action@v6
63+
- name: Build and push image
64+
uses: docker/build-push-action@v6
4565
with:
4666
context: ros2_debian
4767
push: true
68+
provenance: false
69+
sbom: false
4870
file: ros2_debian/Dockerfile.${{ matrix.debian_version }}
49-
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ matrix.ros_distro }}-debian
71+
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ steps.image_meta.outputs.image_tag }}
72+
labels: |
73+
org.opencontainers.image.source=https://github.com/ros-controls/ros2_control_ci
74+
org.opencontainers.image.description=${{ matrix.debian_version }} for ros-controls CI
75+
org.opencontainers.image.licenses=Apache-2.0
76+
cache-from: ${{ github.event_name != 'schedule' && format('type=gha,scope=debian-{0}', matrix.ros_distro) || '' }}
77+
cache-to: type=gha,scope=debian-${{ matrix.ros_distro }},mode=max
5078
build-args: |
5179
ROS_DISTRO=${{ matrix.ros_distro }}
5280
SOURCE_PACKAGES=${{ matrix.source_packages }}
81+
82+
stack-build:
83+
if: ${{ github.event_name == 'pull_request' }}
84+
needs: build_images
85+
uses: ./.github/workflows/reusable-debian-build.yml
86+
strategy:
87+
fail-fast: false
88+
matrix:
89+
ROS_DISTRO: [rolling, humble, jazzy, kilted]
90+
with:
91+
ros_distro: ${{ matrix.ROS_DISTRO }}
92+
target_workspace: ros_controls.${{ matrix.ROS_DISTRO }}.repos
93+
skip_packages_regex: '^mujoco_ros2_control.*$|^gz_ros2_control.*$|^ros2_control_demo_example_9$|^ros2_control_demos$|^ign_ros2_control.*$'
94+
ref_for_scheduled_build: master
95+
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}

.github/workflows/build_and_publish_rhel_docker.yaml

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@ name: Build and publish RHEL docker images
33

44
on:
55
workflow_dispatch:
6+
push:
7+
branches:
8+
- master
9+
paths:
10+
- '.github/workflows/build_and_publish_rhel_docker.yaml'
11+
- 'ros2_rhel/**'
612
pull_request:
713
paths:
814
- '.github/workflows/build_and_publish_rhel_docker.yaml'
915
- 'ros2_rhel/**'
1016
schedule:
1117
- cron: '1 0 * * MON'
1218

19+
concurrency:
20+
# cancel previous runs of the same workflow, except for pushes on given branches
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/heads') }}
23+
1324
jobs:
1425
build_images:
1526
runs-on: ubuntu-latest
@@ -35,17 +46,49 @@ jobs:
3546
steps:
3647
- uses: actions/checkout@v6
3748
- uses: docker/setup-buildx-action@v3
49+
- name: Set image tag
50+
id: image_meta
51+
run: |
52+
tag_suffix=""
53+
if [ "${{ github.event_name }}" = "pull_request" ]; then
54+
tag_suffix="-pr-${{ github.event.pull_request.number }}"
55+
fi
56+
echo "image_tag=${{ matrix.ros_distro }}-rhel${tag_suffix}" >> "$GITHUB_OUTPUT"
3857
- uses: docker/login-action@v3
3958
with:
4059
registry: ghcr.io
4160
username: ${{ github.repository_owner }}
4261
password: ${{ secrets.GITHUB_TOKEN }}
43-
- uses: docker/build-push-action@v6
62+
- name: Build and push image
63+
uses: docker/build-push-action@v6
4464
with:
4565
context: ros2_rhel
4666
push: true
67+
provenance: false
68+
sbom: false
4769
file: ros2_rhel/Dockerfile.${{ matrix.rhel_version }}
48-
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ matrix.ros_distro }}-rhel
70+
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ steps.image_meta.outputs.image_tag }}
71+
labels: |
72+
org.opencontainers.image.source=https://github.com/ros-controls/ros2_control_ci
73+
org.opencontainers.image.description=${{ matrix.rhel_version }} for ros-controls CI
74+
org.opencontainers.image.licenses=Apache-2.0
75+
cache-from: ${{ github.event_name != 'schedule' && format('type=gha,scope=rhel-{0}', matrix.ros_distro) || '' }}
76+
cache-to: type=gha,scope=rhel-${{ matrix.ros_distro }},mode=max
4977
build-args: |
5078
ROS_DISTRO=${{ matrix.ros_distro }}
5179
SOURCE_PACKAGES=${{ matrix.source_packages }}
80+
81+
stack-build:
82+
if: ${{ github.event_name == 'pull_request' }}
83+
needs: build_images
84+
uses: ./.github/workflows/reusable-rhel-binary-build.yml
85+
strategy:
86+
fail-fast: false
87+
matrix:
88+
ROS_DISTRO: [rolling, humble, jazzy, kilted]
89+
with:
90+
ros_distro: ${{ matrix.ROS_DISTRO }}
91+
target_workspace: ros_controls.${{ matrix.ROS_DISTRO }}.repos
92+
skip_packages_regex: '^mujoco_ros2_control.*$|^gz_ros2_control.*$|^ros2_control_demo_example_9$|^ros2_control_demos$|^ign_ros2_control.*$'
93+
ref_for_scheduled_build: master
94+
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}

.github/workflows/build_and_publish_ubuntu_docker.yaml

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@ name: Build and publish Ubuntu docker images
33

44
on:
55
workflow_dispatch:
6+
push:
7+
branches:
8+
- master
9+
paths:
10+
- '.github/workflows/build_and_publish_ubuntu_docker.yaml'
11+
- 'ros2_ubuntu/**'
612
pull_request:
713
paths:
814
- '.github/workflows/build_and_publish_ubuntu_docker.yaml'
915
- 'ros2_ubuntu/**'
1016
schedule:
1117
- cron: '1 2 * * MON'
1218

19+
concurrency:
20+
# cancel previous runs of the same workflow, except for pushes on given branches
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/heads') }}
23+
1324
jobs:
1425
build_images:
1526
runs-on: ubuntu-latest
@@ -47,23 +58,45 @@ jobs:
4758
steps:
4859
- uses: actions/checkout@v6
4960
- uses: docker/setup-buildx-action@v3
61+
- name: Set image tag
62+
id: image_meta
63+
run: |
64+
tag_suffix=""
65+
if [ "${{ github.event_name }}" = "pull_request" ]; then
66+
tag_suffix="-pr-${{ github.event.pull_request.number }}"
67+
fi
68+
if [ "${{ matrix.ros-repo-packages }}" = "-testing" ]; then
69+
echo "image_tag=${{ matrix.ros_distro }}-ubuntu-testing${tag_suffix}" >> "$GITHUB_OUTPUT"
70+
else
71+
echo "image_tag=${{ matrix.ros_distro }}-ubuntu${tag_suffix}" >> "$GITHUB_OUTPUT"
72+
fi
5073
- uses: docker/login-action@v3
5174
with:
5275
registry: ghcr.io
5376
username: ${{ github.repository_owner }}
5477
password: ${{ secrets.GITHUB_TOKEN }}
55-
- uses: docker/build-push-action@v6
78+
- name: Build and push image
79+
uses: docker/build-push-action@v6
5680
with:
5781
context: ros2_ubuntu
5882
push: true
83+
provenance: false
84+
sbom: false
5985
file: ros2_ubuntu/Dockerfile
60-
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ matrix.ros_distro }}-ubuntu${{ matrix.ros-repo-packages }}
86+
tags: ghcr.io/${{ github.repository_owner }}/ros:${{ steps.image_meta.outputs.image_tag }}
87+
labels: |
88+
org.opencontainers.image.source=https://github.com/ros-controls/ros2_control_ci
89+
org.opencontainers.image.description=${{ matrix.base_image }} with preinstalled ROS for ros-controls CI
90+
org.opencontainers.image.licenses=Apache-2.0
91+
cache-from: ${{ github.event_name != 'schedule' && format('type=gha,scope=ubuntu-{0}{1}', matrix.ros_distro, matrix.ros-repo-packages) || '' }}
92+
cache-to: type=gha,scope=ubuntu-${{ matrix.ros_distro }}${{ matrix.ros-repo-packages }},mode=max
6193
build-args: |
6294
FROM=${{ matrix.base_image }}
6395
ROS_DISTRO=${{ matrix.ros_distro }}
6496
ROS_REPO_PACKAGES=${{ matrix.ros-repo-packages }}
6597
6698
stack-build:
99+
if: ${{ github.event_name == 'pull_request' }}
67100
needs: build_images
68101
uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml
69102
strategy:
@@ -76,8 +109,10 @@ jobs:
76109
ros_repo: ${{ matrix.ROS_REPO }}
77110
target_workspace: ros_controls.${{ matrix.ROS_DISTRO }}.repos
78111
ref_for_scheduled_build: master
112+
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}
79113

80114
compatibility-stack-build:
115+
if: ${{ github.event_name == 'pull_request' }}
81116
needs: build_images
82117
uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml
83118
strategy:
@@ -90,3 +125,4 @@ jobs:
90125
ros_repo: ${{ matrix.ROS_REPO }}
91126
target_workspace: ros_controls.rolling-on-${{ matrix.ROS_DISTRO }}.repos
92127
ref_for_scheduled_build: master
128+
docker_image_tag_suffix: ${{ format('-pr-{0}', github.event.pull_request.number) }}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
name: Cleanup PR-tagged docker images
3+
4+
on:
5+
pull_request:
6+
types: [closed]
7+
workflow_dispatch:
8+
inputs:
9+
pr_number:
10+
description: 'PR number to clean up (required for manual runs)'
11+
required: false
12+
type: string
13+
14+
concurrency:
15+
group: cleanup-pr-images-${{ github.event.pull_request.number || inputs.pr_number || github.run_id }}
16+
cancel-in-progress: false
17+
18+
jobs:
19+
cleanup-pr-images:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
packages: write
24+
steps:
25+
- name: Resolve PR number
26+
id: resolve_pr
27+
shell: bash
28+
run: |
29+
PR_NUMBER="${{ github.event.pull_request.number || inputs.pr_number }}"
30+
if [[ -z "$PR_NUMBER" ]]; then
31+
echo "No PR number provided. Set workflow_dispatch input 'pr_number' or run on pull_request.closed."
32+
exit 1
33+
fi
34+
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
35+
- name: Delete PR-tagged GHCR versions
36+
uses: dataaxiom/ghcr-cleanup-action@v1
37+
with:
38+
token: ${{ secrets.GITHUB_TOKEN }}
39+
owner: ${{ github.repository_owner }}
40+
repository: ${{ github.event.repository.name }}
41+
packages: ros
42+
delete-tags: '*-pr-${{ steps.resolve_pr.outputs.pr_number }}'
43+
delete-untagged: false

0 commit comments

Comments
 (0)