Fix SBOM root component: replace synthetic closure name with OCI image metadata#3
Fix SBOM root component: replace synthetic closure name with OCI image metadata#3mrdavidlaing wants to merge 3 commits intomainfrom
Conversation
…e metadata bombon names the root component after the symlinkJoin derivation (e.g. "postgres-closure"), which has no version, PURL, license, or dependency links. This causes sbomify-action to warn about an incomplete dependency graph. Post-process the bombon output to set the root component to the actual OCI image with proper name, version, container type, PURL, SPDX license, and dependency relationships to all closure components. https://claude.ai/code/session_01NfQFeoLwbv5VJNEne5NRoA
…spec tests Move the jq post-processing logic that rewrites bombon's synthetic root component into a standalone script (bin/patch-sbom-root) that reads from stdin and writes to stdout. Both generate-sboms.sh and the CI workflow now call this shared script instead of duplicating the jq filter. Add shellspec with 18 specs covering argument validation, root component patching, dependency graph wiring, and passthrough behavior. https://claude.ai/code/session_01NfQFeoLwbv5VJNEne5NRoA
Split sbom-generate-upload.yml into three workflows: - sbom-generate.yml: generate, patch, and enrich SBOMs (PR + main) - sbom-quality-gate.yml: score with sbomqs, diff with sbomlyze, post PR comment, block merge on quality regression - sbom-upload.yml: upload enriched SBOMs to sbomify (main only) New TDD scripts (45 shellspec examples, all passing): - bin/sbom-score: wraps sbomqs, outputs structured JSON - bin/sbom-compare: wraps sbomlyze diff with policy checking - bin/sbom-report: aggregates results into markdown, exits non-zero on quality regression https://claude.ai/code/session_01NfQFeoLwbv5VJNEne5NRoA
| - name: postgres | ||
| sbom_package: postgres-sbom | ||
| nixpkg: postgresql_17 | ||
| license: PostgreSQL |
There was a problem hiding this comment.
Can we rather get the license data from the nix package / derivation that we're making for the image?
Ideally by lining the image license to the license of its primary package; in the same way the we do for version
| bin/patch-sbom-root \ | ||
| --name "wellmaintained/packages/${{ matrix.image.name }}-image" \ | ||
| --version "$VERSION" \ | ||
| --purl "pkg:docker/wellmaintained/packages/${{ matrix.image.name }}@${VERSION}" \ | ||
| --license "${{ matrix.image.license }}" \ | ||
| < "$SBOM" > "${SBOM}.tmp" && mv "${SBOM}.tmp" "$SBOM" |
There was a problem hiding this comment.
Same argument here - can we it get the data we need for this patch from the nix expression used to describe the image?
| - name: Install sbomqs | ||
| run: | | ||
| curl -sSfL https://github.com/interlynk-io/sbomqs/releases/latest/download/sbomqs-linux-amd64 \ | ||
| -o /usr/local/bin/sbomqs | ||
| chmod +x /usr/local/bin/sbomqs | ||
|
|
||
| - name: Install sbomlyze | ||
| run: | | ||
| curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sh | ||
| mv ./sbomlyze /usr/local/bin/sbomlyze |
There was a problem hiding this comment.
Can we rather make custom nix packages for these so we can pin to specific versions
| if: >- | ||
| github.event.workflow_run.event == 'pull_request' && | ||
| github.event.workflow_run.conclusion == 'success' | ||
| runs-on: blacksmith-4vcpu-ubuntu-2404 |
There was a problem hiding this comment.
Is there a cheaper blacksmith image type we can use for these jobs where we aren't doing compilation or image building
| sbomify-keycloak | ||
| sbomify-caddy-dev | ||
| sbomify-minio-init | ||
| postgres:PostgreSQL |
There was a problem hiding this comment.
Same comment here - let's embed license info in the nix; not in the CI
Summary
symlinkJoinclosure namebin/patch-sbom-root)sbom-generate-upload.ymlinto three focused workflows with a PR quality gateProblem
bombon names the SBOM root component after the
symlinkJoinderivation (e.g.postgres-closure), which has no version, PURL, license, or dependency links. This causes:WARNING: SBOM dependency graph is incomplete: root component 'postgres-closure'from sbomify-actionWorkflow architecture
The old
sbom-generate-upload.ymlis replaced by three workflows:1.
sbom-generate.yml(PR + main)Generates, patches, and enriches SBOMs. Enrichment uses sbomify-action with
UPLOAD: false— the enriched SBOM is saved as an artifact only.nix build .#postgres-sbom
→ bombon CycloneDX output (root = “postgres-closure”)
→ bin/patch-sbom-root –name wellmaintained/packages/postgres-image –version 17.4 –purl pkg:docker/… –license PostgreSQL
→ sbomify-action (AUGMENT + ENRICH, no upload)
→ artifact: sbom-postgres/postgres.enriched.cdx.json
2.
sbom-quality-gate.yml(PR only)Triggered by
sbom-generate.ymlcompletion. Scores each image's SBOM, compares against the baseline from the last successful main run, and posts a sticky PR comment.Example PR comment output: