Create a requirement.in file listing the dependencies, use pip compile --generate-hashes to created a version with hashes, and configure the build to prefetch the dependencies.
Agent-Generated Plan
Plan: Switch ldap-server build to hermetic mode
Design
The reviewer's feedback identifies a fundamental problem with the prior plan: using fedora-minimal as the base image requires microdnf to install python3 and python3-pip, which itself would need network access during the hermetic build. Locking RPM dependencies in addition to Python packages would be disproportionate complexity for a test-only image.
Chosen approach: switch the base image from registry.fedoraproject.org/fedora-minimal:44 to an official Python image. A Python base image already contains the interpreter and pip, so microdnf is no longer needed, removing the RPM prefetch requirement entirely. Only the pip dependencies (ldaptor and its transitive dependencies) need to be locked.
Affected Files
| File |
Change |
integration-tests/images/ldap-server/requirements.in |
Create — lists direct pip dependencies |
integration-tests/images/ldap-server/requirements.txt |
Create — pip-compiled lock file with hashes |
integration-tests/images/ldap-server/Containerfile |
Modify — switch base image; install from requirements.txt |
.tekton/ldap-server-pull-request.yaml |
Modify — enable hermetic mode and set prefetch-input |
.tekton/ldap-server-push.yaml |
Modify — enable hermetic mode and set prefetch-input |
Implementation Steps
1. Create requirements.in
Create integration-tests/images/ldap-server/requirements.in with the two direct runtime dependencies:
2. Generate requirements.txt with hashes
Install pip-tools locally and run:
pip-compile --generate-hashes \
--output-file integration-tests/images/ldap-server/requirements.txt \
integration-tests/images/ldap-server/requirements.in
The resulting requirements.txt pins all transitive dependencies (e.g., automat, constantly, hyperlink, incremental, zope.interface) with cryptographic hashes. Both files are committed to the repository.
The requirements.txt is a static file that must be regenerated manually whenever requirements.in changes (or periodically to pick up security fixes). No CI automation is required by this issue.
3. Update the Containerfile
Replace the fedora-minimal base image with an official python image and install dependencies from the lock file:
FROM python:3.12-slim
RUN pip install --no-cache-dir --require-hashes -r /tmp/requirements.txt
COPY requirements.txt /tmp/requirements.txt
COPY server.py /app/server.py
EXPOSE 1389
USER 1001
CMD ["python3", "/app/server.py"]
Note on image choice: python:3.12-slim (Debian-slim) contains only pip and the interpreter — no additional system package manager calls are needed. The Cachi2 pip prefetch handles everything. If a UBI-based Python image is required for organizational policy reasons (e.g., registry.access.redhat.com/ubi9/python-312), that image already includes pip as well. The implementer should confirm the preferred base image. The plan uses python:3.12-slim as the default; switching to a UBI variant is a one-line change with no other consequences.
The COPY requirements.txt line must come before the RUN pip install line so the file is available at build time.
4. Enable hermetic mode in the Tekton pipelines
In both .tekton/ldap-server-pull-request.yaml and .tekton/ldap-server-push.yaml, set the pipeline-level params defaults so that hermetic mode is active without requiring a runtime override:
- name: hermetic
value: "true"
- name: prefetch-input
value: pip
These parameters are already threaded through to both the prefetch-dependencies task (via $(params.prefetch-input)) and the build-container task (via $(params.hermetic) and $(params.prefetch-input)). The prefetch-dependencies task in the ldap-server pipelines does not have a when guard (unlike the cts pipelines), so it will run unconditionally; setting prefetch-input to pip will instruct Cachi2 to prefetch PyPI packages. No structural change to the task ordering is needed.
The prefetch-input value pip tells Cachi2 to look for requirements.txt at the root of the build context (integration-tests/images/ldap-server/), which is where the file lives. No cachi2.yaml config file is required for this simple case.
Edge Cases and Constraints
- Transitive dependency churn:
ldaptor and twisted pull in several transitive packages. If the lock file is generated on a different platform or Python version than the build image, the hashes may not match. Generate requirements.txt using the same Python minor version as the base image (3.12) to avoid platform-specific wheel hash mismatches. Use --pip-args="--only-binary=:all:" if all dependencies have published wheels, or omit it if source distributions are acceptable.
USER 1001 compatibility: The official python:3.12-slim image does not pre-create user 1001. The CMD and EXPOSE statements do not require root, so the USER 1001 directive will still work (Kubernetes/OpenShift will run the process as UID 1001 even without a /etc/passwd entry). This is unchanged from the current Containerfile.
server.py location: The current Containerfile copies server.py to /app/server.py. The new Containerfile preserves this path.
Acceptance Criteria
integration-tests/images/ldap-server/requirements.in exists and contains ldaptor and twisted as the only entries.
integration-tests/images/ldap-server/requirements.txt exists and every package entry includes a --hash= annotation.
integration-tests/images/ldap-server/Containerfile does not contain a reference to fedora-minimal or microdnf.
integration-tests/images/ldap-server/Containerfile contains pip install using -r requirements.txt with --require-hashes.
- In
.tekton/ldap-server-pull-request.yaml, the top-level spec.params block contains hermetic: "true" and prefetch-input: pip.
- In
.tekton/ldap-server-push.yaml, the top-level spec.params block contains hermetic: "true" and prefetch-input: pip.
Create a requirement.in file listing the dependencies, use
pip compile --generate-hashesto created a version with hashes, and configure the build to prefetch the dependencies.Agent-Generated Plan
Plan: Switch ldap-server build to hermetic mode
Design
The reviewer's feedback identifies a fundamental problem with the prior plan: using
fedora-minimalas the base image requiresmicrodnfto installpython3andpython3-pip, which itself would need network access during the hermetic build. Locking RPM dependencies in addition to Python packages would be disproportionate complexity for a test-only image.Chosen approach: switch the base image from
registry.fedoraproject.org/fedora-minimal:44to an official Python image. A Python base image already contains the interpreter and pip, somicrodnfis no longer needed, removing the RPM prefetch requirement entirely. Only the pip dependencies (ldaptorand its transitive dependencies) need to be locked.Affected Files
integration-tests/images/ldap-server/requirements.inintegration-tests/images/ldap-server/requirements.txtintegration-tests/images/ldap-server/Containerfile.tekton/ldap-server-pull-request.yaml.tekton/ldap-server-push.yamlImplementation Steps
1. Create
requirements.inCreate
integration-tests/images/ldap-server/requirements.inwith the two direct runtime dependencies:2. Generate
requirements.txtwith hashesInstall
pip-toolslocally and run:pip-compile --generate-hashes \ --output-file integration-tests/images/ldap-server/requirements.txt \ integration-tests/images/ldap-server/requirements.inThe resulting
requirements.txtpins all transitive dependencies (e.g.,automat,constantly,hyperlink,incremental,zope.interface) with cryptographic hashes. Both files are committed to the repository.The
requirements.txtis a static file that must be regenerated manually wheneverrequirements.inchanges (or periodically to pick up security fixes). No CI automation is required by this issue.3. Update the
ContainerfileReplace the
fedora-minimalbase image with an officialpythonimage and install dependencies from the lock file:The
COPY requirements.txtline must come before theRUN pip installline so the file is available at build time.4. Enable hermetic mode in the Tekton pipelines
In both
.tekton/ldap-server-pull-request.yamland.tekton/ldap-server-push.yaml, set the pipeline-levelparamsdefaults so that hermetic mode is active without requiring a runtime override:These parameters are already threaded through to both the
prefetch-dependenciestask (via$(params.prefetch-input)) and thebuild-containertask (via$(params.hermetic)and$(params.prefetch-input)). Theprefetch-dependenciestask in the ldap-server pipelines does not have awhenguard (unlike the cts pipelines), so it will run unconditionally; settingprefetch-inputtopipwill instruct Cachi2 to prefetch PyPI packages. No structural change to the task ordering is needed.The
prefetch-inputvaluepiptells Cachi2 to look forrequirements.txtat the root of the build context (integration-tests/images/ldap-server/), which is where the file lives. Nocachi2.yamlconfig file is required for this simple case.Edge Cases and Constraints
ldaptorandtwistedpull in several transitive packages. If the lock file is generated on a different platform or Python version than the build image, the hashes may not match. Generaterequirements.txtusing the same Python minor version as the base image (3.12) to avoid platform-specific wheel hash mismatches. Use--pip-args="--only-binary=:all:"if all dependencies have published wheels, or omit it if source distributions are acceptable.USER 1001compatibility: The officialpython:3.12-slimimage does not pre-create user1001. TheCMDandEXPOSEstatements do not require root, so theUSER 1001directive will still work (Kubernetes/OpenShift will run the process as UID 1001 even without a/etc/passwdentry). This is unchanged from the current Containerfile.server.pylocation: The current Containerfile copiesserver.pyto/app/server.py. The new Containerfile preserves this path.Acceptance Criteria
integration-tests/images/ldap-server/requirements.inexists and containsldaptorandtwistedas the only entries.integration-tests/images/ldap-server/requirements.txtexists and every package entry includes a--hash=annotation.integration-tests/images/ldap-server/Containerfiledoes not contain a reference tofedora-minimalormicrodnf.integration-tests/images/ldap-server/Containerfilecontainspip installusing-r requirements.txtwith--require-hashes..tekton/ldap-server-pull-request.yaml, the top-levelspec.paramsblock containshermetic: "true"andprefetch-input: pip..tekton/ldap-server-push.yaml, the top-levelspec.paramsblock containshermetic: "true"andprefetch-input: pip.