@@ -3,6 +3,9 @@ on: workflow_call
33defaults :
44 run :
55 shell : bash
6+ concurrency :
7+ group : ${{github.workflow_ref}}
8+ cancel-in-progress : true
69jobs :
710 check-formatting-dockerfile :
811 name : Check Formatting (Dockerfile)
2831 name : Build & Test
2932 runs-on : ubuntu-latest
3033 timeout-minutes : 30
31- services :
32- registry :
33- image : registry
34- ports :
35- - 5000:5000
3634 steps :
3735 - name : Checkout
3836 uses : actions/checkout@v6.0.2
@@ -51,46 +49,43 @@ jobs:
5149 IFS=","
5250 PLATFORMS="${PLATFORMS[*]}"
5351 IFS="$SAVE_IFS"
54- TEMP_IMAGE='localhost:5000/base-ubuntu '
52+ TEMP_IMAGE='ci '
5553 echo "platforms=$PLATFORMS" >> $GITHUB_OUTPUT
56- echo "base-image-tag=$TEMP_IMAGE:base-image" >> $GITHUB_OUTPUT
57- echo "test-image-tag=$TEMP_IMAGE:test" >> $GITHUB_OUTPUT
54+ echo "ci-image-tag=$TEMP_IMAGE:image" >> $GITHUB_OUTPUT
55+ echo "ci-test-image-tag=$TEMP_IMAGE:test-image" >> $GITHUB_OUTPUT
56+ - name : Set up Docker
57+ uses : docker/setup-docker-action@v5.0.0
58+ with :
59+ daemon-config : |
60+ { "features": { "containerd-snapshotter": true } }
5861 - name : Set up QEMU
5962 uses : docker/setup-qemu-action@v4.0.0
6063 with :
6164 platforms : ${{steps.info.outputs.platforms}}
62- - name : Set up Docker Buildx
63- uses : docker/setup-buildx-action@v4.0.0
64- id : buildx
65- with :
66- driver-opts : network=host
6765 - name : Build image
6866 uses : docker/build-push-action@v7.0.0
6967 with :
7068 context : .
71- builder : ${{steps.buildx.outputs.name}}
7269 platforms : ${{steps.info.outputs.platforms}}
73- tags : ${{steps.info.outputs.base -image-tag}}
70+ tags : ${{steps.info.outputs.ci -image-tag}}
7471 cache-from : type=gha
7572 cache-to : type=gha,mode=max
76- push : true
73+ load : true
7774 - name : Build test image
7875 uses : docker/build-push-action@v7.0.0
7976 with :
8077 context : ./test
81- builder : ${{steps.buildx.outputs.name}}
8278 build-contexts : |
83- base-image:ci =docker-image://${{steps.info.outputs.base -image-tag}}
79+ ci:image =docker-image://${{steps.info.outputs.ci -image-tag}}
8480 platforms : ${{steps.info.outputs.platforms}}
85- tags : ${{steps.info.outputs.test-image-tag}}
81+ tags : ${{steps.info.outputs.ci- test-image-tag}}
8682 cache-from : type=gha
8783 cache-to : type=gha,mode=max
88- push : true
84+ load : true
8985 - name : Run tests
9086 run : >
9187 for PLATFORM in ${PLATFORMS//,/ }; do
9288 echo "::group::Run test ($PLATFORM)"
93- docker pull --platform "$PLATFORM" "$TEST_IMAGE_TAG" > /dev/null
9489 docker run --rm \
9590 --platform "$PLATFORM" \
9691 -e 'TZ=America/Toronto' \
9994 echo '::endgroup::'
10095 done
10196 env :
102- TEST_IMAGE_TAG : ${{steps.info.outputs.test-image-tag}}
97+ TEST_IMAGE_TAG : ${{steps.info.outputs.ci- test-image-tag}}
10398 PLATFORMS : ${{steps.info.outputs.platforms}}
10499 - name : Hide outdated build details comments
105100 uses : int128/hide-comment-action@v1.53.0
@@ -110,58 +105,127 @@ jobs:
110105 id : image-details
111106 if : github.event_name == 'pull_request'
112107 run : |
108+ # Determine the remote image tag to compare against
109+ echo "::group::Determine remote image tag"
113110 VERSION=$(grep -E '^FROM ubuntu:[a-z]+-[0-9]+$' Dockerfile)
114111 VERSION=${VERSION##*:}
115112 STREAM=${VERSION%-*}
116113 REMOTE_IMAGE_TAG=$REMOTE_IMAGE:$STREAM
117- set +e
118- EXISTS_OUTPUT=$(
119- docker buildx imagetools inspect $REMOTE_IMAGE_TAG 2> /dev/null
120- )
121- EXISTS_RESULT="$?"
122- set -e
123- if [[ "$EXISTS_OUTPUT" == "" || "$EXISTS_RESULT" -ne 0 ]]; then
124- echo "Stream tag '$STREAM' does not exist, using latest tag"
114+ echo "Local image: $LOCAL_IMAGE_TAG"
115+ echo "Remote image: $REMOTE_IMAGE_TAG"
116+ echo "Platforms: $PLATFORMS"
117+ if ! docker buildx imagetools inspect \
118+ $REMOTE_IMAGE_TAG > /dev/null 2>&1; then
119+ echo "::warning::Tag '$STREAM' not found, falling back to 'latest'"
125120 REMOTE_IMAGE_TAG=$REMOTE_IMAGE:latest
121+ echo "Remote image: $REMOTE_IMAGE_TAG"
126122 fi
123+ echo "::endgroup::"
124+ # Build the comment body per platform
127125 BODY=$'<!-- build details -->\n\n'
128- BODY+=$'## Build Details\n\n'
126+ HAVE_REMOTE=true
127+ FAILED_PLATFORMS=()
128+ TOTAL_SIZE_NEW=0
129+ TOTAL_SIZE_OLD=0
130+ PLATFORM_BODIES=""
131+ FMT='--to=iec --suffix=B --format=%.2f'
129132 for PLATFORM in ${PLATFORMS//,/ }; do
130- docker pull --platform=$PLATFORM $LOCAL_IMAGE_TAG
131- SIZE_NEW=$(docker inspect -f '{{.Size}}' $LOCAL_IMAGE_TAG)
133+ echo "::group::$PLATFORM"
134+ PULL_FAILED=false
135+ # Local image size
136+ SIZE_NEW=$(docker image inspect --platform=$PLATFORM \
137+ -f '{{.Size}}' $LOCAL_IMAGE_TAG)
138+ echo "Local size: $SIZE_NEW ($(echo $SIZE_NEW | numfmt $FMT))"
139+ # Layer breakdown
132140 DETAILS=$(
133- docker image history --format \
134- 'table | {{.Size}} | {{.CreatedBy}} |' $LOCAL_IMAGE_TAG
141+ docker image history --platform=$PLATFORM \
142+ --format 'table | {{.Size}} | {{.CreatedBy}} |' $LOCAL_IMAGE_TAG
135143 )
136144 DETAILS=${DETAILS#*$'\n'}
137- docker rmi -f $LOCAL_IMAGE_TAG
145+ echo "Layer breakdown:"
146+ echo "$DETAILS"
147+ # Remote image size
138148 if docker pull --platform=$PLATFORM $REMOTE_IMAGE_TAG; then
139- SIZE_OLD=$(docker inspect -f '{{.Size}}' $REMOTE_IMAGE_TAG)
149+ SIZE_OLD=$(
150+ docker image inspect --platform=$PLATFORM -f '{{.Size}}' \
151+ $REMOTE_IMAGE_TAG
152+ )
153+ echo "Remote size: $SIZE_OLD ($(echo $SIZE_OLD | numfmt $FMT))"
140154 else
155+ HAVE_REMOTE=false
156+ FAILED_PLATFORMS+=("$PLATFORM")
157+ PULL_FAILED=true
141158 SIZE_OLD=$SIZE_NEW
159+ echo "::warning::Failed to pull remote image for $PLATFORM," \
160+ "using local as baseline"
142161 fi
143- docker rmi -f $REMOTE_IMAGE_TAG
144- SIZE=$(echo $SIZE_NEW | numfmt --to=iec --suffix=B --format='%.2f')
145- SIZE_DIFF=$(
146- echo "$(( SIZE_NEW - SIZE_OLD ))" |
147- numfmt --to=iec --suffix=B --format='%.2f'
148- )
149- if (( $SIZE_NEW > $SIZE_OLD )); then
150- SIZE="$SIZE \`+$SIZE_DIFF\`"
151- elif (( $SIZE_NEW < $SIZE_OLD )); then
152- SIZE="$SIZE \`$SIZE_DIFF\`"
162+ # Format size with difference
163+ SIZE=$(echo $SIZE_NEW | numfmt $FMT)
164+ DIFF=$(( SIZE_NEW - SIZE_OLD ))
165+ echo "Difference: $DIFF bytes"
166+ if (( DIFF > 0 )); then
167+ SIZE+=" \`+$(echo $DIFF | numfmt $FMT)\`"
168+ elif (( DIFF < 0 )); then
169+ SIZE+=" \`$(echo $DIFF | numfmt $FMT)\`"
153170 fi
154- BODY+="\`$PLATFORM\`: **$SIZE**"
155- BODY+=$'\n\n<details>\n<summary>Layer Breakdown</summary>\n\n'
156- BODY+=$'| Size | Created By |\n'
157- BODY+=$'| ---- | ---------- |\n'
158- BODY+="$DETAILS"
159- BODY+=$'\n\n</details>\n\n'
171+ echo "Formatted size: $SIZE"
172+ # Accumulate totals
173+ TOTAL_SIZE_NEW=$((TOTAL_SIZE_NEW + SIZE_NEW))
174+ TOTAL_SIZE_OLD=$((TOTAL_SIZE_OLD + SIZE_OLD))
175+ # Determine status indicator
176+ if (( DIFF > 0 )); then
177+ STATUS=":red_square:"
178+ elif (( DIFF < 0 )); then
179+ STATUS=":yellow_square:"
180+ else
181+ STATUS=":green_square:"
182+ fi
183+ # Append to platform bodies
184+ PLATFORM_BODIES+=$'<details>\n'
185+ PLATFORM_BODIES+="<summary><code>$PLATFORM</code>"
186+ PLATFORM_BODIES+=" $STATUS</summary><br/>"$'\n\n'
187+ if [[ "$PULL_FAILED" == "true" ]]; then
188+ PLATFORM_BODIES+=$'> [!NOTE]\n'
189+ PLATFORM_BODIES+=$'> Remote image unavailable.'
190+ PLATFORM_BODIES+=$' Size comparison skipped'
191+ PLATFORM_BODIES+=$' for this platform.\n\n'
192+ fi
193+ PLATFORM_BODIES+="**Size:** $SIZE"$'\n'
194+ PLATFORM_BODIES+=$'\n#### Layers\n\n'
195+ PLATFORM_BODIES+=$'| Size | Created By |\n'
196+ PLATFORM_BODIES+=$'| ---- | ---------- |\n'
197+ PLATFORM_BODIES+="$DETAILS"
198+ PLATFORM_BODIES+=$'\n\n</details>\n\n'
199+ echo "::endgroup::"
160200 done
201+ # Overall size summary
202+ OVERALL_SIZE=$(echo $TOTAL_SIZE_NEW | numfmt $FMT)
203+ OVERALL_DIFF=$((TOTAL_SIZE_NEW - TOTAL_SIZE_OLD))
204+ if (( OVERALL_DIFF > 0 )); then
205+ OVERALL_SIZE+=" \`+$(echo $OVERALL_DIFF | numfmt $FMT)\`"
206+ elif (( OVERALL_DIFF < 0 )); then
207+ OVERALL_SIZE+=" \`$(echo $OVERALL_DIFF | numfmt $FMT)\`"
208+ fi
209+ BODY+=$'## Build Details\n\n'
210+ if [[ "$HAVE_REMOTE" != "true" ]]; then
211+ BODY+=$'> [!WARNING]\n'
212+ BODY+=$'> Size comparison may be inaccurate.'
213+ BODY+=$' Failed to pull remote image for the following platforms:\n'
214+ for FP in "${FAILED_PLATFORMS[@]}"; do
215+ BODY+="> * \`$FP\`"$'\n'
216+ done
217+ BODY+=$'\n'
218+ fi
219+ BODY+="**Size:** $OVERALL_SIZE"$'\n'
220+ BODY+=$'\n### Platforms\n\n'
221+ BODY+="$PLATFORM_BODIES"
222+ echo "::group::Report final image details"
223+ docker image ls --tree 2>/dev/null
224+ echo "::endgroup::"
161225 gh pr comment "$PULL_REQUEST_NUMBER" --body "$BODY"
162226 env :
163227 REMOTE_IMAGE : ghcr.io/${{github.repository_owner}}/base-ubuntu
164- LOCAL_IMAGE_TAG : ${{steps.info.outputs.base -image-tag}}
228+ LOCAL_IMAGE_TAG : ${{steps.info.outputs.ci -image-tag}}
165229 PLATFORMS : ${{steps.info.outputs.platforms}}
166230 PULL_REQUEST_NUMBER : ${{github.event.pull_request.number}}
167231 GITHUB_TOKEN : ${{github.token}}
0 commit comments