Modernize pelican project to PEP-standard pyproject.toml with uv and Hatch#702
Conversation
|
I will test tomorrow against some my uses of the action. |
There was a problem hiding this comment.
Pull request overview
Modernizes the pelican/ subtree into a PEP-standard Python project (via pyproject.toml) and updates the composite action + Docker runtime to install Pelican and the action’s dependencies using uv tool install, removing requirements.txt as the dependency source of truth.
Changes:
- Replace
requirements.txt-based dependency management withpelican/pyproject.toml(PEP 621 + PEP 735 dependency groups), plus Hatch/uv configuration. - Rework
pelican/action.ymlto provision Python viaactions/setup-python, installuv, and install Pelican + action deps into an isolated uv tool venv. - Update
pelican/Dockerfileto bootstrapuvand install Pelican + action deps viauv tool install, plus adjust thepelicanasfwrapper to runplugin_pathsinside the tool venv.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pelican/requirements.txt |
Removed in favor of pyproject.toml as the single dependency source of truth. |
pelican/README.md |
Rewritten docs covering inputs, layout, and uv/Hatch workflows. |
pelican/pyproject.toml |
New PEP-standard project metadata, runtime deps, PEP 735 dev group, and tooling config (uv/Hatch/ruff). |
pelican/Dockerfile |
Switches runtime install flow to uv tool install and updates the pelicanasf wrapper to use the tool venv’s Python for plugin_paths. |
pelican/action.yml |
Uses setup-python + uv tool installs; runs Pelican directly from the uv tool venv and executes plugin_paths via the tool venv Python. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sebbASF
left a comment
There was a problem hiding this comment.
The dependabot change appears to be tangential to this PR.
I don't have any experience with setting up uv, so cannot comment otherwise
4b173e8 to
9022092
Compare
|
Oh. absolutely. But the copilot has a very oudated approach - they way it locks dependencies it's not only few years old but it also does not allow for modern ways of keeping it up-to-date (while providing reproducibility). But I am so glad that you asked @dave2wave and @sebbASF and that you care about reproducibility. Actually when I prepared the pr, I had an option to add uv.lock to the the PR, I thought that it will be too much to add to the PR, but since reproducibility seems to be an important aspect, I added it. Generally speaking Actually - to be perfectly honest - what dependabot (and previous approach) proposed was not at all reproducible. At most it was "reproduce-ish". It only pinned one dependency, but all the transitive dependencies were not pinned - which did not guarantee python package reproducibility. Uv lock, and the way how it pins not only the specified dependency, but all the transitive ones and also all the architecture variations for reproducibility, is the absolute modern standard for reproducibility - of both modern development environment and also it allows to add dependabot upgrades when security issues are published for them. |
Not really tangential - it's just how adding managing dependencies work in modern projects. Dependabot understandlats uv lock and pyproject.toml - and adding it to the modern way of packaging (especially with cooldown) allows few things:
so - those are not really tangential changes, those are all changes to modernise general setup of dependencies, development environment and package management. This absolutely follows all the modern standards - published by Python Packaging Authority (PyPA) - some of them as old as 4-5 years. All modern tools and IDEs support those as well - for example opening such "pelican" folder in an IDE will result in a working version that you can run tests on and develop without any setup at all - just auto-discovery will have everything created. With Python packaging and tooling had gone a long way over last 4 years - matching now all modern language development. It also makes it easier for agentic workflows - standard project setup allows agents to disover how to run tests and develop code easily - so for example they will run all the tests, formatting and linting automatically - based on |
|
Convert the `pelican/` subtree from a requirements.txt-driven install to a fully PEP-standard Python project, with both uv (proprietary, astral-sh) and Hatch (PyPA/PSF-managed) wired in as first-class dev environment front-ends sharing a single PEP 735 dependency group, and with a committed uv.lock pinning every transitive dependency for reproducible Docker builds. - Add pyproject.toml following PEP 517/518/621/639/735: setuptools build backend, SPDX `Apache-2.0` license, requires-python >=3.10, curated runtime dependencies in [project].dependencies, and a [dependency-groups].dev holding Pelican itself (via `pelican[markdown]`) plus ruff and pytest. - Configure both environment managers against the same dev group: [tool.uv].required-version enforces uv >=0.5.0, and [tool.hatch.envs.default] uses dependency-groups = ["dev"] with `installer = "uv"` plus named `lint`/`fmt`/`test` scripts. - Commit pelican/uv.lock alongside pyproject.toml so transitive versions are pinned by hash. The lockfile is the source of truth for the Docker image and for `uv sync` workflows; the composite action deliberately ignores it so the action's `version` input stays authoritative for Pelican. - Delete pelican/requirements.txt; pyproject.toml is now the single source of truth for declared dependency ranges across every install path. - Rewire action.yml to set up Python via actions/setup-python pinned by full commit SHA (a26af69be951a213d495a4c3e4e4022e16d87065, v5.6.0) per GitHub Actions security hardening guidance, bootstrap uv with a plain pip install, and run `uv tool install 'pelican[markdown]==<version>' --with <action-path>` so Pelican and the action's deps land in one isolated tool venv. Optional `inputs.requirements` is layered in via --with-requirements. The Generate step invokes the `pelican` CLI from that venv and runs `plugin_paths` as a module via `$PELICAN_TOOL_PY`. - Rewire Dockerfile to bootstrap uv, copy pyproject.toml + uv.lock into the image, and run `uv sync --frozen` to install the project and its dev group (which includes Pelican) into /opt/pelican-asf/.venv straight from the lockfile. --frozen makes the build fail if uv.lock drifts from pyproject.toml, so production rebuilds are byte-reproducible. The `pelicanasf` wrapper now resolves Pelican from .venv/bin and runs `plugin_paths` via the venv's own Python. - Widen the dependabot uv ecosystem entry from "/" to ["/", "/pelican/"] via the plural `directories` field so Dependabot tracks the new pelican/pyproject.toml + pelican/uv.lock and proposes weekly bumps with a 4-day cooldown. - Rewrite README.md: PEP 621-style inputs table, project layout, three documented dev workflows (uv sync, manual uv venv, Hatch), tool version floors (uv >=0.5.0, hatch >=1.16.0), a plain English explanation of the two execution paths (composite action re-resolves on every run, Docker image is locked), and a dedicated "Updating dependencies" section covering manual `uv lock` / `uv lock --upgrade` workflows alongside Dependabot's weekly + cooldown behaviour. Generated-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9022092 to
2e014ef
Compare
|
I also added nicer handling of the case when pelicanconf.py is not found: |
|
Also - it nicely runs |
|
This will close #92 |
dave2wave
left a comment
There was a problem hiding this comment.
I reality wish that this PR was a branch in the apache/infrastructure-actions repository. If it were I could TEST it. Unfortunately I cannot easily test that this has no regressions. Please have no fear of creating a PR in a branch of the main repository.
|
I fear not: https://github.com/apache/infrastructure-actions/tree/modernize-pelican-pyproject -> branch created. BTW. It's easy to push it by anyone: Is what I did :) . |
dave2wave
left a comment
There was a problem hiding this comment.
I tested the build using apache/tooling-docs and the pages had no unexpected markup changes.
I will note that the action is not widely used:
- datafusion-site
- flex-site
- petri
- solr-site
- tooling-docs
I'm responsible for two of these. We should warn datafusion, flex, and Solr.
|
@sebbASF Do you have any opinion about the |
|
Once we merge I'll let the three projects know so that they can pin to the old sha if they get unexpected behavior. |
good idea. |
|
I sent an email to users@infra bcc'd to the three PMC's dev lists. |
Cool. Let's see what they come back with :) |
Summary
Modernizes the
pelican/subtree into a fully PEP-standard Python project,with both uv (proprietary, astral-sh) and Hatch (PyPA/PSF-managed)
wired in as first-class development environment front-ends sharing a single
PEP 735 dependency group. Runtime installs (Dockerfile and the composite
action) are rewired onto
uv tool install, andrequirements.txtis gone —pyproject.tomlis now the single source of truth.Both environment managers follow modern Python standards and are set up so a
contributor can pick whichever tool they prefer without losing anything:
Astral. Used for the actual install path in
action.ymlandDockerfile(
uv tool install 'pelican[markdown]' --with .) and as one of the threedocumented local-dev flows (
uv sync).[tool.hatch.envs.default]withinstaller = "uv"anddependency-groups = ["dev"], so it resolves the same PEP 735 dev groupthat uv does.
Modern standards adopted
[build-system][project]license = "Apache-2.0"[dependency-groups].devWhat changed
pyproject.toml(new) — PEP 621 metadata, SPDXApache-2.0license,requires-python = ">=3.10", curated runtime deps in[project].dependencies, a PEP 735[dependency-groups].devholdingpelican[markdown]>=4.11,<4.12+ruff+pytest,[tool.uv]withrequired-version = ">=0.5.0",[tool.hatch.envs.default]withdependency-groups = ["dev"]andinstaller = "uv", plus[tool.hatch.envs.default.scripts]namedlint/fmt/test.requirements.txt(deleted) — pyproject.toml is now canonical.Dockerfile— bootstraps uv, runsuv tool install 'pelican[markdown]' --with .against the in-imagecheckout, and rebuilds the
pelicanasfwrapper around the tool venv'spelicanCLI. The wrapper resolves the venv's own Python at build timeso user
pelicanconf.pycan import any dep that lives in the same venv.action.yml— addsactions/setup-python@v5as the first step,bootstraps uv via
pip install uv(no morePIP_BREAK_SYSTEM_PACKAGES),and runs
uv tool install "pelican[markdown]==${{ inputs.version }}" --with ${{ github.action_path }}with optional
--with-requirements ${{ inputs.requirements }}layeredin. The Generate step now calls
pelicandirectly and runsplugin_pathsas a module through
$PELICAN_TOOL_PY(published viaGITHUB_ENV).README.md— full rewrite of the working-with-the-project sections:PEP 621-style inputs table, project layout table, three documented dev
workflows (
uv sync, manualuv venv,hatch env create), tool versionfloors (uv
>=0.5.0, hatch>=1.16.0), and a plain-English explanationof the shared tool-venv execution model used by both the composite
action and the Docker image.
Behaviour changes worth flagging
pelican==4.5.4; it now follows theaction's
inputs.versiondefault (4.11.0.post0), aligning the Dockerpath with the composite action path. The stale
MarkupSafe<2.1.0workaround comment block tied to the 4.5.4 pin is gone.
actions/setup-python@v5(currently pinned to3.12) rather than therunner's system-managed Python.
Test plan
Validated locally on macOS against the real
pyproject.toml:uv tool install 'pelican[markdown]' --with .— resolves Pelican4.11.0.post0 + all runtime deps into a single tool venv; the
pelicanCLI is on PATH andpython -m plugin_pathsworks from thetool venv's own Python.
uv sync— creates.venv/+uv.lock, pulls in thedevgroupby default, and
python -c "import pelican, ruff, plugin_paths"succeeds.
uv venv && uv pip install -e . && uv pip install --group dev—alternate manual flow validated.
hatch env create/hatch run python -c "import pelican, ruff, plugin_paths"— Hatch reads[dependency-groups].devviadependency-groups = ["dev"](confirmed against Hatch 1.16.5 with afreshly recreated env).
[tool.uv].required-version = ">=0.5.0"enforced —uv syncpassesthe check; parse-verified via
tomllib.build-only) — needs a PR-triggered run on a downstream pelican site.
pelicanasf content— not yet run locally (requires the full cmarkbuild chain); will rely on CI / manual follow-up.
🤖 Generated with Claude Code