Skip to content

feat(ci): add a full SBOM - app deps, OTP/Elixir runtime, container OS packages - #54

Merged
bougyman merged 3 commits into
mainfrom
issue-53
Aug 10, 2026
Merged

feat(ci): add a full SBOM - app deps, OTP/Elixir runtime, container OS packages#54
bougyman merged 3 commits into
mainfrom
issue-53

Conversation

@bougyman

@bougyman bougyman commented Aug 10, 2026

Copy link
Copy Markdown
Member

Summary

Closes #53.

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, 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 passed
  • mix format --check-formatted - clean
  • Ran mix sbom.cyclonedx for real locally and inspected the actual output - confirmed it includes elixir at our exact pinned version (1.20.3) plus the OTP standard library apps, alongside all real Hex deps (67 components total)
  • Verified aquasecurity/trivy-action's format input passes straight through to Trivy's own CLI (checked entrypoint.sh directly - only sarif/github are special-cased, cyclonedx isn't)
  • Confirmed the exact local image tag ci/build_image.sh produces (linear-cli-ex:<tag>, no registry prefix) so Trivy scans the right reference
  • Both edited workflow/doc files validated (ruby -ryaml, asciidoctor -o /dev/null)
  • Next real release should show both new steps succeed, sbom.cdx.json attached to the release, and a container-sbom workflow artifact on the container job

🤖 Generated with Claude Code

…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>
Copilot AI lite review requested due to automatic review settings August 10, 2026 13:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread app/mix.exs Outdated
Comment thread .github/workflows/main.yaml
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
bougyman merged commit e296fdd into main Aug 10, 2026
2 checks passed
@bougyman
bougyman deleted the issue-53 branch August 10, 2026 14:12
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a full SBOM: app deps, Erlang/OTP + Elixir runtime, and container OS packages

2 participants