Conversation
…S packages mix.lock has exact versions + checksums for the Hex dependency tree, but it's not a real SBOM - wrong format (Erlang-term syntax, not SPDX/ CycloneDX), no license data, and doesn't cover the OTP/ERTS runtime Burrito bundles into each binary or the Alpine packages baked into the container image. Two real SBOMs, kept as separate files since a container SBOM has no use to anyone not using the container: - App + Hex deps + Erlang/OTP + Elixir runtime, via erlef/mix_sbom (verified: includes the OTP standard library apps - kernel/stdlib/ crypto/ssl/etc - and Elixir at the exact pinned version by default, no manual merge needed). Generated in the burrito job, attached to the release as sbom.cdx.json in the same atomic `gh release create` call that creates the release. - Container OS packages (Alpine/apk), via aquasecurity/trivy-action (--format cyclonedx). Generated in the container job, which runs after the release is already published (and thus immutable, #18) - published as a workflow artifact, not a release asset, since it genuinely can't be attached to the already-locked release. Closes #53. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds automated generation and publishing of Software Bill of Materials (SBOM) outputs as part of the release pipeline, covering both application/runtime dependencies and container OS packages, and documents the new artifacts for users.
Changes:
- Generate an app/runtime CycloneDX SBOM during the Burrito release job and upload it with the GitHub release assets.
- Generate a separate CycloneDX SBOM for container OS packages via Trivy and upload it as a workflow artifact.
- Document the SBOM outputs in the README and add the SBOM tooling dependency to the app.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| Readme.adoc | Documents the new SBOM outputs and where they are published. |
| app/mix.exs | Adds the :sbom dependency for local/dev SBOM generation. |
| app/mix.lock | Locks new transitive deps introduced by :sbom. |
| .github/workflows/main.yaml | Implements app SBOM generation/upload in the release job and container SBOM generation/upload in the container job. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Two review findings on #54: - `~> 0.8` doesn't allow 0.10.0 (Elixir's ~> pins the second segment tight for pre-1.0 versions), but mix.lock already resolved to 0.10.0 - the exact version already tested. Widened to `~> 0.10` rather than downgrading. - erlef/mix_sbom has no output-filename input (verified directly in the action's own script: it always writes to $RUNNER_TEMP/$RANDOM.cdx.json, exposed via sbom-path). gh release create uses a file's own basename as the actual download filename - the `#label` syntax only sets a cosmetic display label, not the filename - so without an explicit rename, the Readme's documented .../download/sbom.cdx.json URL would 404. Added a rename step.
bougyman
pushed a commit
that referenced
this pull request
Aug 10, 2026
🤖 I have created a release *beep* *boop* --- ## [0.8.3](v0.8.2...v0.8.3) (2026-08-10) ### Features * **ci:** add a full SBOM - app deps, OTP/Elixir runtime, container OS packages ([#54](#54)) ([e296fdd](e296fdd)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #53.
mix.lockhas exact versions + checksums for the Hex dependency tree, but it's not a real SBOM - wrong format (Erlang-term syntax, not SPDX/CycloneDX), no license data, and doesn't cover the OTP/ERTS runtime Burrito bundles into each binary or the Alpine packages baked into the container image.Two real SBOMs, kept as separate files since a container SBOM has no use to anyone not using the container:
erlef/mix_sbom(verified: includes the OTP standard library apps -kernel/stdlib/crypto/ssl/etc - and Elixir at the exact pinned version by default, no manual merge needed). Generated in theburritojob, attached to the release assbom.cdx.jsonin the same atomicgh release createcall that creates the release.aquasecurity/trivy-action(--format cyclonedx). Generated in thecontainerjob, which runs after the release is already published (and thus immutable, Releases ship with zero assets - GitHub's Immutable Releases locks them before the build finishes #18) - published as a workflow artifact, not a release asset, since it genuinely can't be attached to the already-locked release.Test plan
mix test- 182 passedmix format --check-formatted- cleanmix sbom.cyclonedxfor real locally and inspected the actual output - confirmed it includeselixirat our exact pinned version (1.20.3) plus the OTP standard library apps, alongside all real Hex deps (67 components total)aquasecurity/trivy-action'sformatinput passes straight through to Trivy's own CLI (checkedentrypoint.shdirectly - onlysarif/githubare special-cased,cyclonedxisn't)ci/build_image.shproduces (linear-cli-ex:<tag>, no registry prefix) so Trivy scans the right referenceruby -ryaml,asciidoctor -o /dev/null)sbom.cdx.jsonattached to the release, and acontainer-sbomworkflow artifact on the container job🤖 Generated with Claude Code