3434 required : false
3535 type : string
3636 default : ubuntu-latest
37- outputs :
38- image-basename :
39- description : " The sanitized base name of the image (without registry or tag)"
40- value : ${{ jobs.sanitize-inputs.outputs.image-basename }}
41- image-name :
42- description : " The sanitized name of the image (without registry or tag)"
43- value : ${{ jobs.sanitize-inputs.outputs.image-name }}
44- fully-qualified-image-name :
45- description : " The fully qualified name of the image including registry (but without tag)"
46- value : ${{ jobs.sanitize-inputs.outputs.fully-qualified-image-name }}
4737 secrets :
4838 DOCKER_USERNAME :
4939 description : " User name for Docker login, if not provided the GitHub actor will be used"
5545permissions : {}
5646
5747jobs :
58- sanitize-inputs :
59- runs-on : ${{ inputs.default-runner }}
60- outputs :
61- image-basename : ${{ steps.sanitize-image-name.outputs.sanitized-basename }}
62- image-name : ${{ steps.sanitize-image-name.outputs.sanitized-image-name }}
63- fully-qualified-image-name : ${{ inputs.registry }}/${{ steps.sanitize-image-name.outputs.sanitized-image-name }}
64- steps :
65- - name : Sanitize image name
66- id : sanitize-image-name
67- env :
68- IMAGE_NAME : ${{ inputs.image-name }}
69- run : |
70- set -Eeuo pipefail
71-
72- # Split all image name components (on '/') and sanitize each component independently.
73- # Rules: lowercase; allowed chars a-z0-9._- ; collapse invalid sequences to single '-'; trim leading/trailing '-'.
74- IFS='/' read -r -a PARTS <<< "$IMAGE_NAME"
75- SANITIZED_PARTS=()
76-
77- for PART in "${PARTS[@]}"; do
78- SANITIZED_PART=$(echo "$PART" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9._-]+/-/g' | sed -E 's/^-+|-+$//g')
79- if [ -z "$SANITIZED_PART" ]; then
80- echo "Invalid or empty component after sanitization in image component: '$PART', please correct your image name: '$IMAGE_NAME'" >&2
81- exit 1
82- fi
83- SANITIZED_PARTS+=("$SANITIZED_PART")
84- done
85-
86- SANITIZED_IMAGE_NAME=$(IFS='/'; echo "${SANITIZED_PARTS[*]}")
87- SANITIZED_BASENAME=${SANITIZED_PARTS[-1]}
88- echo "sanitized-image-name=$SANITIZED_IMAGE_NAME" >> "$GITHUB_OUTPUT"
89- echo "sanitized-basename=$SANITIZED_BASENAME" >> "$GITHUB_OUTPUT"
48+ sanitize-image-name :
49+ uses : ./.github/workflows/wc-sanitize-image-name.yml
50+ with :
51+ image-name : ${{ inputs.image-name }}
52+ registry : ${{ inputs.registry }}
53+ runner-labels : ${{ inputs.default-runner }}
9054
9155 build-push :
9256 strategy :
9357 matrix : ${{ fromJson(inputs.build-matrix) }}
9458 runs-on : ${{ matrix.runner }}
95- needs : sanitize-inputs
59+ needs : sanitize-image-name
9660 permissions :
9761 contents : read
9862 packages : write
11882 DOCKER_METADATA_SET_OUTPUT_ENV : false
11983 id : metadata
12084 with :
121- images : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
85+ images : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
12286 # Generate image LABEL for devcontainer.metadata
12387 # the sed expression is a workaround for quotes being eaten in arrays (e.g. ["x", "y", "z"] -> ["x",y,"z"])
12488 - run : echo "metadata=$(jq -cj '[.]' ".devcontainer/${CONTAINER_FLAVOR}/devcontainer-metadata-vscode.json" | sed 's/,"/, "/g')" >> "$GITHUB_OUTPUT"
13498 with :
13599 file : ${{ inputs.dockerfile }}
136100 push : true
137- tags : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
101+ tags : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
138102 labels : |
139103 ${{ steps.metadata.outputs.labels }}
140104 devcontainer.metadata=${{ steps.devcontainer-metadata.outputs.metadata }}
@@ -151,7 +115,7 @@ jobs:
151115 RUNNER_TEMP : ${{ runner.temp }}
152116 - uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
153117 with :
154- name : digests-${{ needs.sanitize-inputs .outputs.image-basename }}-${{ steps.devcontainer-arch.outputs.arch }}
118+ name : digests-${{ needs.sanitize-image-name .outputs.image-basename }}-${{ steps.devcontainer-arch.outputs.arch }}
155119 path : ${{ runner.temp }}/digests/*
156120 if-no-files-found : error
157121 retention-days : 1
@@ -160,7 +124,7 @@ jobs:
160124 runs-on : ${{ inputs.default-runner }}
161125 needs :
162126 - build-push
163- - sanitize-inputs
127+ - sanitize-image-name
164128 permissions :
165129 actions : read
166130 attestations : write
@@ -181,7 +145,7 @@ jobs:
181145 - uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
182146 with :
183147 path : ${{ runner.temp }}/digests
184- pattern : digests-${{ needs.sanitize-inputs .outputs.image-basename }}-*
148+ pattern : digests-${{ needs.sanitize-image-name .outputs.image-basename }}-*
185149 merge-multiple : true
186150 - uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
187151 - uses : docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -198,7 +162,7 @@ jobs:
198162 DOCKER_METADATA_ANNOTATIONS_LEVELS : index
199163 DOCKER_METADATA_SET_OUTPUT_ENV : false
200164 with :
201- images : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
165+ images : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
202166 # Generate Docker tags based on the following events/attributes.
203167 # To prevent unnecessary image builds we simulate the `type=edge` tag
204168 # with `type=raw,value=edge,enable=...` which only enables the tag
@@ -230,7 +194,7 @@ jobs:
230194 print(' '.join(command))
231195 subprocess.run(command, check=True)
232196 env :
233- FULLY_QUALIFIED_IMAGE_NAME : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
197+ FULLY_QUALIFIED_IMAGE_NAME : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
234198 METADATA_JSON : ${{ steps.metadata.outputs.json }}
235199 shell : python
236200 working-directory : ${{ runner.temp }}/digests
@@ -241,44 +205,44 @@ jobs:
241205 output=$(docker buildx imagetools inspect "${CONTAINER}" --format '{{json .}}')
242206 echo "digest=$(echo "$output" | jq -r '.manifest.digest // .manifests[0].digest')" >> "$GITHUB_OUTPUT"
243207 env :
244- CONTAINER : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
208+ CONTAINER : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
245209 - run : |
246210 set -Eeuo pipefail
247211 wget -O diffoci https://github.com/reproducible-containers/diffoci/releases/download/v0.1.7/diffoci-v0.1.7.linux-amd64
248212 chmod +x diffoci
249213 ./diffoci diff --semantic --report-file=container-diff.json "${FROM_CONTAINER}" "${TO_CONTAINER}" || true
250214 env:
251- FROM_CONTAINER: ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}:edge
252- TO_CONTAINER: ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
215+ FROM_CONTAINER: ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}:edge
216+ TO_CONTAINER: ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
253217 - uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
254218 with :
255- name : container-diff-${{ needs.sanitize-inputs .outputs.image-basename }}
219+ name : container-diff-${{ needs.sanitize-image-name .outputs.image-basename }}
256220 path : container-diff.json
257221 retention-days : 10
258222 - uses : ./.github/actions/container-size-diff
259223 id : container-size-diff
260224 with :
261- from-container : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}:edge
262- to-container : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
225+ from-container : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}:edge
226+ to-container : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}:${{ steps.metadata.outputs.version }}
263227 - uses : marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
264228 with :
265- header : container-size-diff-${{ needs.sanitize-inputs .outputs.image-basename }}
229+ header : container-size-diff-${{ needs.sanitize-image-name .outputs.image-basename }}
266230 message : |
267231 ${{ steps.container-size-diff.outputs.size-diff-markdown }}
268232 - uses : anchore/sbom-action@f8bdd1d8ac5e901a77a92f111440fdb1b593736b # v0.20.6
269233 with :
270- image : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}@${{ steps.inspect-manifest.outputs.digest }}
234+ image : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}@${{ steps.inspect-manifest.outputs.digest }}
271235 dependency-snapshot : true
272236 - uses : actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
273237 with :
274- subject-name : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
238+ subject-name : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
275239 subject-digest : ${{ steps.inspect-manifest.outputs.digest }}
276240 show-summary : false
277241 push-to-registry : true
278242 - name : Verify attestation
279243 run : gh attestation verify --repo "${GH_REPO}" "oci://${FULLY_QUALIFIED_IMAGE_NAME}@${DIGEST}"
280244 env :
281245 DIGEST : ${{ steps.inspect-manifest.outputs.digest }}
282- FULLY_QUALIFIED_IMAGE_NAME : ${{ needs.sanitize-inputs .outputs.fully-qualified-image-name }}
246+ FULLY_QUALIFIED_IMAGE_NAME : ${{ needs.sanitize-image-name .outputs.fully-qualified-image-name }}
283247 GH_REPO : ${{ github.repository }}
284248 GH_TOKEN : ${{ github.token }}
0 commit comments