Skip to content

packages: wolfi import batch 3 — python (requests + 27 more, from-source)#369

Open
bryan-minimal wants to merge 2 commits into
mainfrom
add-wolfi-imports-batch3-python
Open

packages: wolfi import batch 3 — python (requests + 27 more, from-source)#369
bryan-minimal wants to merge 2 commits into
mainfrom
add-wolfi-imports-batch3-python

Conversation

@bryan-minimal

@bryan-minimal bryan-minimal commented Jul 8, 2026

Copy link
Copy Markdown
Member

Third batch from pkgmgr import-wolfi — the python ecosystem. Where batches 1–2 were C-family and go/rust single binaries, python is a different shape (site-packages payloads, PEP-517 backends, console-script entry points, dependency fan-in), so this batch both adds the packages and builds out the importer's python support.

The headline: requests builds from source in Minimal with its whole dependency tree resolved and imported by the tool.

What's here (28 packages, all build + pass every minimal check at 0 TODOs)

  • Foundational / apps: requests, jinja2, pygments, distro, click, boltons, pyyaml, markupsafe, python-dateutil, six, wrapt, more-itertools, itsdangerous, blinker, mdurl
  • The requests tree: urllib3, certifi, charset-normalizer, idna
  • The PEP-517 backend bootstrap (needed so hatchling/scm-backed packages build at all): setuptools-scm, pluggy, trove-classifiers, hatchling, hatch-vcs, pathspec, editables, calver, typing-extensions

How they're produced

  • build.sh = pip3 wheel --no-build-isolation + pip3 install --root $OUTPUT_DIR (Minimal's pyproject-hooks/meson convention).
  • backend read authoritatively from the source's pyproject.toml [build-system] (recipes list several; only the source says which is real), mapped to a Minimal package in build_deps.
  • outputs = the real top-level site-packages entries read from the built artifact (the import name often differs from the distribution name — PyYAML → yaml, python-dateutil → dateutil), plus any console-script usr/bin entry points.
  • runtime_deps = python + the package's actual pypi deps, mapped to their Minimal packages (jinja2 → markupsafe; requests → urllib3/certifi/charset-normalizer/idna).
  • Sources mirrored to gs://minimal-staging-archives/<owner>/<repo>/<tag>.tar.gz.

Reviewer notes (surfaced, not hidden)

  • Backend bootstrap: Minimal previously had setuptools/flit-core but not hatchling/setuptools-scm, which blocked a large slice of modern python. Those are self-hosting python packages; this batch bootstraps them (setuptools-scm builds with plain setuptools; hatchling builds from its own backend/ source). They're build-time backends — in build_deps, not runtime.
  • C extensions (markupsafe, pyyaml, wrapt) build native code via toolchain + Python.h and mark the site-packages .so allow_executable (cf. numpy).
  • setuptools-scm / hatch-vcs packages get SETUPTOOLS_SCM_PRETEND_VERSION (a github archive has no .git).
  • Deferred: attrs (needs the hatch-fancy-pypi-readme plugin — a further bootstrap step). urllib3 pulls the hatch-vcs plugin, which is included.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added packaging support for several Python libraries, including requests, Jinja2, click, urllib3, certifi, PyYAML, Pygments, and others.
    • These packages can now be built and installed through a consistent workflow.
  • Tests

    • Added smoke tests for selected packages to help verify command-line behavior after installation.

Third batch from `pkgmgr import-wolfi` — the python ecosystem. requests builds
from source in Minimal with its full dependency tree; the PEP-517 backends
(hatchling, setuptools-scm, …) are bootstrapped so hatchling-backed packages
build at all.

  apps/libs:  requests jinja2 pygments distro click boltons pyyaml markupsafe
              python-dateutil six wrapt more-itertools itsdangerous blinker mdurl
  requests tree: urllib3 certifi charset-normalizer idna
  backend bootstrap: setuptools-scm pluggy trove-classifiers hatchling hatch-vcs
              pathspec editables calver typing-extensions

build.sh = pip3 wheel --no-build-isolation + pip3 install --root; backend read
from the source pyproject.toml; outputs + runtime_deps from the built artifact.
Each builds clean and passes every `minimal check` at 0 TODOs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 57 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0dde14ec-2193-4645-8cf7-d324899f1828

📥 Commits

Reviewing files that changed from the base of the PR and between bac1839 and 3423431.

📒 Files selected for processing (9)
  • packages/itsdangerous/build.ncl
  • packages/jinja2/build.ncl
  • packages/markupsafe/build.sh
  • packages/mdurl/build.ncl
  • packages/pluggy/build.ncl
  • packages/pluggy/build.sh
  • packages/trove-classifiers/build.ncl
  • packages/trove-classifiers/build.sh
  • packages/wrapt/build.ncl
📝 Walkthrough

Walkthrough

This PR adds new build.ncl and build.sh definitions for roughly 35 Python packages (build tooling, general-purpose libraries, and HTTP-stack packages), each wiring source fetch, build command, output globs, runtime deps, and license/provenance metadata. It also updates the certifi patch to use Alpine's system CA bundle.

Changes

New package build specs

Layer / File(s) Summary
Build backend/tooling packages
packages/hatchling/build.ncl, packages/hatchling/build.sh, packages/hatch-vcs/build.ncl, packages/hatch-vcs/build.sh, packages/setuptools-scm/build.ncl, packages/setuptools-scm/build.sh, packages/pluggy/build.ncl, packages/pluggy/build.sh, packages/pathspec/build.ncl, packages/pathspec/build.sh, packages/trove-classifiers/build.ncl, packages/trove-classifiers/build.sh
New build.ncl/build.sh pairs pin upstream versions, fetch/verify source tarballs, build wheels via pip3, install into $OUTPUT_DIR, declare output globs and runtime deps, and set license/provenance attrs; some include smoke tests.
Core utility/runtime libraries
packages/blinker/..., packages/boltons/..., packages/calver/..., packages/click/..., packages/distro/..., packages/editables/..., packages/idna/..., packages/itsdangerous/..., packages/jinja2/..., packages/markupsafe/..., packages/mdurl/..., packages/more-itertools/..., packages/six/..., packages/typing-extensions/..., packages/wrapt/..., packages/python-dateutil/..., packages/pyyaml/..., packages/pygments/...
Each package adds build.ncl (source fetch, build command, outputs, runtime deps, attrs) and build.sh (pip3 wheel build then offline pip3 install into $OUTPUT_DIR).
HTTP stack packages and certifi patch
packages/charset-normalizer/..., packages/urllib3/..., packages/certifi/..., packages/requests/...
New build.ncl/build.sh specs for these networking-related packages; certifi's use-alpine-system-certs.patch is updated to add ALPINE_CA_CERTS_PATH and route contents()/_CACERT_PATH to Alpine's system CA bundle instead of the vendored cacert.pem.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: msample

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is specific and accurately summarizes the main change: a third Wolfi import batch for Python packages built from source.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-wolfi-imports-batch3-python

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (3)
packages/blinker/build.ncl (2)

22-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align outputs with the specific site-packages/dist-info glob pattern used by sibling packages.

pathspec and trove-classifiers split outputs into python_site_package and python_dist_info OutputData entries; this file instead uses a single catch-all usr/** glob. Not incorrect, but inconsistent with the established pattern for this batch.

♻️ Suggested alignment
   outputs = {
-    everything = { glob = "usr/**", allow_executable = true } | OutputData,
+    python_site_package = { glob = "usr/lib/python*/site-packages/blinker/**" } | OutputData,
+    python_dist_info = { glob = "usr/lib/python*/site-packages/blinker-*.dist-info/**" } | OutputData,
   },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/blinker/build.ncl` around lines 22 - 24, The outputs for the blinker
package are using a broad catch-all glob instead of the same split pattern used
by sibling builds. Update the outputs definition in the build config to match
the established approach from pathspec and trove-classifiers by separating
site-packages and dist-info into distinct OutputData entries, and adjust the
glob(s) accordingly while keeping the same build symbols and structure.

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Resolve the outstanding reviewer TODO before merge.

Per the PR's own claim of "0 TODOs" across this batch, this comment should be resolved. Web search confirms blinker 1.9.0 has no install_requires beyond Python >=3.9, so runtime_deps = [python] is correct — the TODO can be cleared for that part.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/blinker/build.ncl` around lines 1 - 2, The build manifest still
contains an unresolved reviewer TODO in the imported blinker package metadata.
Update the blinker build definition to clear the TODO now that the runtime
dependency check is confirmed, and make sure the package entry reflects the
resolved state without leaving the reviewer note in the file. Refer to the
blinker package definition in build.ncl and remove or replace the TODO so the
batch is consistent with the “0 TODOs” claim.
packages/wrapt/build.ncl (1)

10-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Narrow the wrapt output glob outputs.everything = { glob = "usr/**", allow_executable = true } is broader than needed here; wrapt installs into site-packages/wrapt/** plus wrapt-*.dist-info/**, so a package-specific output would avoid collecting unrelated files. toolchain isn’t needed because the package already falls back to pure Python when a compiler isn’t available.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/wrapt/build.ncl` around lines 10 - 24, The wrapt package output glob
is too broad and should be narrowed to the package’s actual install paths.
Update the outputs definition in build.ncl so the artifact only collects wrapt
under site-packages and the corresponding wrapt-*.dist-info metadata instead of
all usr/** files, using the existing build_deps/cmd setup and the wrapt package
name to locate the relevant output. Also remove the unnecessary toolchain
dependency since wrapt already falls back to pure Python when no compiler is
available.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/certifi/build.ncl`:
- Around line 10-20: The certifi build configuration is missing the
use-alpine-system-certs.patch dependency, so the package still uses its vendored
CA bundle instead of Alpine’s system certificates. Update build_deps in
build.ncl to include the patch alongside the existing Local and Source entries,
using the build.sh flow and certifi package symbols so the patch is applied
during the build.

In `@packages/itsdangerous/build.ncl`:
- Line 2: Remove the lingering TODO in build.ncl and replace the broad
everything output with precise package globs, matching the patterns used by
sibling package configs such as idna and urllib3. Update the package definition
symbols in build.ncl so the declared outputs explicitly target the Python
site-packages and .dist-info artifacts, and ensure the pypi runtime
dependencies/install_requires are verified as part of the same cleanup.

In `@packages/jinja2/build.ncl`:
- Line 2: Remove the unresolved TODO in build.ncl and replace the broad usr/**
output with precise package outputs consistent with sibling packages like idna
and urllib3. Update the package definition symbols around install_requires and
outputs so the runtime deps are verified and the exported artifacts use
python_site_package and python_dist_info globs instead of the catch-all
everything glob.

In `@packages/markupsafe/build.sh`:
- Around line 1-5: The build script for MarkupSafe’s C extension is missing the
required reproducibility settings. Update the build steps in build.sh so the pip
wheel/install flow runs with the toolchain flags applied: set CFLAGS/CXXFLAGS to
include -ffile-prefix-map=$(pwd)=/builddir and -gno-record-gcc-switches, set
LDFLAGS to include -Wl,--build-id=none, and set ARFLAGS to Drc before invoking
pip3 in the build script.

In `@packages/mdurl/build.ncl`:
- Around line 1-2: Remove the reviewer TODO from the mdurl package metadata and
tighten the package outputs definition. Update the build config using the mdurl
package block so it reflects that mdurl has no runtime dependencies beyond
Python, then replace the broad usr/** output with the same split used in sibling
packages: explicit python_site_package and python_dist_info outputs. Keep the
change scoped to the package’s build definition and ensure the final metadata no
longer advertises unresolved reviewer work.
- Line 5: The binding name in the top-level import expression is invalid because
Nickel bare identifiers cannot contain hyphens. Update the `let` binding in the
module so it uses a valid Nickel identifier, such as an underscore-based name or
a quoted identifier, and then adjust any nearby references in the same file to
match the new symbol. Keep the import target unchanged; only rename the local
binding used for the result of `import "../flit-core/build.ncl"`.

In `@packages/pluggy/build.sh`:
- Line 4: The version in build.sh is hardcoded and duplicates the version
declared in build.ncl, so update the build flow to pass the version through
build_args instead of exporting SETUPTOOLS_SCM_PRETEND_VERSION directly. Use the
existing version variable in build.ncl and forward it with build_args = {
include version }, so the build.sh setup stays in sync with the package version.

In `@packages/trove-classifiers/build.ncl`:
- Around line 8-23: The package build currently duplicates the version in
build.sh instead of reusing the build.ncl version variable. Update the
trove-classifiers build definition to pass version through build_args using the
existing version symbol, and then change build.sh to consume that injected value
for SETUPTOOLS_SCM_PRETEND_VERSION rather than hardcoding the literal. This
keeps the build metadata in sync when the version is bumped.

In `@packages/trove-classifiers/build.sh`:
- Line 4: The version export in build.sh is hardcoded and can drift from the
source of truth. Update the build.sh logic to use $MINIMAL_ARG_VERSION instead
of the literal value, and make sure build.ncl forwards version through
build_args so the environment variable is populated consistently. Use the
existing build.sh setup and the build.ncl version wiring to keep both files in
sync on future version bumps.

In `@packages/wrapt/build.ncl`:
- Line 2: The wrapt build definition still contains an unresolved TODO, which
conflicts with the PR’s “0 TODOs” claim. Remove the leftover reviewer TODO from
build.ncl and, using the existing package metadata around runtime_deps in the
wrapt package definition, confirm the outputs are correct or update them
explicitly if needed so the file is left in a final state with no TODO markers.

---

Nitpick comments:
In `@packages/blinker/build.ncl`:
- Around line 22-24: The outputs for the blinker package are using a broad
catch-all glob instead of the same split pattern used by sibling builds. Update
the outputs definition in the build config to match the established approach
from pathspec and trove-classifiers by separating site-packages and dist-info
into distinct OutputData entries, and adjust the glob(s) accordingly while
keeping the same build symbols and structure.
- Around line 1-2: The build manifest still contains an unresolved reviewer TODO
in the imported blinker package metadata. Update the blinker build definition to
clear the TODO now that the runtime dependency check is confirmed, and make sure
the package entry reflects the resolved state without leaving the reviewer note
in the file. Refer to the blinker package definition in build.ncl and remove or
replace the TODO so the batch is consistent with the “0 TODOs” claim.

In `@packages/wrapt/build.ncl`:
- Around line 10-24: The wrapt package output glob is too broad and should be
narrowed to the package’s actual install paths. Update the outputs definition in
build.ncl so the artifact only collects wrapt under site-packages and the
corresponding wrapt-*.dist-info metadata instead of all usr/** files, using the
existing build_deps/cmd setup and the wrapt package name to locate the relevant
output. Also remove the unnecessary toolchain dependency since wrapt already
falls back to pure Python when no compiler is available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b6201881-462e-4356-89cf-6c39e4ac1b17

📥 Commits

Reviewing files that changed from the base of the PR and between 99f1af9 and bac1839.

📒 Files selected for processing (57)
  • packages/blinker/build.ncl
  • packages/blinker/build.sh
  • packages/boltons/build.ncl
  • packages/boltons/build.sh
  • packages/calver/build.ncl
  • packages/calver/build.sh
  • packages/certifi/build.ncl
  • packages/certifi/build.sh
  • packages/certifi/use-alpine-system-certs.patch
  • packages/charset-normalizer/build.ncl
  • packages/charset-normalizer/build.sh
  • packages/click/build.ncl
  • packages/click/build.sh
  • packages/distro/build.ncl
  • packages/distro/build.sh
  • packages/editables/build.ncl
  • packages/editables/build.sh
  • packages/hatch-vcs/build.ncl
  • packages/hatch-vcs/build.sh
  • packages/hatchling/build.ncl
  • packages/hatchling/build.sh
  • packages/idna/build.ncl
  • packages/idna/build.sh
  • packages/itsdangerous/build.ncl
  • packages/itsdangerous/build.sh
  • packages/jinja2/build.ncl
  • packages/jinja2/build.sh
  • packages/markupsafe/build.ncl
  • packages/markupsafe/build.sh
  • packages/mdurl/build.ncl
  • packages/mdurl/build.sh
  • packages/more-itertools/build.ncl
  • packages/more-itertools/build.sh
  • packages/pathspec/build.ncl
  • packages/pathspec/build.sh
  • packages/pluggy/build.ncl
  • packages/pluggy/build.sh
  • packages/pygments/build.ncl
  • packages/pygments/build.sh
  • packages/python-dateutil/build.ncl
  • packages/python-dateutil/build.sh
  • packages/pyyaml/build.ncl
  • packages/pyyaml/build.sh
  • packages/requests/build.ncl
  • packages/requests/build.sh
  • packages/setuptools-scm/build.ncl
  • packages/setuptools-scm/build.sh
  • packages/six/build.ncl
  • packages/six/build.sh
  • packages/trove-classifiers/build.ncl
  • packages/trove-classifiers/build.sh
  • packages/typing-extensions/build.ncl
  • packages/typing-extensions/build.sh
  • packages/urllib3/build.ncl
  • packages/urllib3/build.sh
  • packages/wrapt/build.ncl
  • packages/wrapt/build.sh

Comment on lines +10 to +20
build_deps = [
{ file = "build.sh" } | Local,
{
url = "gs://minimal-staging-archives/certifi/python-certifi/%{version}.tar.gz",
sha256 = "de76d4c70f5a4fecce2522a11e01b57ea75d41d878bc590dcc43290d26a0acc8",
extract = true,
strip_prefix = "python-certifi-%{version}",
} | Source,
base,
setuptools,
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files:\n'
git ls-files 'packages/certifi/*' || true

printf '\n--- build.ncl (numbered excerpt) ---\n'
cat -n packages/certifi/build.ncl | sed -n '1,120p'

printf '\n--- build.sh (numbered excerpt) ---\n'
cat -n packages/certifi/build.sh | sed -n '1,200p'

printf '\n--- patch references ---\n'
rg -n --no-heading 'use-alpine-system-certs\.patch|patch -p1|patch ' packages/certifi || true

Repository: gominimal/pkgs

Length of output: 2362


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n--- use-alpine-system-certs.patch (excerpt) ---\n'
cat -n packages/certifi/use-alpine-system-certs.patch | sed -n '1,220p'

Repository: gominimal/pkgs

Length of output: 2449


Add use-alpine-system-certs.patch to build_deps. build.sh doesn’t apply the patch today, so certifi still ships its vendored cacert.pem instead of Alpine’s system CA bundle.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/certifi/build.ncl` around lines 10 - 20, The certifi build
configuration is missing the use-alpine-system-certs.patch dependency, so the
package still uses its vendored CA bundle instead of Alpine’s system
certificates. Update build_deps in build.ncl to include the patch alongside the
existing Local and Source entries, using the build.sh flow and certifi package
symbols so the patch is applied during the build.

Comment thread packages/itsdangerous/build.ncl Outdated
Comment thread packages/jinja2/build.ncl Outdated
Comment on lines +1 to +5
#!/bin/sh
# Imported from Wolfi `markupsafe` (3.0.3, python) by pkgmgr import-wolfi.
set -eu
pip3 wheel -w dist --no-build-isolation --no-deps --no-cache-dir "$(pwd)"
pip3 install --no-index --find-links dist --no-deps --no-user --root "$OUTPUT_DIR" markupsafe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Missing C build reproducibility flags for MarkupSafe's C extension.

This package pulls in toolchain (build.ncl) because MarkupSafe compiles a _speedups C extension, but build.sh never sets the required CFLAGS/LDFLAGS/ARFLAGS. Without -ffile-prefix-map/-gno-record-gcc-switches/--build-id=none, the compiled .so will embed the sandbox's absolute build path and a build ID, breaking bit-for-bit reproducibility.

🛠️ Proposed fix
 #!/bin/sh
 # Imported from Wolfi `markupsafe` (3.0.3, python) by pkgmgr import-wolfi.
 set -eu
+export CFLAGS="${CFLAGS:-} -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches"
+export CXXFLAGS="${CXXFLAGS:-} -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches"
+export LDFLAGS="${LDFLAGS:-} -Wl,--build-id=none"
+export ARFLAGS="Drc"
 pip3 wheel -w dist --no-build-isolation --no-deps --no-cache-dir "$(pwd)"
 pip3 install --no-index --find-links dist --no-deps --no-user --root "$OUTPUT_DIR" markupsafe

As per coding guidelines: "For C/C++ builds, apply compiler flags: CFLAGS/CXXFLAGS with '-ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches', LDFLAGS with '-Wl,--build-id=none', and ARFLAGS='Drc'".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#!/bin/sh
# Imported from Wolfi `markupsafe` (3.0.3, python) by pkgmgr import-wolfi.
set -eu
pip3 wheel -w dist --no-build-isolation --no-deps --no-cache-dir "$(pwd)"
pip3 install --no-index --find-links dist --no-deps --no-user --root "$OUTPUT_DIR" markupsafe
#!/bin/sh
# Imported from Wolfi `markupsafe` (3.0.3, python) by pkgmgr import-wolfi.
set -eu
export CFLAGS="${CFLAGS:-} -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches"
export CXXFLAGS="${CXXFLAGS:-} -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches"
export LDFLAGS="${LDFLAGS:-} -Wl,--build-id=none"
export ARFLAGS="Drc"
pip3 wheel -w dist --no-build-isolation --no-deps --no-cache-dir "$(pwd)"
pip3 install --no-index --find-links dist --no-deps --no-user --root "$OUTPUT_DIR" markupsafe
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/markupsafe/build.sh` around lines 1 - 5, The build script for
MarkupSafe’s C extension is missing the required reproducibility settings.
Update the build steps in build.sh so the pip wheel/install flow runs with the
toolchain flags applied: set CFLAGS/CXXFLAGS to include
-ffile-prefix-map=$(pwd)=/builddir and -gno-record-gcc-switches, set LDFLAGS to
include -Wl,--build-id=none, and set ARFLAGS to Drc before invoking pip3 in the
build script.

Source: Coding guidelines

Comment thread packages/mdurl/build.ncl Outdated
Comment thread packages/mdurl/build.ncl
# TODO: REVIEWER — verify the pypi runtime deps (install_requires) + outputs.
let { Attrs, BuildSpec, Local, OutputData, Source, .. } = import "minimal.ncl" in
let base = import "../base/build.ncl" in
let flit-core = import "../flit-core/build.ncl" in

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does the Nickel configuration language allow hyphens in bare identifiers used in let-bindings?

💡 Result:

No, the Nickel configuration language does not allow hyphens in bare identifiers [1]. According to the official Nickel syntax documentation, identifiers must start with zero or more underscores, followed by an alphabetic character (a-z or A-Z) [1]. Hyphens are not included in the allowed character set for standard identifiers, and using them directly in a let-binding will result in a syntax error. If you need to use an identifier containing a hyphen or other special characters, you must use string-based identifiers, which are typically used for record fields [2] or accessed via dynamic lookup, rather than as bare variable names in let-bindings. Bare identifiers in let-bindings must strictly adhere to the language's alphanumeric naming conventions [1].

Citations:


🌐 Web query:

Nickel language bare identifier grammar hyphen let binding official docs

💡 Result:

In the Nickel language, bare identifiers must follow a specific grammar and do not support hyphens [1]. According to official Nickel documentation, identifiers start with zero or more underscores (_), followed by an alphabetic character (a-z or A-Z), and are then followed by zero or more alphanumeric characters, underscores, or apostrophes (') [1]. Because hyphens (-) are not included in this allowed character set, they cannot be used in bare identifiers [1]. Regarding let-bindings, Nickel uses the standard let <identifier> = <expression> in <expression> syntax [2][3][4]. Type annotations can also be attached directly to let-bindings using the colon operator (e.g., let x : Number = 1 in x) [3][4]. While bare identifiers are restricted, Nickel provides mechanisms for working with dynamic or special identifiers. If you need an identifier containing characters not allowed in bare syntax (such as hyphens), you must typically use quoted identifiers or record-based approaches where string interpolation or literal strings are supported as keys (e.g., in record field names), rather than as bare lexical identifiers [5]. Internally, the language uses an Ident structure that can represent identifiers with arbitrary strings, but these are distinct from the surface-level bare identifiers allowed by the parser [6][7][8].

Citations:


Rename the binding to a valid Nickel identifier
flit-core is not a valid bare let name in Nickel; hyphens are not allowed in identifiers, so this line will not parse. Use an underscore or a quoted identifier instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mdurl/build.ncl` at line 5, The binding name in the top-level import
expression is invalid because Nickel bare identifiers cannot contain hyphens.
Update the `let` binding in the module so it uses a valid Nickel identifier,
such as an underscore-based name or a quoted identifier, and then adjust any
nearby references in the same file to match the new symbol. Keep the import
target unchanged; only rename the local binding used for the result of `import
"../flit-core/build.ncl"`.

Comment thread packages/pluggy/build.sh Outdated
#!/bin/sh
# Imported from Wolfi `pluggy` (1.6.0, python) by pkgmgr import-wolfi.
set -eu
export SETUPTOOLS_SCM_PRETEND_VERSION="1.6.0"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Hardcoded version duplicates build.ncl's version variable.

SETUPTOOLS_SCM_PRETEND_VERSION="1.6.0" is a literal duplicate of the version = "1.6.0" declared in build.ncl. If the package is bumped, this string must be manually kept in sync, risking silent version-metadata mismatches. Forward the version via build_args instead.

♻️ Proposed fix
-export SETUPTOOLS_SCM_PRETEND_VERSION="1.6.0"
+export SETUPTOOLS_SCM_PRETEND_VERSION="$MINIMAL_ARG_VERSION"

And in build.ncl, forward the version:

+  build_args = { include version },

As per coding guidelines: "Declare version as a variable at the top of build.ncl and forward it through 'build_args = { include version }' to avoid hardcoding in build.sh."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export SETUPTOOLS_SCM_PRETEND_VERSION="1.6.0"
export SETUPTOOLS_SCM_PRETEND_VERSION="$MINIMAL_ARG_VERSION"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/pluggy/build.sh` at line 4, The version in build.sh is hardcoded and
duplicates the version declared in build.ncl, so update the build flow to pass
the version through build_args instead of exporting
SETUPTOOLS_SCM_PRETEND_VERSION directly. Use the existing version variable in
build.ncl and forward it with build_args = { include version }, so the build.sh
setup stays in sync with the package version.

Source: Coding guidelines

Comment on lines +8 to +23
let version = "2026.6.1.19" in
{
name = "trove-classifiers",
build_deps = [
{ file = "build.sh" } | Local,
{
url = "gs://minimal-staging-archives/pypa/trove-classifiers/%{version}.tar.gz",
sha256 = "20360c44ddae1f970eab52c26523de6e2e79bbe7c493fa363c681ee5fa47a588",
extract = true,
strip_prefix = "trove-classifiers-%{version}",
} | Source,
base,
setuptools,
setuptools-scm,
],
cmd = "./build.sh",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Forward version via build_args instead of duplicating it as a hardcoded literal in build.sh.

build.sh hardcodes SETUPTOOLS_SCM_PRETEND_VERSION="2026.6.1.19", duplicating the version variable declared here. If this package is ever version-bumped, updating only this file's version would silently leave the build.sh literal stale, causing the built wheel to report the wrong version. As per coding guidelines: "Declare version as a variable at the top of build.ncl and forward it through 'build_args = { include version }' to avoid hardcoding in build.sh."

Note: this differs from the retrieved-learning exception (which applies when the install step only uses the distribution name and doesn't need the version value at runtime) — here the version value is actually consumed by SETUPTOOLS_SCM_PRETEND_VERSION inside the build environment.

🔧 Proposed fix
   cmd = "./build.sh",
+  build_args = {
+    include version,
+  },
   outputs = {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let version = "2026.6.1.19" in
{
name = "trove-classifiers",
build_deps = [
{ file = "build.sh" } | Local,
{
url = "gs://minimal-staging-archives/pypa/trove-classifiers/%{version}.tar.gz",
sha256 = "20360c44ddae1f970eab52c26523de6e2e79bbe7c493fa363c681ee5fa47a588",
extract = true,
strip_prefix = "trove-classifiers-%{version}",
} | Source,
base,
setuptools,
setuptools-scm,
],
cmd = "./build.sh",
let version = "2026.6.1.19" in
{
name = "trove-classifiers",
build_deps = [
{ file = "build.sh" } | Local,
{
url = "gs://minimal-staging-archives/pypa/trove-classifiers/%{version}.tar.gz",
sha256 = "20360c44ddae1f970eab52c26523de6e2e79bbe7c493fa363c681ee5fa47a588",
extract = true,
strip_prefix = "trove-classifiers-%{version}",
} | Source,
base,
setuptools,
setuptools-scm,
],
cmd = "./build.sh",
build_args = {
include version,
},
outputs = {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/trove-classifiers/build.ncl` around lines 8 - 23, The package build
currently duplicates the version in build.sh instead of reusing the build.ncl
version variable. Update the trove-classifiers build definition to pass version
through build_args using the existing version symbol, and then change build.sh
to consume that injected value for SETUPTOOLS_SCM_PRETEND_VERSION rather than
hardcoding the literal. This keeps the build metadata in sync when the version
is bumped.

Source: Coding guidelines

Comment thread packages/trove-classifiers/build.sh Outdated
Comment thread packages/wrapt/build.ncl Outdated
- markupsafe: export the C-extension reproducibility flags (CFLAGS/CXXFLAGS
  -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches, LDFLAGS
  --build-id=none) so _speedups.so doesn't embed the sandbox path / a build-id.
- pluggy, trove-classifiers: SETUPTOOLS_SCM_PRETEND_VERSION now reads
  $MINIMAL_ARG_VERSION (forwarded via build_args) instead of a hardcoded literal
  that would silently go stale on a version bump.
- itsdangerous, jinja2, mdurl, wrapt: replace the discovery-mode catch-all
  `usr/**` output + reviewer TODO with precise python_site_package /
  python_dist_info globs, derived from the actual built trees (wrapt also ships
  a wrapt-stubs/ top-level dir). Runtime deps already verified correct
  (jinja2 -> markupsafe; the rest pure-python).

All rebuilt clean (minimal package --rebuild --no-fetch). These match what the
now-fixed importer emits. certifi's system-CA-bundle patch is left for a reviewer
decision (see PR comment) — it changes trust behavior + adds a runtime dep.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@bryan-minimal

Copy link
Copy Markdown
Member Author

Addressed CodeRabbit review (pushed)

  • markupsafe: export the C-extension reproducibility flags so _speedups.so doesn't embed the sandbox path / a build-id.
  • pluggy, trove-classifiers: SETUPTOOLS_SCM_PRETEND_VERSION now reads $MINIMAL_ARG_VERSION (forwarded via build_args) instead of a hardcoded literal that would go stale on a bump.
  • itsdangerous, jinja2, mdurl, wrapt: replaced the discovery-mode catch-all usr/** output + reviewer TODO with precise python_site_package / python_dist_info globs, derived from the actual built trees (wrapt also ships a wrapt-stubs/ top-level dir). Runtime deps confirmed correct (jinja2 → markupsafe; the rest pure-python).

All rebuilt clean with minimal package --rebuild --no-fetch. The template gaps are also fixed in the importer (pkgmgr-rs #471) so future imports don't reintroduce them.

One dismissed as a false positive

mdurl/build.ncl — "flit-core is not a valid bare let name". Same as re2 in #367: Nickel permits hyphens; the package builds and passes minimal check. Left as-is.

One left as a reviewer decision: certifi

CR's point is valid — certifi ships its vendored cacert.pem rather than deferring to the system CA bundle (Wolfi/Alpine patch this with use-alpine-system-certs.patch). I've not applied it here because it's a genuine trust-policy change: it makes certifi.where() return the system path and adds a ca-certificates runtime dep, and the patch is certifi-version-specific. If we want Minimal's Python stack to defer to the system trust store (I'd lean yes), I'll wire the patch + runtime dep in a follow-up. Flagging rather than silently changing TLS trust behavior.

@twitchyliquid64 twitchyliquid64 left a comment

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.

Confirming these are all CLI programs? as a general rule, we don't want to have packages that just provide python libraries as source (as debian does) bc it doesnt scale. Though we have had to do that for some packages (i.e. pyproject, cython etc)

@bryan-minimal

Copy link
Copy Markdown
Member Author

I'll review before merging, these were packages that many other packages were dependant on, but you are right, we usually let the package bring their python libs.

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.

2 participants