| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- name: Generate SBOM
- on:
- workflow_run:
- workflows: ["Build and Publish Release"]
- types:
- - completed
- workflow_dispatch:
- inputs:
- release_version:
- description: "Version of the release to generate SBOM for"
- required: true
- pull_request:
- branches:
- - develop
- permissions: read-all
- concurrency:
- group: sbom-${{ github.ref }}
- cancel-in-progress: true
- env:
- REGISTRY: ghcr.io
- jobs:
- generate-sbom:
- runs-on: ubuntu-latest
- if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
- permissions:
- contents: write
- actions: read
- packages: read
- steps:
- - name: Checkout Repo (for version detection)
- if: github.event_name == 'workflow_run'
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Get Version From Workflow Run
- id: tag
- if: github.event_name == 'workflow_run'
- run: |
- # Get the SHA from the workflow run
- SHA="${{ github.event.workflow_run.head_sha }}"
- # Find the tag pointing to this SHA
- TAG=$(git tag --points-at $SHA | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
- if [ -z "$TAG" ]; then
- echo "Error: No version tag found for SHA $SHA"
- exit 1
- fi
- echo "TRIGGERED_TAG=$TAG" >> $GITHUB_ENV
- echo "Found tag: $TAG"
- - name: Determine Version Number
- id: version_number
- run: |
- if [ "${{ github.event_name }}" == "workflow_run" ]; then
- version=$TRIGGERED_TAG
- elif [ -n "${{ inputs.release_version }}" ]; then
- version=${{ inputs.release_version }}
- else
- version=""
- 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
- if: github.event_name != 'workflow_run'
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event_name != 'pull_request' && steps.branch.outputs.BRANCH_NAME || '' }}
- - name: Set OpenCost Image Tag
- id: image_tag
- if: github.event_name != 'pull_request'
- env:
- REPO_OWNER: ${{ github.repository_owner }}
- RELEASE_VERSION: ${{ steps.version_number.outputs.RELEASE_VERSION }}
- run: |
- echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:$RELEASE_VERSION" >> $GITHUB_OUTPUT
- # Generate SBOM for source code using Trivy
- - name: Run Trivy SBOM for Source Code (SPDX)
- uses: aquasecurity/trivy-action@master
- with:
- scan-type: 'fs'
- scan-ref: '.'
- format: 'spdx-json'
- output: 'opencost-source-sbom.spdx.json'
- - name: Run Trivy SBOM for Source Code (CycloneDX)
- uses: aquasecurity/trivy-action@master
- with:
- scan-type: 'fs'
- scan-ref: '.'
- format: 'cyclonedx'
- output: 'opencost-source-sbom.cyclonedx.json'
- # Generate SBOM for container image using Trivy
- - name: Run Trivy SBOM for Container Image (SPDX)
- if: github.event_name != 'pull_request'
- uses: aquasecurity/trivy-action@master
- with:
- scan-type: 'image'
- image-ref: ${{ steps.image_tag.outputs.IMAGE_TAG }}
- format: 'spdx-json'
- output: 'opencost-container-sbom.spdx.json'
- - name: Run Trivy SBOM for Container Image (CycloneDX)
- if: github.event_name != 'pull_request'
- uses: aquasecurity/trivy-action@master
- with:
- scan-type: 'image'
- image-ref: ${{ steps.image_tag.outputs.IMAGE_TAG }}
- format: 'cyclonedx'
- output: 'opencost-container-sbom.cyclonedx.json'
- # Display SBOM contents on PRs for review
- - name: Display SBOM Contents
- if: github.event_name == 'pull_request'
- run: |
- echo "## SBOM Contents (SPDX Format)" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "### Package Count" >> $GITHUB_STEP_SUMMARY
- PACKAGE_COUNT=$(jq '.packages | length' opencost-source-sbom.spdx.json)
- echo "Total packages: $PACKAGE_COUNT" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "### Top-level Packages" >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- jq -r '.packages[] | select(.name != null) | "\(.name) - \(.versionInfo // "unknown")"' opencost-source-sbom.spdx.json | head -50 >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "<details>" >> $GITHUB_STEP_SUMMARY
- echo "<summary>Full SPDX SBOM (click to expand)</summary>" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo '```json' >> $GITHUB_STEP_SUMMARY
- cat opencost-source-sbom.spdx.json >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- echo "</details>" >> $GITHUB_STEP_SUMMARY
- # Upload SBOMs as artifacts
- - name: Upload SBOM Artifacts
- uses: actions/upload-artifact@v4
- with:
- name: sbom-files
- path: |
- opencost-source-sbom.spdx.json
- opencost-source-sbom.cyclonedx.json
- opencost-container-sbom.spdx.json
- opencost-container-sbom.cyclonedx.json
- if-no-files-found: ignore
- # Attach SBOMs to GitHub release (only for releases, not PRs)
- - name: Attach SBOMs to GitHub Release
- if: github.event_name != 'pull_request'
- uses: softprops/action-gh-release@v1
- with:
- tag_name: v${{ steps.version_number.outputs.RELEASE_VERSION }}
- files: |
- opencost-source-sbom.spdx.json
- opencost-source-sbom.cyclonedx.json
- opencost-container-sbom.spdx.json
- opencost-container-sbom.cyclonedx.json
- fail_on_unmatched_files: false
- # 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 [ "${{ github.event_name }}" != "pull_request" ]; then
- echo "📦 SBOMs have been attached to the GitHub release" >> $GITHUB_STEP_SUMMARY
- fi
|