@@ -91,33 +91,97 @@ runs:
9191
9292 SBOM_FILE="${{ steps.find-sbom.outputs.sbom_file }}"
9393 IMAGE_REF="${{ inputs.image_name }}@${{ inputs.image_digest }}"
94+ MAX_RETRIES=3
95+ RETRY_DELAY=5
96+
97+ # Function to attest with retry logic
98+ attest_with_retry() {
99+ local target_ref="$1"
100+ local platform_info="${2:-unknown}"
101+ local attempt=1
102+
103+ while [ $attempt -le $MAX_RETRIES ]; do
104+ echo "Attesting ${target_ref} (${platform_info}) - attempt ${attempt}/${MAX_RETRIES}"
105+
106+ if cosign attest \
107+ --yes \
108+ --predicate "$SBOM_FILE" \
109+ --type cyclonedx \
110+ "$target_ref" 2>&1 | tee /tmp/cosign_output.log; then
111+
112+ # Verify attestation was created by checking for success indicators
113+ if grep -q "tlog entry created\|Attestation written\|successfully" /tmp/cosign_output.log || \
114+ [ ${PIPESTATUS[0]} -eq 0 ]; then
115+ echo "✓ Attestation successful for ${target_ref}"
116+
117+ # Additional verification: check if attestation exists in registry
118+ sleep 2 # Brief delay for registry propagation
119+ if cosign verify-attestation \
120+ --type cyclonedx \
121+ --certificate-identity-regexp=".*" \
122+ --certificate-oidc-issuer-regexp=".*" \
123+ "$target_ref" &>/dev/null; then
124+ echo "✓ Attestation verified in registry for ${target_ref}"
125+ return 0
126+ else
127+ echo "⚠ Attestation created but not yet visible in registry, continuing anyway"
128+ return 0
129+ fi
130+ fi
131+ fi
132+
133+ # If we get here, attestation failed
134+ echo "✗ Attestation attempt ${attempt} failed for ${target_ref}"
135+ cat /tmp/cosign_output.log || true
136+
137+ if [ $attempt -lt $MAX_RETRIES ]; then
138+ echo "Retrying in ${RETRY_DELAY} seconds..."
139+ sleep $RETRY_DELAY
140+ attempt=$((attempt + 1))
141+ else
142+ echo "::error::Failed to attest ${target_ref} after ${MAX_RETRIES} attempts"
143+ return 1
144+ fi
145+ done
146+ }
94147
95148 # Check if this is a multi-platform image (OCI index)
96149 MANIFEST_TYPE=$(crane manifest "$IMAGE_REF" | jq -r '.mediaType // "unknown"')
97150
98151 if [[ "$MANIFEST_TYPE" == "application/vnd.oci.image.index.v1+json" ]] || \
99152 [[ "$MANIFEST_TYPE" == "application/vnd.docker.distribution.manifest.list.v2+json" ]]; then
100153 # Multi-platform: attest each platform digest separately
101- PLATFORM_DIGESTS=$(crane manifest "$IMAGE_REF" | \
102- jq -r '.manifests[] | select((.annotations."vnd.docker.reference.type" // "") != "attestation-manifest") | .digest')
154+ echo "Detected multi-platform image, will attest each platform separately"
103155
104- while IFS= read -r DIGEST; do
105- echo "Attesting ${{ inputs.image_name }}@${DIGEST}"
106- cosign attest \
107- --yes \
108- --predicate "$SBOM_FILE" \
109- --type cyclonedx \
110- "${{ inputs.image_name }}@${DIGEST}"
111- done <<< "$PLATFORM_DIGESTS"
156+ # Get platform digests with architecture info
157+ PLATFORM_INFO=$(crane manifest "$IMAGE_REF" | \
158+ jq -r '.manifests[] | select((.annotations."vnd.docker.reference.type" // "") != "attestation-manifest") | "\(.digest) \(.platform.architecture)/\(.platform.os)"')
159+
160+ FAILED_PLATFORMS=()
161+ while IFS= read -r line; do
162+ DIGEST=$(echo "$line" | awk '{print $1}')
163+ PLATFORM=$(echo "$line" | awk '{print $2}')
164+
165+ if ! attest_with_retry "${{ inputs.image_name }}@${DIGEST}" "$PLATFORM"; then
166+ FAILED_PLATFORMS+=("$PLATFORM ($DIGEST)")
167+ fi
168+ done <<< "$PLATFORM_INFO"
169+
170+ # Check if any platforms failed
171+ if [ ${#FAILED_PLATFORMS[@]} -gt 0 ]; then
172+ echo "::error::Failed to attest the following platforms:"
173+ printf '::error:: - %s\n' "${FAILED_PLATFORMS[@]}"
174+ exit 1
175+ fi
176+
177+ echo "✓ All platform attestations completed successfully"
112178 else
113179 # Single-platform: attest directly
114- echo "Attesting $IMAGE_REF"
115- cosign attest \
116- --yes \
117- --predicate "$SBOM_FILE" \
118- --type cyclonedx \
119- "$IMAGE_REF"
180+ echo "Detected single-platform image"
181+ attest_with_retry "$IMAGE_REF" "single-platform"
120182 fi
183+
184+ echo "✓ SBOM attestation process completed"
121185
122186 - name : Attest build provenance
123187 uses : actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
0 commit comments