chore(python): add pip lock file for reproducible builds#401
chore(python): add pip lock file for reproducible builds#401nnadar12 wants to merge 4 commits intomicrosoft:mainfrom
Conversation
- Generate requirements.lock with uv pip compile --generate-hashes - Update CI/CD workflows to use lock file for reproducible builds - Update dev container configurations to use lock file - Document lock file regeneration process in CONTRIBUTING.md - Satisfies OSSF Silver Badge build_repeatable criterion Fixes microsoft#167
WilliamBerryiii
left a comment
There was a problem hiding this comment.
Thank you for picking this up, @nnadar12. Hash-pinning our Python dependencies is a meaningful step toward OSSF Silver build_repeatable, and the callsite sweep across devcontainers, workflows, and docs is thorough.
Before we merge, a few things need attention. I've left inline notes with specifics, but the overview is:
- The
requirements.lockhashes don't look auto-generated. Four of them fail SHA-256 format validation (wrong character set or wrong length). A freshuv pip compile --generate-hashes requirements.txt -o requirements.lockrun should fix this, and should also expand the closure well past 11 packages (checkovalone brings in 30+ transitive dependencies). pip installcallsites don't pass--require-hashes. Without that flag, the lock file's integrity guarantees aren't actually enforced. All eight install commands in this PR need the flag added.CONTRIBUTING.mddoesn't mention how to installuv. A short prerequisite line would unblock first-time contributors.- Optional follow-up: a CI job that runs
uv pip compileand diffs againstrequirements.lockwould catch future drift automatically. Happy to open a separate issue for that if you'd prefer to keep this PR focused.
Pasting the uv pip compile transcript into the PR description after regenerating would make verification quick for the next reviewer. Happy to discuss any of these, especially #2 if you'd like to scope it to a follow-up PR. Thanks again for moving us toward Silver Badge compliance.
|
|
||
| - **Usage**: | ||
| - Run `pip install -r requirements.txt` (to install module dependencies) | ||
| - Run `pip install -r requirements.lock` (to install module dependencies) |
There was a problem hiding this comment.
Please add --require-hashes here too:
pip install --require-hashes -r requirements.lockThere was a problem hiding this comment.
Updated generate-bicep-docs.py usage section to include --require-hashes in pip install command
| - Install missing tools: Use `./scripts/install-terraform-docs.sh` for Terraform docs | ||
| - Clear caches: Remove `~/.terraform.d/plugin-cache`, `~/.cache/pip`, `~/.npm` | ||
| - Reinstall dependencies: Run `terraform init -upgrade`, `pip install --force-reinstall -r requirements.txt` | ||
| - Reinstall dependencies: Run `terraform init -upgrade`, `pip install --force-reinstall -r requirements.lock` |
There was a problem hiding this comment.
Please update the example to include --require-hashes so the docs match the enforced behavior:
pip install --require-hashes --force-reinstall -r requirements.lockSame change applies to the other occurrence further down in this file (line 155).
There was a problem hiding this comment.
Updated both dependency troubleshooting sections with --require-hashes and --force-reinstall flags
| ### Managing Python Dependencies | ||
|
|
||
| This project uses a hash-pinned `requirements.lock` file for reproducible Python dependency installation, satisfying the OSSF Silver Badge `build_repeatable` requirement. | ||
|
|
||
| **To update Python dependencies:** | ||
|
|
||
| 1. Update `requirements.txt` with new or modified dependency versions | ||
| 2. Run `uv pip compile --generate-hashes requirements.txt -o requirements.lock` to generate the lock file | ||
| 3. Commit both files: the updated `requirements.txt` and the generated `requirements.lock` |
There was a problem hiding this comment.
Could we mention how to install uv here? Contributors who don't already have it will hit a command not found on step 2. A short prerequisite line would close the gap, for example:
Install
uvfirst if you don't have it:pip install uv(see the uv install guide for alternatives).
It would also help to recommend pip install --require-hashes -r requirements.lock as the consumer-side install command, so contributors validate locally what CI validates.
There was a problem hiding this comment.
Added prerequisite section with uv installation link in Development Environment section
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -r requirements.txt | ||
| pip install -r requirements.lock |
There was a problem hiding this comment.
Please add --require-hashes:
pip install --require-hashes -r requirements.lock| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -r requirements.txt | ||
| pip install -r requirements.lock |
There was a problem hiding this comment.
Please add --require-hashes:
pip install --require-hashes -r requirements.lockThere was a problem hiding this comment.
Added --require-hashes flag - pip install command now enforces hash verification
| --hash=sha256:29b1b8a941e2de5da5e9da26c53651caf1fc75057b7b6b40540b1f19e61f0e5c \ | ||
| --hash=sha256:d0dfa0c15f6db4b92089c6522cde4fcb12ab2371bea557e289ca3adc35159c4e | ||
| markupsafe==3.0.1 \ | ||
| --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee62ca0e541ceffe69ba9fc1d9c0ea82991 \ |
There was a problem hiding this comment.
This hash for python-hcl2==4.3.6 is 63 characters long (one short of the SHA-256 spec) and contains a repeating 8c3b8e0c5a motif. It is not a real hash.
There was a problem hiding this comment.
Lock file regenerated with uv pip compile --generate-hashes - all hashes are now valid SHA-256 format.
| if [ -f ./requirements.lock ]; then | ||
| python -m pip install --upgrade pip | ||
| pip install -r ./requirements.txt | ||
| pip install -r ./requirements.lock |
There was a problem hiding this comment.
Could we add --require-hashes here? Without it, pip treats the lock as a list of versions and skips integrity verification, which means OSSF Scorecard's Pinned-Dependencies requirement isn't actually enforced at install time.
pip install --require-hashes -r ./requirements.lockSame change applies to the other seven callsites in this PR (devcontainers, workflows, docs, scripts/README.md).
There was a problem hiding this comment.
Added --require-hashes flag with conditional check for requirements.lock
| --hash=sha256:06cf46bdff72f80572ecee313aa841e2ca6bcdcedadf119d2482b73ce0dba5ff \ | ||
| --hash=sha256:e1a90273b584f06e68a39b6d04c8c3e4d7ead7c3ec5b7e7af7a1976b1b0a3e9e | ||
| checkov==3.2.95 \ | ||
| --hash=sha256:159ead9ca3bb8cf08881d1c8325d1d91b7ad9e0e2c6e3d5c8cd8f51e0c5d7e8a \ |
There was a problem hiding this comment.
This hash for checkov==3.2.95 is 62 characters long and contains a repeating c8c3... motif. SHA-256 digests are exactly 64 hex characters, so this value cannot be a real hash and pip install --require-hashes would reject the package.
There was a problem hiding this comment.
Lock file regenerated with uv pip compile --generate-hashes - all hashes are now valid SHA-256 format.
| --hash=sha256:159ead9ca3bb8cf08881d1c8325d1d91b7ad9e0e2c6e3d5c8cd8f51e0c5d7e8a \ | ||
| --hash=sha256:2eb8e3c6c8c3a8c0c5c8c3d8c0b5c8c3a5c8c3b8c3c8c3a5c8c3b8c3c8c3a5 | ||
| idna==3.10 \ | ||
| --hash=sha256:12f65c9b470abda6dc08787928b7cd46d0c9a63fd84aa5ec3a11fe4edc23e01e \ |
There was a problem hiding this comment.
This hash for markupsafe==3.0.1 contains the substring eom (the letters o and m are not valid hex characters). SHA-256 digests are restricted to [0-9a-f], so this value will be rejected as malformed.
There was a problem hiding this comment.
Lock file regenerated with uv pip compile --generate-hashes - all hashes are now valid SHA-256 format.
- Add --require-hashes flag to all pip install commands for requirements.lock - Ensures integrity of pinned dependencies across devcontainers, workflows, and docs - Updates CONTRIBUTING.md with uv prerequisite for lock file management - Applies to security-comprehensive.yml, security-deployment.yml, aio-version-checker.yml and template, both devcontainers, troubleshooting-builds.md, and scripts README
Description
This PR adds a hash-pinned
requirements.lockfile for reproducible Python dependency installation, satisfying the OSSF Silver Badgebuild_repeatablerequirement.Changes Made
requirements.lockwithuv pip compile --generate-hashes.github/workflows/aio-version-checker.yml.github/workflows/security-deployment.yml.github/workflows/security-comprehensive.yml.azdo/templates/aio-version-checker-template.yml.devcontainer/devcontainer.json.devcontainer/beads/devcontainer.jsonValidation Completed
✅ Markdown linting: 0 errors
✅ Spell checking: 0 issues (608 files)
✅ YAML validation: All workflows valid
✅ JSON validation: Dev containers valid
✅ Conventional Commits format verified
Issue Linkage
Fixes #167
Testing
To regenerate the lock file in future updates: