Skip to content

Lock production Python packages and refresh dependencies - #15

Merged
adewale merged 6 commits into
mainfrom
claude/upbeat-pascal-5v19jz
Sep 24, 2026
Merged

adewale merged 6 commits into
mainfrom
claude/upbeat-pascal-5v19jz

Conversation

@adewale

@adewale adewale commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Summary

This PR is a dependency refresh in five parts. Each has its own commit, so it can be reviewed one commit at a time.

1. Production Python packages are now locked (e937763). This is the important one. Pywrangler 1.9.3 ignored uv.lock: at every deploy it resolved the unpinned fastapi in [project] dependencies afresh. So CI tested one set of packages while production shipped whatever was newest that day:

Package Tested (uv.lock on main) Shipped by a deploy today
fastapi 0.136.1 0.141.1
starlette 1.0.0 (5 advisories) 1.7.0
pydantic 2.13.3 2.10.6 (newest with a Pyodide wheel)

Pywrangler 1.17.4 instead resolves production packages into a committed, hash-pinned pylock.toml and reuses it on later syncs. uv.lock now pins every package the two files share to the pylock.toml version, so the tests run against exactly what ships. Several things now enforce that:

  • tests/test_dependency_locks.py fails if the two lockfiles disagree, naming the package.
  • CI (after pywrangler dev syncs) and make deploy run git diff --exit-code -- pylock.toml, so production can't drift from the commit.
  • make upgrade-runtime-deps refreshes both lockfiles together, using scripts/align_runtime_lock.py.
  • Pywrangler 1.17 needs uv 0.12.3 or newer. The README now says so, and CI's setup-uv already installs the latest uv.

2. Pillow 12.3.0 (e39ff68): removes the <12 cap. The previous 11.3.0 had 17 advisories. Pillow is used only by the social-card tooling.

3. CI actions on Node 24 (d254fed): moves to checkout v7, setup-node v7, setup-python v7 and setup-uv v10.2.0, which clears the Node.js 20 deprecation warning on every run.

  • setup-uv no longer publishes floating major tags, so it's pinned to a commit SHA with a version comment, as its README recommends.
  • setup-node v6+ turns on npm caching automatically when package.json has a packageManager field. package-manager-cache: false keeps CI cache-free, like enable-cache: false does for uv.

4. Dependabot (438635e): weekly updates with a 3-day cooldown for:

  • npm;
  • GitHub Actions, grouped into one PR;
  • Hypothesis, Pillow and Pywrangler.

Runtime packages are left out, because their versions depend on which Pyodide wheels exist; they're refreshed with make upgrade-runtime-deps. Ruff is left out because upgrades add lint rules and must match required-version.

The toolchain test used to hard-code the Wrangler version. It now checks that Wrangler is pinned exactly and matches between package.json and the lockfile, so Dependabot's bumps can pass.

5. Browser libraries (bde4e6c):

  • Shiki 1.29.2 → 4.4.3. Every Python block in the example sources (440 of them) renders byte-identical HTML on both versions, in both themes.
  • CodeMirror: state 6.5.2 → 6.7.6, view 6.41.1 → 6.43.13, language 6.12.3 → 6.12.4.
  • Fingerprinted assets were rebuilt and the HTML cache version bumped.

Pywrangler's upgrade is part of (1). Commit 467b405 updates the CHANGELOG and lessons-learned.

Result: pip-audit reports no known vulnerabilities in uv.lock or pylock.toml, and npm audit finds 0 at every severity.

Verification

Run locally on Node 22.22.2, Python 3.13 and uv 0.12.18, with pywrangler dev --port 9696 on Pywrangler 1.17.4:

  • make verify: every step passed except browser-layout-test (see below), including 227 tests, SEO/cache lint, verify-examples, all quality checks, search ranking, lint and check-generated.
  • scripts/format_examples.py --check
  • make verify-python-version VERSION=3.13 (109 examples)
  • git diff --check
  • Added or updated regression tests and verified they fail when the fix is reverted. After changing pylock.toml's Starlette to 1.6.0, tests/test_dependency_locks.py failed with {'starlette': ('1.6.0', '1.7.0')}.
  • Manual verification:
    • make smoke-deployment URL=http://localhost:9696 passed 9 GETs and 5 Dynamic Worker POST runs on the newly locked runtime packages.
    • After pywrangler dev, the packages in python_modules/ match pylock.toml exactly, and pylock.toml is unchanged.
    • dependabot.yml validates against the SchemaStore schema.

browser-layout-test fails locally only on "Search focus indicator is too weak" and "CodeMirror focus indicator is too weak". main fails the same two checks in this sandbox's Chromium, and CI uses Google Chrome.

Visual evidence

There's no visual change. I ran browser-layout-test on main and on this branch in the same environment. All 113 measurements it reports are identical, including Shiki's code colours, CodeMirror's editor colours in light and dark mode, and code-block and editor layout. In headless Chromium, the new esm.sh builds render highlighted blocks and a working editor in both colour schemes, with no console errors.

Reproduction: CHROME_PATH=… make browser-layout-test against pywrangler dev (base: b6e9062; head: 467b405; 390px mobile viewport, both colour schemes), then compare the JSON the check prints.

🤖 Generated with Claude Code

https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b


Generated by Claude Code

Pywrangler 1.9.3 vendored `[project] dependencies` by resolving an
unpinned `fastapi` afresh at every deploy, ignoring uv.lock. CI tested
fastapi 0.136.1, starlette 1.0.0 and pydantic 2.13.3, while a deploy
shipped whatever was newest that day (fastapi 0.141.1, starlette 1.7.0,
pydantic 2.10.6).

Pywrangler 1.17.4 resolves production packages into a committed,
hash-pinned pylock.toml and reuses it on later syncs. uv.lock now pins
every shared package to the pylock.toml version, so the suite runs
against exactly what ships (starlette 1.7.0 also clears the five
advisories against the previously tested 1.0.0).

- tests/test_dependency_locks.py fails when the two locks disagree.
- CI and `make deploy` fail if pywrangler's sync would change the
  committed pylock.toml.
- `make upgrade-runtime-deps` refreshes both locks together via
  scripts/align_runtime_lock.py.

Pywrangler 1.17 requires uv 0.12.3 or newer; the README says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
The <12 cap held the social-card tooling on Pillow 11.3.0, which has 17
published advisories (PSD, FITS, PDF, font and JPEG2000 parsing, among
others), all fixed by 12.3.0. The script only opens its own generated
JPEGs, so exposure was low, but the cap blocked every fix.
`scripts/build_social_cards.py --check` decodes all 120 cards cleanly
on 12.3.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
Every Verify run warned that checkout@v4, setup-node@v4,
setup-python@v5 and setup-uv@v5 target the deprecated Node.js 20
runtime and were being forced onto Node 24. Their current releases
(checkout v7, setup-node v7, setup-python v7, setup-uv v10.2.0) run on
Node 24 natively.

- setup-uv no longer publishes floating major tags, so it is pinned to
  the v10.2.0 commit, as its README recommends.
- setup-node v6+ enables npm caching automatically when package.json
  has a packageManager field; `package-manager-cache: false` keeps CI
  cache-free, matching setup-uv's `enable-cache: false`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
Wrangler upgrades kept arriving as manual fixes once the high-severity
npm audit gate went red (#12, and twice in #13). Dependabot now
proposes weekly updates for:

- npm (Wrangler), after a 3-day cooldown;
- uv, limited to hypothesis, pillow and workers-py. Runtime packages
  stay on `make upgrade-runtime-deps`, since production vendors
  pylock.toml from Pyodide wheels, and Ruff upgrades stay deliberate
  because they add lint rules and must match `required-version`;
- GitHub Actions, grouped into one PR.

The toolchain contract test now asserts that Wrangler is exactly pinned
and consistent across package.json and package-lock.json instead of
hard-coding a version, so Dependabot's bumps can pass CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
The browser libraries loaded from esm.sh had fallen behind: Shiki by
three major versions (1.29.2 -> 4.4.3) and CodeMirror by several minor
releases (state 6.5.2 -> 6.7.6, view 6.41.1 -> 6.43.13, language
6.12.3 -> 6.12.4; view 6.43 requires state 6.7).

The site uses only Shiki's `codeToHtml(source, { lang: 'python',
theme })` with the GitHub light and dark themes. Rendering all 440
Python blocks from the example sources in both themes produces
byte-identical HTML on 1.29.2 and 4.4.3, so highlighting and dark mode
are unchanged. The screenshot tool's `--legacy-shiki` mode follows the
production pin. Rebuilt fingerprinted assets and the HTML cache
version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
Documents the pylock.toml lock, the upgraded packages and actions, and
the Dependabot policy, and records why a lockfile protects only what
installs from it. The TLS lesson now names UV_SYSTEM_CERTS, since uv
0.12 (Pywrangler 1.17's minimum) deprecates UV_NATIVE_TLS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112H6AesYWoaS2XdDEHUJ4b
@adewale
adewale merged commit 62558e3 into main Sep 24, 2026
2 checks passed
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