Skip to content

Commit 82372d7

Browse files
committed
[GitHub][CI] Factor out duplicate container building code into composite actions
1 parent 718818a commit 82372d7

File tree

4 files changed

+196
-145
lines changed

4 files changed

+196
-145
lines changed

.github/workflows/build-ci-container-tooling.yml

Lines changed: 28 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,29 @@ on:
1212
- '.github/workflows/containers/github-action-ci-tooling/**'
1313
- llvm/utils/git/requirements_formatting.txt
1414
- llvm/utils/git/requirements_linting.txt
15+
- '.github/workflows/build-container/**'
16+
- '.github/workflows/push-container/**'
1517
pull_request:
1618
paths:
1719
- .github/workflows/build-ci-container-tooling.yml
1820
- '.github/workflows/containers/github-action-ci-tooling/**'
1921
- llvm/utils/git/requirements_formatting.txt
2022
- llvm/utils/git/requirements_linting.txt
23+
- '.github/workflows/build-container/**'
24+
- '.github/workflows/push-container/**'
2125

2226
jobs:
2327
build-ci-container-tooling:
2428
if: github.repository_owner == 'llvm'
2529
runs-on: ubuntu-24.04
30+
strategy:
31+
fail-fast: false
32+
matrix:
33+
include:
34+
- container-name: code-format
35+
test-command: 'cd $HOME && clang-format --version | grep version && git-clang-format -h | grep usage && black --version | grep black'
36+
- container-name: code-lint
37+
test-command: 'cd $HOME && clang-tidy --version | grep version && clang-tidy-diff.py -h | grep usage'
2638
steps:
2739
- name: Checkout LLVM
2840
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -32,48 +44,16 @@ jobs:
3244
llvm/utils/git/requirements_formatting.txt
3345
llvm/utils/git/requirements_linting.txt
3446
clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
47+
.github/workflows/build-container
3548
36-
- name: Write Variables
37-
id: vars
38-
run: |
39-
tag=$(git rev-parse --short=12 HEAD)
40-
container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/amd64/ci-ubuntu-24.04"
41-
echo "container-name-format=$container_name-code-format" >> $GITHUB_OUTPUT
42-
echo "container-name-lint=$container_name-code-lint" >> $GITHUB_OUTPUT
43-
echo "container-name-format-tag=$container_name-format:$tag" >> $GITHUB_OUTPUT
44-
echo "container-name-lint-tag=$container_name-lint:$tag" >> $GITHUB_OUTPUT
45-
echo "container-format-filename=$(echo $container_name-format:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT
46-
echo "container-lint-filename=$(echo $container_name-lint:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT
47-
48-
- name: Build container
49-
run: |
50-
podman build --target ci-container-code-format \
51-
-f .github/workflows/containers/github-action-ci-tooling/Dockerfile \
52-
-t ${{ steps.vars.outputs.container-name-format-tag }} .
53-
podman build --target ci-container-code-lint \
54-
-f .github/workflows/containers/github-action-ci-tooling/Dockerfile \
55-
-t ${{ steps.vars.outputs.container-name-lint-tag }} .
56-
57-
# Save the container so we have it in case the push fails. This also
58-
# allows us to separate the push step into a different job so we can
59-
# maintain minimal permissions while building the container.
60-
- name: Save container image
61-
run: |
62-
podman save ${{ steps.vars.outputs.container-name-format-tag }} > ${{ steps.vars.outputs.container-format-filename }}
63-
podman save ${{ steps.vars.outputs.container-name-lint-tag }} > ${{ steps.vars.outputs.container-lint-filename }}
64-
65-
- name: Upload container image
66-
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
49+
- name: Build Container
50+
uses: ./.github/workflows/build-container
6751
with:
68-
name: container-amd64
69-
path: "*.tar"
70-
retention-days: 14
71-
72-
- name: Test Container
73-
run: |
74-
# Use --pull=never to ensure we are testing the just built image.
75-
podman run --pull=never --rm -it ${{ steps.vars.outputs.container-name-format-tag }} /usr/bin/bash -x -c 'cd $HOME && clang-format --version | grep version && git-clang-format -h | grep usage && black --version | grep black'
76-
podman run --pull=never --rm -it ${{ steps.vars.outputs.container-name-lint-tag }} /usr/bin/bash -x -c 'cd $HOME && clang-tidy --version | grep version && clang-tidy-diff.py -h | grep usage'
52+
container-name: ci-ubuntu-24.04-${{ matrix.container-name }}
53+
context: .github/workflows/containers/github-action-ci/
54+
dockerfile: .github/workflows/containers/github-action-ci/Dockerfile
55+
target: ci-container-${{ matrix.container-name }}
56+
test-command: ${{ matrix.test-command }}
7757

7858
push-ci-container:
7959
if: github.event_name == 'push'
@@ -82,34 +62,13 @@ jobs:
8262
permissions:
8363
packages: write
8464
runs-on: ubuntu-24.04
85-
env:
86-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8765
steps:
88-
- name: Download container
89-
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
90-
91-
- name: Push Container
92-
run: |
93-
function push_container {
94-
image_name=$1
95-
latest_name=$(echo $image_name | sed 's/:[a-f0-9]\+$/:latest/g')
96-
podman tag $image_name $latest_name
97-
echo "Pushing $image_name ..."
98-
podman push $image_name
99-
echo "Pushing $latest_name ..."
100-
podman push $latest_name
101-
}
102-
103-
podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io
104-
for f in $(find . -iname '*.tar'); do
105-
image_name=$(podman load -q -i $f | sed 's/Loaded image: //g')
106-
push_container $image_name
66+
- name: Checkout LLVM
67+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
68+
with:
69+
sparse-checkout: |
70+
.github/workflows/push-container
10771
108-
if echo $image_name | grep '/amd64/'; then
109-
# For amd64, create an alias with the arch component removed.
110-
# This matches the convention used on dockerhub.
111-
default_image_name=$(echo $(dirname $(dirname $image_name))/$(basename $image_name))
112-
podman tag $image_name $default_image_name
113-
push_container $default_image_name
114-
fi
115-
done
72+
- uses: ./.github/workflows/push-container
73+
with:
74+
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/build-ci-container.yml

Lines changed: 29 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -10,72 +10,44 @@ on:
1010
paths:
1111
- .github/workflows/build-ci-container.yml
1212
- '.github/workflows/containers/github-action-ci/**'
13+
- '.github/workflows/build-container/**'
14+
- '.github/workflows/push-container/**'
1315
pull_request:
1416
paths:
1517
- .github/workflows/build-ci-container.yml
1618
- '.github/workflows/containers/github-action-ci/**'
19+
- '.github/workflows/build-container/**'
20+
- '.github/workflows/push-container/**'
1721

1822
jobs:
1923
build-ci-container:
2024
if: github.repository_owner == 'llvm'
2125
runs-on: ${{ matrix.runs-on }}
2226
strategy:
2327
matrix:
24-
include:
25-
# The arch names should match the names used on dockerhub.
26-
# See https://github.com/docker-library/official-images#architectures-other-than-amd64
27-
- arch: amd64
28-
runs-on: depot-ubuntu-24.04-16
29-
- arch: arm64v8
30-
runs-on: depot-ubuntu-24.04-arm-16
28+
runs-on:
29+
- depot-ubuntu-24.04-16
30+
- depot-ubuntu-24.04-arm-16
31+
container-name:
32+
- ''
33+
- agent
34+
test-command:
35+
- 'cd $HOME && printf '\''#include <iostream>\nint main(int argc, char **argv) { std::cout << "Hello\\n"; }'\'' | clang++ -x c++ - && ./a.out | grep Hello'
3136
steps:
3237
- name: Checkout LLVM
3338
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
3439
with:
35-
sparse-checkout: .github/workflows/containers/github-action-ci/
36-
# podman is not installed by default on the ARM64 images.
37-
- name: Install Podman
38-
if: runner.arch == 'ARM64'
39-
run: |
40-
sudo apt-get install podman
41-
- name: Write Variables
42-
id: vars
43-
run: |
44-
tag=$(git rev-parse --short=12 HEAD)
45-
container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/${{ matrix.arch }}/ci-ubuntu-24.04"
46-
echo "container-name=$container_name" >> $GITHUB_OUTPUT
47-
echo "container-name-agent=$container_name-agent" >> $GITHUB_OUTPUT
48-
echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT
49-
echo "container-name-agent-tag=$container_name-agent:$tag" >> $GITHUB_OUTPUT
50-
echo "container-filename=$(echo $container_name:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT
51-
echo "container-agent-filename=$(echo $container_name-agent:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT
52-
- name: Build container
53-
working-directory: ./.github/workflows/containers/github-action-ci/
54-
run: |
55-
podman build --target ci-container -t ${{ steps.vars.outputs.container-name-tag }} .
56-
podman build --target ci-container-agent -t ${{ steps.vars.outputs.container-name-agent-tag }} .
40+
sparse-checkout: |
41+
.github/workflows/containers/github-action-ci/
42+
.github/workflows/build-container
5743
58-
# Save the container so we have it in case the push fails. This also
59-
# allows us to separate the push step into a different job so we can
60-
# maintain minimal permissions while building the container.
61-
- name: Save container image
62-
run: |
63-
podman save ${{ steps.vars.outputs.container-name-tag }} > ${{ steps.vars.outputs.container-filename }}
64-
podman save ${{ steps.vars.outputs.container-name-agent-tag }} > ${{ steps.vars.outputs.container-agent-filename }}
65-
66-
- name: Upload container image
67-
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
44+
- name: Build Container
45+
uses: ./.github/workflows/build-container
6846
with:
69-
name: container-${{ matrix.arch }}
70-
path: "*.tar"
71-
retention-days: 14
72-
73-
- name: Test Container
74-
run: |
75-
for image in ${{ steps.vars.outputs.container-name-tag }}; do
76-
# Use --pull=never to ensure we are testing the just built image.
77-
podman run --pull=never --rm -it $image /usr/bin/bash -x -c 'cd $HOME && printf '\''#include <iostream>\nint main(int argc, char **argv) { std::cout << "Hello\\n"; }'\'' | clang++ -x c++ - && ./a.out | grep Hello'
78-
done
47+
container-name: ci-ubuntu-24.04-${{ matrix.container-name }}
48+
dockerfile: .github/workflows/containers/github-action-ci-tooling/Dockerfile
49+
target: ci-container${{ matrix.container-name && format('-{0}', matrix.container-name) }}
50+
test-command: ${{ matrix.test-command }}
7951

8052
push-ci-container:
8153
if: github.event_name == 'push'
@@ -87,31 +59,12 @@ jobs:
8759
env:
8860
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8961
steps:
90-
- name: Download container
91-
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
92-
93-
- name: Push Container
94-
run: |
95-
function push_container {
96-
image_name=$1
97-
latest_name=$(echo $image_name | sed 's/:[a-f0-9]\+$/:latest/g')
98-
podman tag $image_name $latest_name
99-
echo "Pushing $image_name ..."
100-
podman push $image_name
101-
echo "Pushing $latest_name ..."
102-
podman push $latest_name
103-
}
104-
105-
podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io
106-
for f in $(find . -iname '*.tar'); do
107-
image_name=$(podman load -q -i $f | sed 's/Loaded image: //g')
108-
push_container $image_name
62+
- name: Checkout LLVM
63+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
64+
with:
65+
sparse-checkout: |
66+
.github/workflows/push-container
10967
110-
if echo $image_name | grep '/amd64/'; then
111-
# For amd64, create an alias with the arch component removed.
112-
# This matches the convention used on dockerhub.
113-
default_image_name=$(echo $(dirname $(dirname $image_name))/$(basename $image_name))
114-
podman tag $image_name $default_image_name
115-
push_container $default_image_name
116-
fi
117-
done
68+
- uses: ./.github/workflows/push-container
69+
with:
70+
token: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: Build Container
2+
description: >-
3+
Build and test a container using the standard llvm naming scheme for containers.
4+
5+
inputs:
6+
tag:
7+
description: >-
8+
The tag to use for this container.
9+
required: false
10+
container-name:
11+
description: >-
12+
The name for the container.
13+
required: true
14+
dockerfile:
15+
description: >-
16+
Path to docker file.
17+
required: false
18+
target:
19+
description: >-
20+
The container target to build 'passed to podman via ---target option'
21+
required: false
22+
context:
23+
description: >-
24+
Path to context for the container build.
25+
required: false
26+
test-command:
27+
description: >-
28+
Test command to run to ensure the container is working correctly.
29+
required: false
30+
31+
runs:
32+
using: "composite"
33+
steps:
34+
# podman is not installed by default on the ARM64 images.
35+
- name: Install Podman
36+
if: runner.arch == 'ARM64'
37+
shell: bash
38+
run: |
39+
sudo apt-get install podman
40+
41+
- name: Build Container
42+
shell: bash
43+
env:
44+
INPUT_TAG: ${{inputs.tag }}
45+
INPUT_CONTAINER_NAME: ${{ inputs.container-name }}
46+
INPUT_TARGET: ${{ inputs.target }}
47+
INPUT_DOCKERFILE: ${{ inputs.dockerfile }}
48+
INPUT_CONTEXT: ${{ inputs.context }}
49+
id: build
50+
run: |
51+
env
52+
tag="${INPUT_TAG:-$(git rev-parse --short=12 HEAD)}"
53+
54+
case "$RUNNER_ARCH" in
55+
ARM64)
56+
container_arch="arm64v8"
57+
;;
58+
*)
59+
container_arch="amd64"
60+
;;
61+
esac
62+
63+
container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/$container_arch/$INPUT_CONTAINER_NAME:$tag"
64+
container_filename="$(echo $container_name | sed -e 's/\//-/g' -e 's/:/-/g').tar"
65+
if [ -n "$INPUT_TARGET" ]; then
66+
podman_options="$podman_options --target $INPUT_TARGET"
67+
fi
68+
if [ -n "$INPUT_DOCKERFILE" ]; then
69+
podman_options="$podman_options -f $INPUT_DOCKERFILE"
70+
fi
71+
podman_options="$podman_options ${INPUT_CONTEXT:-.}"
72+
echo "Podman Options: $podman_options"
73+
74+
podman build -t $container_name $podman_options
75+
76+
podman save $container_name > $container_filename
77+
78+
echo "container-full-name=$container_name" >> $GITHUB_OUTPUT
79+
80+
- name: Create container artifact
81+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
82+
with:
83+
name: ${{ inputs.container-name }}-${{ runner.arch }}
84+
path: "*.tar"
85+
retention-days: 14
86+
87+
- name: Test container
88+
shell: bash
89+
if: inputs.test-command
90+
env:
91+
INPUT_TEST_COMMAND: ${{ inputs.test-command }}
92+
CONTAINER_FULL_NAME: ${{ steps.build.outputs.container-full-name }}
93+
run: |
94+
podman run --pull=never --rm -it $CONTAINER_FULL_NAME /usr/bin/bash -x -c "$INPUT_TEST_COMMAND"
95+

0 commit comments

Comments
 (0)