Skip to content

Install hash-locked tooling and build with the locked setuptools in the PyPI publish jobs - #497

Open
JE-Chen wants to merge 2 commits into
devfrom
feat/locked-publish-tooling
Open

JE-Chen wants to merge 2 commits into
devfrom
feat/locked-publish-tooling

Conversation

@JE-Chen

@JE-Chen JE-Chen commented Oct 1, 2026

Copy link
Copy Markdown
Member

Why

The two jobs that receive secrets.PYPI_API_TOKEN (publish in stable.yml, publish-dev in dev.yml) pinned build and twine by version only: no hashes, and their dependencies at whatever was newest that day. python -m build then created an isolated environment and downloaded the newest setuptools. All of that runs in the job that is about to upload with the token.

What changes

  • New .github/requirements/publish.in and the generated publish.txt: build==1.5.0, twine==6.2.0 (the versions the workflows already named) and the build backend setuptools (locked at 84.0.0), 30 pins in all, wheels only, with hashes, for Python 3.12 on x86_64-manylinux_2_28. The uv pip compile command is at the top of publish.in.
  • Both jobs run one install, python -m pip install --require-hashes --only-binary :all: -r .github/requirements/publish.txt, and build with python -m build --no-isolation, so the backend is the locked one. Triggers, the other steps and the secret are unchanged.
  • release.yml is unchanged: its build job has no PyPI token.
  • .github/dependabot.yml: the pip entry names / and /.github/requirements, which Dependabot does not reach from the root.
  • New test/unit_test/headless/test_publish_tooling_lock.py (11 cases): only those two jobs read the token; each runs exactly the locked install; every python -m build in them carries --no-isolation; build-system.requires in pyproject.toml and dev.toml names only packages the lock pins, at a version inside the specifier; publish.in names exactly what the jobs run plus the backend; the lock is resolved for the Python the jobs set up; Dependabot watches the directory.
  • test_dev_release.py compares the locked install line and the --no-isolation build line of the two jobs instead of the build== line.
  • architecture.md, architecture_explore.md, CLAUDE.md and docs/updates/ (U-20261001-10) describe it.

Checked

  • All 30 locked wheels download for CPython 3.12 on manylinux x86_64 with matching hashes (pip download --require-hashes --only-binary :all: --no-deps).
  • Built in a throwaway worktree in a Python 3.12 environment holding the 30 locked versions: stable metadata (0.0.225) and dev metadata (scripts/dev_release.py prepare, 0.0.137), each with --no-isolation and, for comparison, isolated. sdist and wheel build, twine check passes, each wheel has 1,062 members with the same names and content as the isolated build's, each sdist the same 1,067 files.
  • The dev wheel differs from the published je_auto_control_dev 0.0.136 only in its version line and RECORD, so publish-dev has nothing to upload for this change.
  • Full headless suite locally (Windows, Python 3.14): 10673 passed, 46 skipped.

Not exercised here

Neither publish job runs on a pull request. publish-dev first runs its install and build steps on the push that brings this to dev; stable.yml's publish once dev is merged into main.

…he jobs that hold the PyPI token

publish (stable.yml) and publish-dev (dev.yml) pinned build and twine by
version only, so their dependencies were whatever was newest that day, and
python -m build then downloaded the newest setuptools into an isolated
environment. All of it runs next to PYPI_API_TOKEN.

Both jobs now install only .github/requirements/publish.txt (wheels only, at
recorded hashes, generated from publish.in with uv) and build with
python -m build --no-isolation, so the backend is the locked setuptools too.
build stays at 1.5.0 and twine at 6.2.0; setuptools is locked at 84.0.0.

Dependabot's pip entry names .github/requirements, which it does not reach
from the root. test_publish_tooling_lock.py fails when a job with the token
runs any other pip install or an isolated build, and when build-system.requires
in pyproject.toml or dev.toml asks for something the lock does not pin.
@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@sonarqubecloud

sonarqubecloud Bot commented Oct 1, 2026

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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.

1 participant