Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 70 additions & 16 deletions .github/workflows/ci-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,33 @@ jobs:
password: ${{ secrets.HARBOR_PASSWORD }}

- name: Sign manifest
env:
IMAGE: ${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}
run: |
cosign sign --yes --recursive --new-bundle-format=false --use-signing-config=false \
"${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}"
# cosign gives up after two internal attempts when a Sigstore transparency
# log write fails, so a brief rekor.sigstore.dev blip is enough to fail a
# release. Retry the whole command instead; five attempts 60s apart cover a
# ~4-minute outage. The sbom job carries a verbatim copy of this function:
# the jobs run on separate runners, so sharing it would take a checkout or a
# third-party action in the signing path. Keep the two copies identical.
retry() {
local attempt
for attempt in 1 2 3 4 5; do
if "$@"; then
return 0
fi
if [ "${attempt}" -lt 5 ]; then
echo "::warning::${1} ${2} failed (attempt ${attempt}/5), retrying in 60s"
sleep 60
fi
done
echo "::error::${1} ${2} failed after 5 attempts"
return 1
}

retry cosign sign --yes --recursive \
--new-bundle-format=false --use-signing-config=false \
"${IMAGE}"

sbom:
needs: merge
Expand Down Expand Up @@ -236,20 +260,16 @@ jobs:
"${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}" \
--output cyclonedx-json=infrahub-sbom.cdx.json

- name: Attest SBOM (SPDX)
run: |
cosign attest --yes \
--type spdxjson \
--predicate infrahub-sbom.spdx.json \
"${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}"

- name: Attest SBOM (CycloneDX)
run: |
cosign attest --yes \
--type cyclonedx \
--predicate infrahub-sbom.cdx.json \
"${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}"

# Uploaded before the attestations so that a transparency-log outage cannot cost
# us the SBOMs themselves: v1.10.7 shipped without any because the attest step
# failed first and skipped this one.
#
# overwrite is required precisely because this now runs before a step that can
# fail. Artifacts are scoped to the run rather than the attempt, so on a re-run
# this name already exists from the earlier attempt and the default overwrite:
# false would fail the upload, breaking the recovery path this ordering exists to
# protect. Every caller passes a version unique to its invocation, so the only
# artifact this can replace is the same SBOM from a previous attempt.
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v7
with:
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Expand All @@ -258,3 +278,37 @@ jobs:
infrahub-sbom.spdx.json
infrahub-sbom.cdx.json
retention-days: 90
overwrite: true

- name: Attest SBOMs
env:
IMAGE: ${{ vars.HARBOR_HOST }}/${{ github.repository }}@${{ needs.merge.outputs.digest }}
run: |
# Same transparency-log flakiness the sign job guards against; this is a
# verbatim copy of that job's retry function (separate runners, so it cannot
# be shared without a checkout or a third-party action in the signing path).
# Keep the two copies identical.
retry() {
local attempt
for attempt in 1 2 3 4 5; do
if "$@"; then
return 0
fi
if [ "${attempt}" -lt 5 ]; then
echo "::warning::${1} ${2} failed (attempt ${attempt}/5), retrying in 60s"
sleep 60
fi
done
echo "::error::${1} ${2} failed after 5 attempts"
return 1
}

retry cosign attest --yes \
--type spdxjson \
--predicate infrahub-sbom.spdx.json \
"${IMAGE}"

retry cosign attest --yes \
--type cyclonedx \
--predicate infrahub-sbom.cdx.json \
"${IMAGE}"
Loading