Skip to content

Python: Pin openrewrite Python package version in RPC bootstrap#6813

Merged
knutwannheden merged 4 commits intomainfrom
bright-pangolin
Feb 25, 2026
Merged

Python: Pin openrewrite Python package version in RPC bootstrap#6813
knutwannheden merged 4 commits intomainfrom
bright-pangolin

Conversation

@knutwannheden
Copy link
Contributor

@knutwannheden knutwannheden commented Feb 25, 2026

Summary

PythonRewriteRpc.bootstrapOpenrewrite() was running bare pip install openrewrite without a version specifier, unlike the JavaScript side which reads /META-INF/version.txt and pins @openrewrite/rewrite@<version> via npx. This could result in a mismatched Python openrewrite package, and the existence-only check meant users could get stuck on a stale version indefinitely.

Changes

  • Version resource: Generate META-INF/version.txt at build time (PEP 440 format), matching the rewrite-javascript pattern. Wired into sourcesJar, processResources, licenseMain, assemble tasks. License exclude and .gitignore entry added.
  • Version pinning: bootstrapOpenrewrite() reads the version from the resource and runs pip install --upgrade openrewrite==<version> for release/CI builds. For local .dev0 builds, the version is not pinned.
  • Stale install detection: A .openrewrite-version marker file tracks the installed version in pipPackagesPath. On startup, if the marker doesn't match the JAR's version, the package is reinstalled with --upgrade.
  • Dev interpreter detection: For SNAPSHOT/dev builds only, probes whether the Python interpreter can already import rewrite (e.g., from a venv with an editable install). If so, skips both bootstrap and PYTHONPATH prepend so the interpreter's own package takes precedence. This mirrors the JS pattern where SNAPSHOT trusts the local dev environment (npm link).

Behavior matrix

Build type version.txt Interpreter has rewrite? Behavior
Release 8.75.0 8.75.0 (ignored) Bootstrap openrewrite==8.75.0, prepend to PYTHONPATH
CI SNAPSHOT 8.75.0.dev2026... (ignored) Bootstrap pinned dev version, prepend to PYTHONPATH
Local SNAPSHOT 8.75.0.dev0 Yes (venv) Skip bootstrap, skip prepend — use venv's package
Local SNAPSHOT 8.75.0.dev0 No Bootstrap unpinned openrewrite, prepend to PYTHONPATH

Companion CLI PR: https://github.com/moderneinc/moderne-cli/pull/3350

Test plan

  • ./gradlew :rewrite-python:assemble succeeds, version.txt present in JAR with correct content
  • ./gradlew :rewrite-python:licenseFormat does not inject headers into version.txt
  • Verify release build (non-SNAPSHOT) produces clean version like 8.75.0 in version.txt
  • Verify bootstrap with pipPackagesPath set installs the pinned version
  • Verify dev build with venv interpreter skips bootstrap and uses venv's package

PythonRewriteRpc.bootstrapOpenrewrite() was running bare `pip install
openrewrite` without a version specifier, unlike the JavaScript side
which reads /META-INF/version.txt and pins `@openrewrite/rewrite@<version>`.

This meant the Python RPC could end up with a mismatched openrewrite
package version, and the existence-only check meant users could get
stuck on a stale version indefinitely.

Changes:
- Generate META-INF/version.txt in the build (PEP 440 format) so the
  Java code can read the expected Python package version at runtime
- Pin `openrewrite==<version>` in bootstrapOpenrewrite() for release
  and CI builds; skip pinning for local .dev0 builds
- Track installed version via a marker file to detect and upgrade
  stale installs
- Add license exclude for version.txt and .gitignore entry
Without --upgrade, pip install --target may skip the install when
it sees the package already exists, even if the version differs.
@knutwannheden knutwannheden changed the title Pin openrewrite Python package version in RPC bootstrap Python: Pin openrewrite Python package version in RPC bootstrap Feb 25, 2026
@knutwannheden knutwannheden changed the title Python: Pin openrewrite Python package version in RPC bootstrap Python: Pin `openrewrite Python package version in RPC bootstrap Feb 25, 2026
@knutwannheden knutwannheden changed the title Python: Pin `openrewrite Python package version in RPC bootstrap Python: Pin openrewrite Python package version in RPC bootstrap Feb 25, 2026
For SNAPSHOT/dev builds, probe whether the Python interpreter can
already import rewrite (e.g., from a venv with an editable install).
If so, skip both the bootstrap and the PYTHONPATH prepend so the
interpreter's own package takes precedence.

For release/CI builds, always bootstrap and prepend to ensure the
correct pinned version is used. This mirrors the JS pattern where
SNAPSHOT trusts the local dev environment (npm link) while release
pins the exact version.
@knutwannheden knutwannheden merged commit 02c48a7 into main Feb 25, 2026
1 check passed
@knutwannheden knutwannheden deleted the bright-pangolin branch February 25, 2026 10:53
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Feb 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant