@@ -496,6 +496,37 @@ jobs:
496496 env :
497497 CODER_BASE_IMAGE_TAG : ${{ steps.image-base-tag.outputs.tag }}
498498
499+ - name : SBOM Generation and Attestation
500+ if : ${{ !inputs.dry_run }}
501+ run : |
502+ set -euxo pipefail
503+
504+ # Generate SBOM for multi-arch image with version in filename
505+ echo "Generating SBOM for multi-arch image: ${{ steps.build_docker.outputs.multiarch_image }}"
506+ syft "${{ steps.build_docker.outputs.multiarch_image }}" -o spdx-json > coder_${{ steps.version.outputs.version }}_sbom.spdx.json
507+
508+ # Attest SBOM to multi-arch image
509+ echo "Attesting SBOM to multi-arch image: ${{ steps.build_docker.outputs.multiarch_image }}"
510+ COSIGN_EXPERIMENTAL=1 cosign clean "${{ steps.build_docker.outputs.multiarch_image }}"
511+ COSIGN_EXPERIMENTAL=1 cosign attest --type spdxjson \
512+ --predicate coder_${{ steps.version.outputs.version }}_sbom.spdx.json \
513+ --yes \
514+ "${{ steps.build_docker.outputs.multiarch_image }}"
515+
516+ # If latest tag was created, also attest it
517+ if [[ "${{ steps.build_docker.outputs.created_latest_tag }}" == "true" ]]; then
518+ latest_tag="$(./scripts/image_tag.sh --version latest)"
519+ echo "Generating SBOM for latest image: ${latest_tag}"
520+ syft "${latest_tag}" -o spdx-json > coder_latest_sbom.spdx.json
521+
522+ echo "Attesting SBOM to latest image: ${latest_tag}"
523+ COSIGN_EXPERIMENTAL=1 cosign clean "${latest_tag}"
524+ COSIGN_EXPERIMENTAL=1 cosign attest --type spdxjson \
525+ --predicate coder_latest_sbom.spdx.json \
526+ --yes \
527+ "${latest_tag}"
528+ fi
529+
499530 - name : GitHub Attestation for Docker image
500531 id : attest_main
501532 if : ${{ !inputs.dry_run }}
@@ -612,16 +643,27 @@ jobs:
612643 fi
613644 declare -p publish_args
614645
646+ # Build the list of files to publish
647+ files=(
648+ ./build/*_installer.exe
649+ ./build/*.zip
650+ ./build/*.tar.gz
651+ ./build/*.tgz
652+ ./build/*.apk
653+ ./build/*.deb
654+ ./build/*.rpm
655+ ./coder_${{ steps.version.outputs.version }}_sbom.spdx.json
656+ )
657+
658+ # Only include the latest SBOM file if it was created
659+ if [[ "${{ steps.build_docker.outputs.created_latest_tag }}" == "true" ]]; then
660+ files+=(./coder_latest_sbom.spdx.json)
661+ fi
662+
615663 ./scripts/release/publish.sh \
616664 "${publish_args[@]}" \
617665 --release-notes-file "$CODER_RELEASE_NOTES_FILE" \
618- ./build/*_installer.exe \
619- ./build/*.zip \
620- ./build/*.tar.gz \
621- ./build/*.tgz \
622- ./build/*.apk \
623- ./build/*.deb \
624- ./build/*.rpm
666+ "${files[@]}"
625667 env :
626668 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
627669 CODER_GPG_RELEASE_KEY_BASE64 : ${{ secrets.GPG_RELEASE_KEY_BASE64 }}
@@ -663,6 +705,15 @@ jobs:
663705 ./build/*.apk
664706 ./build/*.deb
665707 ./build/*.rpm
708+ ./coder_${{ steps.version.outputs.version }}_sbom.spdx.json
709+ retention-days : 7
710+
711+ - name : Upload latest sbom artifact to actions (if dry-run)
712+ if : inputs.dry_run && steps.build_docker.outputs.created_latest_tag == 'true'
713+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
714+ with :
715+ name : latest-sbom-artifact
716+ path : ./coder_latest_sbom.spdx.json
666717 retention-days : 7
667718
668719 - name : Send repository-dispatch event
0 commit comments