From f5e3e5e35622f7f410872962f8107220ac2b35f5 Mon Sep 17 00:00:00 2001 From: Alvar Penning Date: Tue, 3 Nov 2026 16:07:40 +0100 Subject: [PATCH] sbom: Initial GitHub Actions For SBOM Generation Create a CycloneDX SBOM via syft from all available information in the repository and attach it as a build artifact. If the workflow action is run on a Pull Request, do the same for the base branch, compare the results, and add a PR warning if something changed. Time will tell if this is useful or just annoying. While on it, enable SBOM generation for docker/build-push-action. These are all first steps to find out what might make sense. --- .github/workflows/container-image.yml | 1 + .github/workflows/sbom.yml | 53 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 .github/workflows/sbom.yml diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml index 2d5a89e..de44421 100644 --- a/.github/workflows/container-image.yml +++ b/.github/workflows/container-image.yml @@ -172,6 +172,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} + sbom: true # The tags generated in the metadata step include tags for both Docker Hub and GHCR image names, # allowing the build and push action to build and push images to both registries. tags: ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml new file mode 100644 index 0000000..494d967 --- /dev/null +++ b/.github/workflows/sbom.yml @@ -0,0 +1,53 @@ +on: + workflow_call: + +permissions: + contents: read + +jobs: + sbom: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + path: head + persist-credentials: false + + - name: Generate SBOM + uses: anchore/sbom-action@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 + with: + path: head + format: cyclonedx-json + output-file: sbom.cdx.json + artifact-name: sbom.cdx.json + upload-release-assets: false + + - name: Checkout base + if: github.event_name == 'pull_request' + uses: actions/checkout@v7 + with: + ref: ${{ github.event.pull_request.base.sha }} + path: base + persist-credentials: false + + - name: Generate base SBOM + if: github.event_name == 'pull_request' + uses: anchore/sbom-action@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 + with: + path: base + format: cyclonedx-json + output-file: sbom-base.cdx.json + upload-artifact: false + upload-release-assets: false + + - name: Compare SBOMs + if: github.event_name == 'pull_request' + shell: bash + run: | + purls() { jq -r '.components[]?.purl // empty' "$1" | sort -u; } + purls sbom-base.cdx.json > "$RUNNER_TEMP/base.txt" + purls sbom.cdx.json > "$RUNNER_TEMP/head.txt" + comm -3 "$RUNNER_TEMP/base.txt" "$RUNNER_TEMP/head.txt" | sed \ + -e 's/^\t/::warning title=SBOM changed::Added /;t' \ + -e 's/^/::warning title=SBOM changed::Removed /'