Added unit tests. #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Generate SBOM | ||
|
Check failure on line 1 in .github/workflows/sbom.yml
|
||
| 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: ${{ github.event_name == 'pull_request' && 'read' || '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 '^v[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 | ||
| - 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: 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 | ||
| # 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 | ||
| # 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 | ||
| - 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 | ||
| # Publish SBOMs to GitHub release (only for releases, not PRs) | ||
| - name: Attach SBOMs to GitHub Release | ||
| if: github.event_name != 'pull_request' | ||
| 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 [ "${{ github.event_name }}" != "pull_request" ]; then | ||
| echo "📦 SBOMs have been attached to the GitHub release" >> $GITHUB_STEP_SUMMARY | ||
| fi | ||