@@ -40,106 +40,123 @@ on:
4040 value : ${{ jobs.verify_attestation.outputs.resolved_digest }}
4141
4242jobs :
43- get_config_values :
44- runs-on : ubuntu-22.04
45- outputs :
46- tag_format : ${{ steps.load-config.outputs.TAG_FORMAT }}
47- devcontainer_version : ${{ steps.load-config.outputs.DEVCONTAINER_VERSION }}
48- devcontainer_image : ${{ steps.load-config.outputs.DEVCONTAINER_IMAGE }}
49- runtime_docker_image : ${{ steps.load-config.outputs.RUNTIME_DOCKER_IMAGE }}
50- steps :
51- - name : Checkout code
52- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
53- with :
54- ref : ${{ env.BRANCH_NAME }}
55- fetch-depth : 0
43+ get_config_values :
44+ runs-on : ubuntu-22.04
45+ outputs :
46+ tag_format : ${{ steps.load-config.outputs.TAG_FORMAT }}
47+ devcontainer_version : ${{ steps.load-config.outputs.DEVCONTAINER_VERSION }}
48+ devcontainer_image : ${{ steps.load-config.outputs.DEVCONTAINER_IMAGE }}
49+ runtime_docker_image : ${{ steps.load-config.outputs.RUNTIME_DOCKER_IMAGE }}
50+ steps :
51+ - name : Checkout code
52+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
53+ with :
54+ ref : ${{ env.BRANCH_NAME }}
55+ fetch-depth : 0
56+
57+ - name : Load config value
58+ id : load-config
59+ run : |
60+ TAG_FORMAT=$(yq '.TAG_FORMAT' .github/config/settings.yml)
61+ DEVCONTAINER_IMAGE=$(jq -r '.build.args.IMAGE_NAME' .devcontainer/devcontainer.json)
62+ DEVCONTAINER_VERSION=$(jq -r '.build.args.IMAGE_VERSION' .devcontainer/devcontainer.json)
63+ RUNTIME_DOCKER_IMAGE="${DEVCONTAINER_IMAGE}:githubactions-${DEVCONTAINER_VERSION}"
64+ {
65+ echo "TAG_FORMAT=$TAG_FORMAT"
66+ echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE"
67+ echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION"
68+ echo "RUNTIME_DOCKER_IMAGE=$RUNTIME_DOCKER_IMAGE"
69+ } >> "$GITHUB_OUTPUT"
5670
57- - name : Load config value
58- id : load-config
59- run : |
60- TAG_FORMAT=$(yq '.TAG_FORMAT' .github/config/settings.yml)
61- DEVCONTAINER_IMAGE=$(jq -r '.build.args.IMAGE_NAME' .devcontainer/devcontainer.json)
62- DEVCONTAINER_VERSION=$(jq -r '.build.args.IMAGE_VERSION' .devcontainer/devcontainer.json)
63- RUNTIME_DOCKER_IMAGE="${DEVCONTAINER_IMAGE}:githubactions-${DEVCONTAINER_VERSION}"
64- {
65- echo "TAG_FORMAT=$TAG_FORMAT"
66- echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE"
67- echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION"
68- echo "RUNTIME_DOCKER_IMAGE=$RUNTIME_DOCKER_IMAGE"
69- } >> "$GITHUB_OUTPUT"
71+ verify_attestation :
72+ runs-on : ubuntu-22.04
73+ needs : get_config_values
74+ permissions :
75+ contents : read
76+ packages : read
77+ attestations : read
78+ outputs :
79+ pinned_image : ${{ steps.resolve.outputs.pinned_image }}
80+ resolved_digest : ${{ steps.resolve.outputs.resolved_digest }}
81+ steps :
82+ - name : Login to github container registry
83+ if : startsWith(inputs.registry, 'ghcr.io')
84+ uses : docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
85+ with :
86+ registry : ghcr.io
87+ username : ${{ github.actor }}
88+ password : ${{ secrets.GITHUB_TOKEN }}
7089
71- verify_attestation :
72- runs-on : ubuntu-22.04
73- needs : get_config_values
74- permissions :
75- contents : read
76- packages : read
77- attestations : read
78- outputs :
79- pinned_image : ${{ steps.resolve.outputs.pinned_image }}
80- resolved_digest : ${{ steps.resolve.outputs.resolved_digest }}
81- steps :
82- - name : Login to github container registry
83- if : startsWith(inputs.registry, 'ghcr.io')
84- uses : docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
85- with :
86- registry : ghcr.io
87- username : ${{ github.actor }}
88- password : ${{ secrets.GITHUB_TOKEN }}
90+ - name : Resolve digest
91+ id : resolve
92+ shell : bash
93+ env :
94+ RUNTIME_DOCKER_IMAGE : ${{ needs.get_config_values.outputs.runtime_docker_image }}
95+ REGISTRY : ${{ inputs.registry }}
96+ NAMESPACE : ${{ inputs.namespace }}
97+ run : |
98+ set -euo pipefail
8999
90- - name : Resolve digest
91- id : resolve
92- shell : bash
93- env :
94- RUNTIME_DOCKER_IMAGE : ${{ needs.get_config_values.outputs.runtime_docker_image }}
95- REGISTRY : ${{ inputs.registry }}
96- NAMESPACE : ${{ inputs.namespace }}
97- run : |
98- set -euo pipefail
100+ if [[ "$RUNTIME_DOCKER_IMAGE" == *"/"* ]]; then
101+ IMAGE_REF="$RUNTIME_DOCKER_IMAGE"
102+ else
103+ IMAGE_REF="${REGISTRY}/${NAMESPACE}/${RUNTIME_DOCKER_IMAGE}"
104+ fi
99105
100- if [[ "$RUNTIME_DOCKER_IMAGE" == *"/"* ]]; then
101- IMAGE_REF="$RUNTIME_DOCKER_IMAGE"
102- else
103- IMAGE_REF="${REGISTRY}/${NAMESPACE}/${RUNTIME_DOCKER_IMAGE}"
104- fi
106+ if [[ "$IMAGE_REF" == *@sha256:* ]]; then
107+ IMAGE_BASE="${IMAGE_REF%@*}"
108+ RESOLVED_DIGEST="${IMAGE_REF#*@}"
109+ else
110+ RESOLVED_DIGEST=""
111+ MAX_ATTEMPTS=5
112+ for attempt in $(seq 1 "$MAX_ATTEMPTS"); do
113+ if OUTPUT="$(docker buildx imagetools inspect "$IMAGE_REF" 2>&1)"; then
114+ RESOLVED_DIGEST="$(awk '/^Digest:/ {print $2; exit}' <<< "$OUTPUT")"
115+ if [[ -n "$RESOLVED_DIGEST" ]]; then
116+ break
117+ fi
118+ echo "Digest not found in imagetools output (attempt ${attempt}/${MAX_ATTEMPTS})." >&2
119+ else
120+ echo "Failed to inspect image ${IMAGE_REF} (attempt ${attempt}/${MAX_ATTEMPTS})." >&2
121+ echo "$OUTPUT" >&2
122+ fi
105123
106- if [[ "$IMAGE_REF" == *@sha256:* ]]; then
107- IMAGE_BASE="${IMAGE_REF%@*}"
108- RESOLVED_DIGEST="${IMAGE_REF#*@}"
109- else
110- RESOLVED_DIGEST="$(docker buildx imagetools inspect "$IMAGE_REF" | awk '/^Digest:/ {print $2; exit}')"
111- IMAGE_BASE="${IMAGE_REF%:*}"
112- fi
124+ if [[ "$attempt" -lt "$MAX_ATTEMPTS" ]]; then
125+ sleep $((attempt * 2))
126+ fi
127+ done
128+ IMAGE_BASE="${IMAGE_REF%:*}"
129+ fi
113130
114- if [[ -z "$RESOLVED_DIGEST" ]]; then
115- echo "Could not resolve digest for image: $IMAGE_REF" >&2
116- exit 1
117- fi
131+ if [[ -z "$RESOLVED_DIGEST" ]]; then
132+ echo "Could not resolve digest for image: $IMAGE_REF" >&2
133+ exit 1
134+ fi
118135
119- PINNED_IMAGE="${IMAGE_BASE}@${RESOLVED_DIGEST}"
120- echo "resolved_digest=${RESOLVED_DIGEST}" >> "$GITHUB_OUTPUT"
121- echo "pinned_image=${PINNED_IMAGE}" >> "$GITHUB_OUTPUT"
122- echo "Resolved image reference: ${IMAGE_REF}"
123- echo "Resolved digest: ${RESOLVED_DIGEST}"
124- echo "Resolved image reference: ${PINNED_IMAGE}"
136+ PINNED_IMAGE="${IMAGE_BASE}@${RESOLVED_DIGEST}"
137+ echo "resolved_digest=${RESOLVED_DIGEST}" >> "$GITHUB_OUTPUT"
138+ echo "pinned_image=${PINNED_IMAGE}" >> "$GITHUB_OUTPUT"
139+ echo "Resolved image reference: ${IMAGE_REF}"
140+ echo "Resolved digest: ${RESOLVED_DIGEST}"
141+ echo "Resolved image reference: ${PINNED_IMAGE}"
125142
126- - name : Verify attestation
127- shell : bash
128- env :
129- GH_TOKEN : ${{ github.token }}
130- OWNER : ${{ inputs.owner }}
131- VERIFY_PUBLISHED_FROM_MAIN_IMAGE : ${{ inputs.verify_published_from_main_image }}
132- PREDICATE_TYPE : ${{ inputs.predicate_type }}
133- PINNED_IMAGE : ${{ steps.resolve.outputs.pinned_image }}
134- run : |
135- set -euo pipefail
143+ - name : Verify attestation
144+ shell : bash
145+ env :
146+ GH_TOKEN : ${{ github.token }}
147+ OWNER : ${{ inputs.owner }}
148+ VERIFY_PUBLISHED_FROM_MAIN_IMAGE : ${{ inputs.verify_published_from_main_image }}
149+ PREDICATE_TYPE : ${{ inputs.predicate_type }}
150+ PINNED_IMAGE : ${{ steps.resolve.outputs.pinned_image }}
151+ run : |
152+ set -euo pipefail
136153
137- args=("oci://${PINNED_IMAGE}" "--owner" "$OWNER" "--predicate-type" "$PREDICATE_TYPE")
154+ args=("oci://${PINNED_IMAGE}" "--owner" "$OWNER" "--predicate-type" "$PREDICATE_TYPE")
138155
139- if [[ "$VERIFY_PUBLISHED_FROM_MAIN_IMAGE" == "true" ]]; then
140- args+=("--source-ref" "refs/heads/main")
141- fi
156+ if [[ "$VERIFY_PUBLISHED_FROM_MAIN_IMAGE" == "true" ]]; then
157+ args+=("--source-ref" "refs/heads/main")
158+ fi
142159
143160
144- GH_FORCE_TTY=120 gh attestation verify "${args[@]}" 2>&1
145- echo "Verified attestation for ${PINNED_IMAGE}"
161+ GH_FORCE_TTY=120 gh attestation verify "${args[@]}" 2>&1
162+ echo "Verified attestation for ${PINNED_IMAGE}"
0 commit comments