Skip to content

build: hash-pin dependencies + SBOM + blocking pip-audit (closes #3)#9

Merged
gesh75 merged 1 commit into
mainfrom
claude/dep-pinning-sbom
Jun 28, 2026
Merged

build: hash-pin dependencies + SBOM + blocking pip-audit (closes #3)#9
gesh75 merged 1 commit into
mainfrom
claude/dep-pinning-sbom

Conversation

@gesh75

@gesh75 gesh75 commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

Implements P0.3 from aegis/docs/NEXT_STEPS.md — the supply-chain hardening that lets the dependency-audit gate become meaningful. Closes #3.

Changes

  • aegis/requirements.lock — fully hash-pinned dependency tree generated with pip-compile --generate-hashes. requirements.txt stays the human-edited input (with a regeneration note); CI installs the lock with pip install --require-hashes for reproducible builds.
  • CI (.github/workflows/ci.yml):
    • test job installs from requirements.lock (hash-verified).
    • pip-audit is now blocking (was informational) against the locked tree.
    • New sbom job emits a CycloneDX SBOM (argus-sbom.cdx.json) as a build artifact via cyclonedx-bom; upload uses the SHA-pinned upload-artifact.

Testing (local)

  • Clean venv pip install --require-hashes -r requirements.lock81 tests pass.
  • pip-audit -r requirements.lock --strict0 known vulnerabilities.
  • SBOM generates: CycloneDX 1.6, 43 components.

Follow-up

The lock currently includes the dev/test dep (pytest) since requirements.txt mixes runtime and dev. Splitting runtime vs dev deps (so the SBOM reflects runtime only) is a minor future refinement.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by Sourcery

Introduce a hash-pinned dependency lockfile, enforce reproducible and vulnerability-audited installs in CI, and generate a CycloneDX SBOM as a build artifact.

New Features:

  • Add a CycloneDX SBOM generation job that produces and uploads an SBOM artifact from the dependency lockfile.

Enhancements:

  • Document the new dependency locking and SBOM process in NEXT_STEPS and annotate requirements.txt with lockfile regeneration instructions.

Build:

  • Add a requirements.lock file with a fully hash-pinned dependency tree to support reproducible installs.
  • Clarify that requirements.txt is the human-edited source for regenerating the hash-pinned lockfile.

CI:

  • Update the test job to install dependencies from the hash-pinned requirements.lock using pip's require-hashes mode.
  • Change the pip-audit job from informational to blocking and run it against the locked dependency tree.
  • Add a dedicated SBOM job in CI that generates a CycloneDX SBOM from requirements.lock and uploads it as an artifact.

…p-audit

Closes the P0.3 supply-chain item from NEXT_STEPS.md.

- requirements.lock: fully hash-pinned tree (pip-compile --generate-hashes).
  requirements.txt stays the human-edited input; CI installs the lock with
  `pip install --require-hashes` for reproducible builds.
- CI: test job installs from the lock; pip-audit is now BLOCKING against the
  locked tree (currently 0 known CVEs); new SBOM job emits a CycloneDX
  artifact (argus-sbom.cdx.json) via cyclonedx-bom (SHA-pinned upload-artifact).
- Verified locally: hashed install + 81 tests pass in a clean venv;
  pip-audit --strict clean; SBOM = CycloneDX 1.6, 43 components.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PH7w1wBoUxFESq9gh6yjAQ
@sourcery-ai

sourcery-ai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces a hash-pinned dependency lockfile and updates CI to install from it, makes pip-audit a blocking gate against the locked tree, adds a CycloneDX SBOM generation workflow, and documents the new process in NEXT_STEPS and requirements.txt.

Flow diagram for the new dependency locking and CI audit/SBOM process

flowchart TD
  dev[Developer edits requirements.txt]
  lock[Run pip-compile --generate-hashes to create requirements.lock]
  ci_test[CI test job installs with pip install --require-hashes -r requirements.lock]
  ci_deps[CI deps job runs pip-audit -r requirements.lock --strict]
  gate{pip-audit passes?}
  ci_sbom[CI sbom job runs cyclonedx-py requirements requirements.lock]
  artifact[Upload argus-sbom.cdx.json as artifact]

  dev --> lock --> requirements_lock[requirements.lock]
  requirements_lock --> ci_test
  requirements_lock --> ci_deps
  ci_deps --> gate
  gate -->|yes| ci_sbom
  gate -->|no| fail["Fail pipeline (blocking deps job)"]
  ci_sbom --> artifact
Loading

File-Level Changes

Change Details Files
Adopt a hash-pinned dependency lockfile and wire CI to use it for reproducible builds.
  • Add aegis/requirements.lock as a fully hash-pinned dependency tree generated via pip-compile --generate-hashes.
  • Switch CI test job to cache based on requirements.lock instead of requirements.txt.
  • Update CI dependency installation to use pip install --require-hashes -r requirements.lock.
  • Document in requirements.txt that it is the human-edited source and how to regenerate requirements.lock.
aegis/requirements.lock
.github/workflows/ci.yml
aegis/requirements.txt
Make pip-audit a blocking dependency audit against the locked tree.
  • Change pip-audit job name from informational to blocking and remove continue-on-error so failures fail the job.
  • Run pip-audit against requirements.lock instead of requirements.txt.
  • Enable strict mode and descriptions via --strict --desc for the audit command.
  • Add inline guidance on how to triage CVEs by updating requirements.txt and regenerating requirements.lock.
.github/workflows/ci.yml
Add a CycloneDX SBOM generation job that produces and uploads an SBOM artifact from the lockfile.
  • Introduce a new sbom job in CI that checks out the repo and sets up Python 3.12.
  • Install cyclonedx-bom==7.3.0 and generate a CycloneDX SBOM from requirements.lock as argus-sbom.cdx.json.
  • Upload the generated SBOM using a SHA-pinned actions/upload-artifact version with a stable artifact name and path.
.github/workflows/ci.yml
Update project documentation to reflect completed dependency pinning and SBOM work and the new lockfile workflow.
  • Mark the dependency pinning + SBOM task as complete in NEXT_STEPS.md and change the section status icon to ✅.
  • Describe the new split between human-edited requirements.txt and generated requirements.lock, including the exact pip-compile command to regenerate the lockfile.
  • Note that CI now emits a CycloneDX SBOM and that pip-audit is blocking against the locked tree with currently 0 known CVEs.
aegis/docs/NEXT_STEPS.md
aegis/requirements.txt

Assessment against linked issues

Issue Objective Addressed Explanation
#3 Introduce a fully hash-pinned Python dependency lockfile and have CI install dependencies from this lockfile with hash verification instead of from the ranged requirements.txt.
#3 Make the pip-audit dependency audit CI job blocking (not informational) and run it against the locked dependency tree.
#3 Emit a software bill of materials (SBOM) as a CI artifact based on the locked dependency tree.

Possibly linked issues

  • #P0.3: PR adds hash-pinned requirements.lock, CycloneDX SBOM job, and changes pip-audit from informational to blocking.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gesh75
gesh75 marked this pull request as ready for review June 28, 2026 20:22
@gesh75
gesh75 merged commit 7040540 into main Jun 28, 2026
6 checks passed

@sourcery-ai sourcery-ai Bot 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.

Hey - I've found 2 issues, and left some high level feedback:

  • In the SBOM job, cyclonedx-py writes argus-sbom.cdx.json to the default working directory, but the upload step points to aegis/argus-sbom.cdx.json; align the output location or the artifact path so the file is actually found.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the SBOM job, `cyclonedx-py` writes `argus-sbom.cdx.json` to the default working directory, but the upload step points to `aegis/argus-sbom.cdx.json`; align the output location or the artifact path so the file is actually found.

## Individual Comments

### Comment 1
<location path=".github/workflows/ci.yml" line_range="28-32" />
<code_context>
           cache: pip
-          cache-dependency-path: aegis/requirements.txt
-      - name: Install deps
+          cache-dependency-path: aegis/requirements.lock
+      - name: Install deps (hash-pinned)
         run: |
           python -m pip install --upgrade pip
-          pip install -r requirements.txt
+          pip install --require-hashes -r requirements.lock
       - name: Run test suite
         run: python -m pytest -q
</code_context>
<issue_to_address>
**issue (bug_risk):** Lockfile path usage is inconsistent between cache configuration and install command.

`cache-dependency-path` references `aegis/requirements.lock`, while the install and SBOM steps use `requirements.lock` without the `aegis/` prefix. If the file is under `aegis/`, those commands will fail; if it’s at the repo root, the cache path is incorrect. Please pick a single location for the lockfile and update all references to match.
</issue_to_address>

### Comment 2
<location path=".github/workflows/ci.yml" line_range="77-81" />
<code_context>
+        run: |
+          pip install cyclonedx-bom==7.3.0
+          cyclonedx-py requirements requirements.lock -o argus-sbom.cdx.json
+      - name: Upload SBOM artifact
+        uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+        with:
+          name: argus-sbom
+          path: aegis/argus-sbom.cdx.json

   secrets:
</code_context>
<issue_to_address>
**issue (bug_risk):** SBOM output path and uploaded artifact path appear to be mismatched.

The SBOM is written as `argus-sbom.cdx.json` in the current directory, but the upload step looks for `aegis/argus-sbom.cdx.json`. Unless the job changes directories, the upload will fail due to a missing file. Please align the output and upload paths (either write to `aegis/argus-sbom.cdx.json` or adjust the upload path).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread .github/workflows/ci.yml
Comment on lines +28 to +32
cache-dependency-path: aegis/requirements.lock
- name: Install deps (hash-pinned)
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install --require-hashes -r requirements.lock

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Lockfile path usage is inconsistent between cache configuration and install command.

cache-dependency-path references aegis/requirements.lock, while the install and SBOM steps use requirements.lock without the aegis/ prefix. If the file is under aegis/, those commands will fail; if it’s at the repo root, the cache path is incorrect. Please pick a single location for the lockfile and update all references to match.

Comment thread .github/workflows/ci.yml
Comment on lines +77 to +81
- name: Upload SBOM artifact
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: argus-sbom
path: aegis/argus-sbom.cdx.json

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): SBOM output path and uploaded artifact path appear to be mismatched.

The SBOM is written as argus-sbom.cdx.json in the current directory, but the upload step looks for aegis/argus-sbom.cdx.json. Unless the job changes directories, the upload will fail due to a missing file. Please align the output and upload paths (either write to aegis/argus-sbom.cdx.json or adjust the upload path).

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.

P0.3 — Pin dependencies (hashes) + SBOM, then make pip-audit blocking

2 participants