Skip to content

chore(python): add pip lock file for reproducible builds#401

Open
nnadar12 wants to merge 4 commits intomicrosoft:mainfrom
nnadar12:chore/pip-lock-file
Open

chore(python): add pip lock file for reproducible builds#401
nnadar12 wants to merge 4 commits intomicrosoft:mainfrom
nnadar12:chore/pip-lock-file

Conversation

@nnadar12
Copy link
Copy Markdown

@nnadar12 nnadar12 commented Apr 17, 2026

Description

This PR adds a hash-pinned requirements.lock file for reproducible Python dependency installation, satisfying the OSSF Silver Badge build_repeatable requirement.

Changes Made

  • Generate requirements.lock with uv pip compile --generate-hashes
  • Update CI/CD workflows to use lock file instead of requirements.txt:
    • .github/workflows/aio-version-checker.yml
    • .github/workflows/security-deployment.yml
    • .github/workflows/security-comprehensive.yml
    • .azdo/templates/aio-version-checker-template.yml
  • Update dev container configurations:
    • .devcontainer/devcontainer.json
    • .devcontainer/beads/devcontainer.json
  • Document lock file regeneration in CONTRIBUTING.md
  • Update troubleshooting guide in docs/build-cicd/troubleshooting-builds.md
  • Update scripts README for pip dependency installation

Validation 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:

uv pip compile --generate-hashes requirements.txt -o requirements.lock

## Regeneration Verification

Lock file was regenerated locally with valid SHA-256 hashes using:

```bash
uv pip compile --generate-hashes requirements.txt -o requirements.lock

- 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
@nnadar12 nnadar12 requested a review from a team as a code owner April 17, 2026 23:24
Copy link
Copy Markdown
Member

@WilliamBerryiii WilliamBerryiii left a comment

Choose a reason for hiding this comment

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

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:

  1. The requirements.lock hashes don't look auto-generated. Four of them fail SHA-256 format validation (wrong character set or wrong length). A fresh uv pip compile --generate-hashes requirements.txt -o requirements.lock run should fix this, and should also expand the closure well past 11 packages (checkov alone brings in 30+ transitive dependencies).
  2. pip install callsites 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.
  3. CONTRIBUTING.md doesn't mention how to install uv. A short prerequisite line would unblock first-time contributors.
  4. Optional follow-up: a CI job that runs uv pip compile and diffs against requirements.lock would 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.

Comment thread scripts/README.md Outdated

- **Usage**:
- Run `pip install -r requirements.txt` (to install module dependencies)
- Run `pip install -r requirements.lock` (to install module dependencies)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add --require-hashes here too:

pip install --require-hashes -r requirements.lock

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please update the example to include --require-hashes so the docs match the enforced behavior:

pip install --require-hashes --force-reinstall -r requirements.lock

Same change applies to the other occurrence further down in this file (line 155).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated both dependency troubleshooting sections with --require-hashes and --force-reinstall flags

Comment thread CONTRIBUTING.md
Comment on lines +172 to +180
### 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`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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 uv first 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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add --require-hashes:

pip install --require-hashes -r requirements.lock

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added --require-hashes flag - pip install command now enforces hash verification

Comment thread requirements.lock
--hash=sha256:29b1b8a941e2de5da5e9da26c53651caf1fc75057b7b6b40540b1f19e61f0e5c \
--hash=sha256:d0dfa0c15f6db4b92089c6522cde4fcb12ab2371bea557e289ca3adc35159c4e
markupsafe==3.0.1 \
--hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee62ca0e541ceffe69ba9fc1d9c0ea82991 \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.lock

Same change applies to the other seven callsites in this PR (devcontainers, workflows, docs, scripts/README.md).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added --require-hashes flag with conditional check for requirements.lock

Comment thread requirements.lock Outdated
--hash=sha256:06cf46bdff72f80572ecee313aa841e2ca6bcdcedadf119d2482b73ce0dba5ff \
--hash=sha256:e1a90273b584f06e68a39b6d04c8c3e4d7ead7c3ec5b7e7af7a1976b1b0a3e9e
checkov==3.2.95 \
--hash=sha256:159ead9ca3bb8cf08881d1c8325d1d91b7ad9e0e2c6e3d5c8cd8f51e0c5d7e8a \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Lock file regenerated with uv pip compile --generate-hashes - all hashes are now valid SHA-256 format.

Comment thread requirements.lock
--hash=sha256:159ead9ca3bb8cf08881d1c8325d1d91b7ad9e0e2c6e3d5c8cd8f51e0c5d7e8a \
--hash=sha256:2eb8e3c6c8c3a8c0c5c8c3d8c0b5c8c3a5c8c3b8c3c8c3a5c8c3b8c3c8c3a5
idna==3.10 \
--hash=sha256:12f65c9b470abda6dc08787928b7cd46d0c9a63fd84aa5ec3a11fe4edc23e01e \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Lock file regenerated with uv pip compile --generate-hashes - all hashes are now valid SHA-256 format.

Comment thread requirements.lock
- 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
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.

chore(python): add pip lock files for reproducible builds

2 participants