Bläddra i källkod

feat: Add SBOM generation workflow using Anchore SBOM Action

This commit introduces a new GitHub Actions workflow for generating
Software Bill of Materials (SBOM) using the Anchore SBOM Action.

Key features:
- Generates SBOM for source code in both SPDX and CycloneDX formats
- Generates SBOM for container images on releases
- Automatically attaches SBOMs to GitHub releases
- Runs on release tags and can be manually triggered
- Includes PR validation for source code SBOMs

The workflow provides comprehensive visibility into project dependencies
and supply chain security, supporting both industry-standard SBOM formats.
Claude 6 månader sedan
förälder
incheckning
98a9b115df
1 ändrade filer med 157 tillägg och 0 borttagningar
  1. 157 0
      .github/workflows/sbom.yml

+ 157 - 0
.github/workflows/sbom.yml

@@ -0,0 +1,157 @@
+name: Generate SBOM
+
+on:
+  push:
+    tags:
+      - 'v[0-9]+.[0-9]+.[0-9]+'
+  workflow_dispatch:
+    inputs:
+      release_version:
+        description: "Version of the release to generate SBOM for"
+        required: true
+  pull_request:
+    branches:
+      - develop
+
+permissions:
+  contents: write
+  actions: read
+
+concurrency:
+  group: sbom-${{ github.ref }}
+  cancel-in-progress: true
+
+env:
+  REGISTRY: ghcr.io
+
+jobs:
+  generate-sbom:
+    runs-on: ubuntu-latest
+    permissions:
+      contents: write
+      actions: read
+      packages: read
+    steps:
+      - name: Get Version From Tag
+        id: tag
+        if: github.event_name == 'push'
+        run: |
+          echo "TRIGGERED_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+
+      - name: Determine Version Number
+        id: version_number
+        env:
+          RELEASE_VERSION: ${{ inputs.release_version }}
+        run: |
+          if [ -z "${TRIGGERED_TAG}" ];
+          then
+            version=$RELEASE_VERSION
+          else
+            version=$TRIGGERED_TAG
+          fi
+          if [[ ${version:0:1} == "v" ]];
+          then
+            echo "RELEASE_VERSION=${version:1}" >> $GITHUB_OUTPUT
+          else
+            echo "RELEASE_VERSION=$version" >> $GITHUB_OUTPUT
+          fi
+
+      - name: Make Branch Name
+        id: branch
+        if: github.event_name != 'pull_request'
+        env:
+          RELEASE_VERSION: ${{ steps.version_number.outputs.RELEASE_VERSION }}
+        run: |
+          echo "BRANCH_NAME=v${RELEASE_VERSION%.*}" >> $GITHUB_OUTPUT
+
+      - name: Checkout Repo
+        uses: actions/checkout@v4
+        with:
+          ref: ${{ github.event_name == 'pull_request' && github.head_ref || steps.branch.outputs.BRANCH_NAME }}
+
+      - name: Set OpenCost Image Tag
+        id: image_tag
+        env:
+          REPO_OWNER: ${{ github.repository_owner }}
+          RELEASE_VERSION: ${{ steps.version_number.outputs.RELEASE_VERSION }}
+        run: |
+          if [ "${{ github.event_name }}" == "pull_request" ]; then
+            echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:develop-latest" >> $GITHUB_OUTPUT
+          else
+            echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:$RELEASE_VERSION" >> $GITHUB_OUTPUT
+          fi
+
+      # Generate SBOM for source code
+      - name: Generate SBOM for Source Code
+        uses: anchore/sbom-action@v0
+        with:
+          path: .
+          artifact-name: opencost-source-sbom.spdx.json
+          output-file: opencost-source-sbom.spdx.json
+          format: spdx-json
+
+      # Generate SBOM for container image
+      - name: Log into registry ${{ env.REGISTRY }}
+        if: github.event_name != 'pull_request'
+        uses: docker/login-action@v3
+        with:
+          registry: ${{ env.REGISTRY }}
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Generate SBOM for Container Image
+        if: github.event_name != 'pull_request'
+        uses: anchore/sbom-action@v0
+        with:
+          image: ${{ steps.image_tag.outputs.IMAGE_TAG }}
+          artifact-name: opencost-container-sbom.spdx.json
+          output-file: opencost-container-sbom.spdx.json
+          format: spdx-json
+          registry-username: ${{ github.actor }}
+          registry-password: ${{ secrets.GITHUB_TOKEN }}
+
+      # Generate CycloneDX format as well for broader compatibility
+      - name: Generate CycloneDX SBOM for Source Code
+        uses: anchore/sbom-action@v0
+        with:
+          path: .
+          artifact-name: opencost-source-sbom.cyclonedx.json
+          output-file: opencost-source-sbom.cyclonedx.json
+          format: cyclonedx-json
+
+      - name: Generate CycloneDX SBOM for Container Image
+        if: github.event_name != 'pull_request'
+        uses: anchore/sbom-action@v0
+        with:
+          image: ${{ steps.image_tag.outputs.IMAGE_TAG }}
+          artifact-name: opencost-container-sbom.cyclonedx.json
+          output-file: opencost-container-sbom.cyclonedx.json
+          format: cyclonedx-json
+          registry-username: ${{ github.actor }}
+          registry-password: ${{ secrets.GITHUB_TOKEN }}
+
+      # Publish SBOMs to GitHub release (only for tagged releases)
+      - name: Attach SBOMs to GitHub Release
+        if: startsWith(github.ref, 'refs/tags/')
+        uses: anchore/sbom-action/publish-sbom@v0
+        with:
+          sbom-artifact-match: ".*\\.spdx\\.json$|.*\\.cyclonedx\\.json$"
+
+      # Create a summary of the SBOM generation
+      - name: Generate Summary
+        run: |
+          echo "## SBOM Generation Summary" >> $GITHUB_STEP_SUMMARY
+          echo "" >> $GITHUB_STEP_SUMMARY
+          echo "✅ Generated SBOMs for OpenCost ${{ steps.version_number.outputs.RELEASE_VERSION || 'PR build' }}" >> $GITHUB_STEP_SUMMARY
+          echo "" >> $GITHUB_STEP_SUMMARY
+          echo "### Generated Artifacts:" >> $GITHUB_STEP_SUMMARY
+          echo "- Source Code SBOM (SPDX)" >> $GITHUB_STEP_SUMMARY
+          echo "- Source Code SBOM (CycloneDX)" >> $GITHUB_STEP_SUMMARY
+          if [ "${{ github.event_name }}" != "pull_request" ]; then
+            echo "- Container Image SBOM (SPDX)" >> $GITHUB_STEP_SUMMARY
+            echo "- Container Image SBOM (CycloneDX)" >> $GITHUB_STEP_SUMMARY
+          fi
+          echo "" >> $GITHUB_STEP_SUMMARY
+          if [ "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]; then
+            echo "📦 SBOMs have been attached to the GitHub release" >> $GITHUB_STEP_SUMMARY
+          fi