Skip to content

ci: install CI dependencies from hash-pinned locks - #620

Merged
imran-siddique merged 2 commits into
mainfrom
ci/hash-pinned-pip
Sep 7, 2026
Merged

ci: install CI dependencies from hash-pinned locks#620
imran-siddique merged 2 commits into
mainfrom
ci/hash-pinned-pip

Conversation

@imran-siddique

Copy link
Copy Markdown
Member

Same pattern as agentrust-io/trace-registry#67, trace-tests#101, trace-spec#302 and agentrust-telemetry#50, all merged and green.

Four locks under requirements/, all installed with --require-hashes — all-or-nothing: pip refuses if any requirement, transitive included, lacks a hash.

Lock Covers
dev.txt [project.dependencies] plus the dev extra
docs.txt the docs toolchain
release.txt build + twine
agt.txt the governance scanner, in its own venv

Why agt.txt stays separate

AGT constrains cryptography below 49 while this runtime requires 50+. The scanner is installed into .agt-venv precisely so its resolution cannot touch the package under test. Pinning it does not change that isolation, and the lock confirms AGT 4.1.0 pulls no cryptography of its own.

The security scan now scans pinned versions

pip install bandit pip-audit fetched whatever was current at scan time. Both are already in the dev extra, so the step now uses the same pinned versions as the rest of the job. A security scan whose own tooling floats is a scan you cannot reproduce.

Deliberately not pinned

release.yml installs "$artifact" — the wheel or sdist the job has just built. Pinning that would defeat the smoke test it exists to perform.

The --upgrade pip setuptools prefixes are dropped rather than pinned; upgrading to whatever is current is the same unpinned fetch this change removes.

Verification

Clean venv: 1651 passed, 16 skipped, no failures.

That is a fully green suite where my local .venv gives four failures, because the lock resolves the versions pyproject.toml actually asks for rather than whatever drifted in. Same effect the new conftest guard is designed to make visible.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XbDBXDWWvMFa7c2jGgyq9t

Same pattern as trace-registry, trace-tests, trace-spec and
agentrust-telemetry.

Four locks under requirements/, all installed with --require-hashes,
which is all-or-nothing: pip refuses if any requirement, transitive
included, lacks a hash.

  dev.txt      [project.dependencies] plus the dev extra
  docs.txt     the docs toolchain
  release.txt  build + twine for the release path
  agt.txt      the governance scanner, in its own venv

agt.txt stays separate on purpose. AGT constrains cryptography below 49
while the runtime requires 50+, so the scanner is installed into
.agt-venv precisely so its resolution cannot touch the package under
test. Pinning it does not change that isolation.

The security-scan step no longer installs bandit and pip-audit. Both are
already in the dev extra, so it now scans with the same pinned versions
the rest of the job uses rather than fetching whatever is current at scan
time, which is the behaviour a security scan should have.

The "--upgrade pip setuptools" prefixes are dropped rather than pinned:
upgrading to whatever is current is the same unpinned fetch this change
removes.

One install is deliberately left alone. release.yml installs "$artifact",
the wheel or sdist the job has just built, and pinning that would defeat
the smoke test it exists to perform.

Verified in a clean venv: 1651 passed, 16 skipped, no failures. Worth
noting that is a fully green suite where the stale local .venv gives
four, because the lock resolves the versions pyproject actually asks for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbDBXDWWvMFa7c2jGgyq9t
@imran-siddique
imran-siddique requested a review from a team as a code owner September 7, 2026 00:49
Two things CI caught that a local run could not.

pip-audit failed on setuptools 79.0.1 (PYSEC-2026-3447, fixed in 83.0.0).
That is a consequence of this branch dropping the old
"pip install --upgrade pip setuptools" prefix: without it the runner
image keeps whatever setuptools it shipped with. Pinning it in the lock
is the answer that satisfies both goals, a fixed version and a hashed
one, rather than going back to an unpinned upgrade.

docs-check previously installed "-r requirements-docs.txt -e ." in one
command, so the plain editable install pulled the runtime dependencies
in. With --no-deps it no longer does, and the job import-failed on httpx.
It now installs the dev lock as well.

Verified in a clean venv: pip-audit reports no known vulnerabilities.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbDBXDWWvMFa7c2jGgyq9t
@imran-siddique
imran-siddique merged commit 5b63642 into main Sep 7, 2026
13 checks passed
@imran-siddique
imran-siddique deleted the ci/hash-pinned-pip branch September 7, 2026 00:57
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.

1 participant