Conversation
📝 WalkthroughWalkthroughAdds a new ChangesPython Release CI Pipeline
Sequence Diagram(s)sequenceDiagram
actor Dev as Developer
participant GHA as GitHub Actions
participant Preflight as preflight job
participant ValidScript as validate_python_release.py
participant PyPIAPI as PyPI / TestPyPI JSON API
participant BuildJobs as build-pure / build-parsing / build-parsing-sdist
participant Smoke as smoke-install job
participant Assemble as assemble-artifacts job
participant Registry as TestPyPI / PyPI
Dev->>GHA: workflow_dispatch (publish_target, channel, versions, confirm)
GHA->>Preflight: run preflight job
Preflight->>ValidScript: python validate_python_release.py --publish-target --channel ...
ValidScript->>PyPIAPI: GET /pypi/{name}/{version}/json (conflict check)
PyPIAPI-->>ValidScript: 404 not found / 200 exists / error
ValidScript-->>Preflight: release-metadata.json + GITHUB_OUTPUT vars
Preflight-->>GHA: upload release-metadata artifact
GHA->>BuildJobs: build pure sdist/wheels + parsing wheels (cibuildwheel matrix) + parsing sdist
BuildJobs-->>GHA: upload dist-pure, dist-parsing-*, dist-parsing-sdist artifacts
GHA->>Smoke: download built dists, install potpie, import parsing module, run potpie setup --dry-run
Smoke-->>GHA: smoke pass / fail
GHA->>Assemble: download all dists + metadata, generate SHA256SUMS.txt
Assemble-->>GHA: upload release-artifacts bundle
GHA->>Registry: pypa/gh-action-pypi-publish (dist/) via OIDC id-token
Registry-->>GHA: publish confirmed
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 @.github/workflows/release-python.yml:
- Around line 79-88: The Validate release metadata step is interpolating
dispatch inputs directly into the shell command, which can be unsafe. Move the
github.event.inputs values into env on the same step, then update the run
command to pass only shell-expanded variables to
scripts/validate_python_release.py; keep the existing argument names but
reference the env vars instead of inline expressions. Use the Validate release
metadata step as the place to fix this and preserve the current validate script
invocation behavior.
- Around line 261-270: The smoke test currently installs potpie with
--find-links dist but can still resolve potpie-context-engine and potpie-parsing
from PyPI, so update the release-python workflow’s Smoke install and run CLI
step to explicitly install and pin the three local built artifacts from dist
using the preflight version output. Make sure the workflow verifies the built
wheel versions for potpie, potpie-context-engine, and potpie-parsing before
running potpie status, so the smoke test only exercises the artifacts produced
in this release job.
In `@scripts/validate_python_release.py`:
- Around line 86-105: Reject .devN versions in validate_pep440 by checking
version.is_devrelease before the beta/rc-specific pre-release validation. Update
validate_pep440 in scripts/validate_python_release.py so the
PackageInfo.parsed_version handling fails for beta and rc channels when a dev
release is present, alongside the existing version.pre checks, while leaving the
final-channel logic unchanged.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 349a78af-95f4-4878-ac62-05cddc3217a1
📒 Files selected for processing (2)
.github/workflows/release-python.ymlscripts/validate_python_release.py
| - name: Validate release metadata | ||
| id: validate | ||
| run: >- | ||
| python scripts/validate_python_release.py | ||
| --publish-target "${{ github.event.inputs.publish_target }}" | ||
| --channel "${{ github.event.inputs.channel }}" | ||
| --expected-potpie-version "${{ github.event.inputs.expected_potpie_version }}" | ||
| --expected-context-engine-version "${{ github.event.inputs.expected_context_engine_version }}" | ||
| --expected-parsing-version "${{ github.event.inputs.expected_parsing_version }}" | ||
| --confirm-publish "${{ github.event.inputs.confirm_publish }}" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Move dispatch inputs through environment variables before invoking the shell.
Line 85 through Line 88 interpolate user-controlled string inputs directly into run; an input containing quotes/semicolons can break out of the quoted argument. Pass expressions via env and expand shell variables instead.
Proposed fix
- name: Validate release metadata
id: validate
+ env:
+ PUBLISH_TARGET: ${{ github.event.inputs.publish_target }}
+ CHANNEL: ${{ github.event.inputs.channel }}
+ EXPECTED_POTPIE_VERSION: ${{ github.event.inputs.expected_potpie_version }}
+ EXPECTED_CONTEXT_ENGINE_VERSION: ${{ github.event.inputs.expected_context_engine_version }}
+ EXPECTED_PARSING_VERSION: ${{ github.event.inputs.expected_parsing_version }}
+ CONFIRM_PUBLISH: ${{ github.event.inputs.confirm_publish }}
run: >-
python scripts/validate_python_release.py
- --publish-target "${{ github.event.inputs.publish_target }}"
- --channel "${{ github.event.inputs.channel }}"
- --expected-potpie-version "${{ github.event.inputs.expected_potpie_version }}"
- --expected-context-engine-version "${{ github.event.inputs.expected_context_engine_version }}"
- --expected-parsing-version "${{ github.event.inputs.expected_parsing_version }}"
- --confirm-publish "${{ github.event.inputs.confirm_publish }}"
+ --publish-target "$PUBLISH_TARGET"
+ --channel "$CHANNEL"
+ --expected-potpie-version "$EXPECTED_POTPIE_VERSION"
+ --expected-context-engine-version "$EXPECTED_CONTEXT_ENGINE_VERSION"
+ --expected-parsing-version "$EXPECTED_PARSING_VERSION"
+ --confirm-publish "$CONFIRM_PUBLISH"📝 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.
| - name: Validate release metadata | |
| id: validate | |
| run: >- | |
| python scripts/validate_python_release.py | |
| --publish-target "${{ github.event.inputs.publish_target }}" | |
| --channel "${{ github.event.inputs.channel }}" | |
| --expected-potpie-version "${{ github.event.inputs.expected_potpie_version }}" | |
| --expected-context-engine-version "${{ github.event.inputs.expected_context_engine_version }}" | |
| --expected-parsing-version "${{ github.event.inputs.expected_parsing_version }}" | |
| --confirm-publish "${{ github.event.inputs.confirm_publish }}" | |
| - name: Validate release metadata | |
| id: validate | |
| env: | |
| PUBLISH_TARGET: ${{ github.event.inputs.publish_target }} | |
| CHANNEL: ${{ github.event.inputs.channel }} | |
| EXPECTED_POTPIE_VERSION: ${{ github.event.inputs.expected_potpie_version }} | |
| EXPECTED_CONTEXT_ENGINE_VERSION: ${{ github.event.inputs.expected_context_engine_version }} | |
| EXPECTED_PARSING_VERSION: ${{ github.event.inputs.expected_parsing_version }} | |
| CONFIRM_PUBLISH: ${{ github.event.inputs.confirm_publish }} | |
| run: >- | |
| python scripts/validate_python_release.py | |
| --publish-target "$PUBLISH_TARGET" | |
| --channel "$CHANNEL" | |
| --expected-potpie-version "$EXPECTED_POTPIE_VERSION" | |
| --expected-context-engine-version "$EXPECTED_CONTEXT_ENGINE_VERSION" | |
| --expected-parsing-version "$EXPECTED_PARSING_VERSION" | |
| --confirm-publish "$CONFIRM_PUBLISH" |
🧰 Tools
🪛 zizmor (1.26.1)
[error] 83-83: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 84-84: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 85-85: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 86-86: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 87-87: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 88-88: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 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 @.github/workflows/release-python.yml around lines 79 - 88, The Validate
release metadata step is interpolating dispatch inputs directly into the shell
command, which can be unsafe. Move the github.event.inputs values into env on
the same step, then update the run command to pass only shell-expanded variables
to scripts/validate_python_release.py; keep the existing argument names but
reference the env vars instead of inline expressions. Use the Validate release
metadata step as the place to fix this and preserve the current validate script
invocation behavior.
Source: Linters/SAST tools
| - name: Smoke install and run CLI | ||
| env: | ||
| POTPIE_VERSION: ${{ needs.preflight.outputs.potpie_version }} | ||
| run: | | ||
| ls -la dist | ||
| python -m venv .release-smoke | ||
| .release-smoke/bin/python -m pip install --upgrade pip | ||
| .release-smoke/bin/python -m pip install --find-links dist "potpie==${POTPIE_VERSION}" | ||
| .release-smoke/bin/python -c "import parsing.parsing_rs" | ||
| PATH="$PWD/.release-smoke/bin:$PATH" potpie status |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Force the smoke test to install the built local artifacts.
Line 268 uses --find-links dist without constraining dependency resolution, so pip can still satisfy potpie-context-engine or potpie-parsing from PyPI instead of the artifacts built in this workflow. Pin and verify the three built package versions before publishing.
Proposed fix
env:
POTPIE_VERSION: ${{ needs.preflight.outputs.potpie_version }}
+ CONTEXT_ENGINE_VERSION: ${{ needs.preflight.outputs.context_engine_version }}
+ PARSING_VERSION: ${{ needs.preflight.outputs.parsing_version }}
run: |
ls -la dist
python -m venv .release-smoke
.release-smoke/bin/python -m pip install --upgrade pip
- .release-smoke/bin/python -m pip install --find-links dist "potpie==${POTPIE_VERSION}"
+ .release-smoke/bin/python -m pip install --find-links dist "potpie==${POTPIE_VERSION}"
+ .release-smoke/bin/python -m pip install --no-index --find-links dist --no-deps --force-reinstall \
+ "potpie==${POTPIE_VERSION}" \
+ "potpie-context-engine==${CONTEXT_ENGINE_VERSION}" \
+ "potpie-parsing==${PARSING_VERSION}"
+ .release-smoke/bin/python -m pip check
+ .release-smoke/bin/python - <<'PY'
+ import importlib.metadata as md
+ import os
+
+ expected = {
+ "potpie": os.environ["POTPIE_VERSION"],
+ "potpie-context-engine": os.environ["CONTEXT_ENGINE_VERSION"],
+ "potpie-parsing": os.environ["PARSING_VERSION"],
+ }
+ for name, version in expected.items():
+ actual = md.version(name)
+ assert actual == version, f"{name}: expected {version}, got {actual}"
+ PY
.release-smoke/bin/python -c "import parsing.parsing_rs"📝 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.
| - name: Smoke install and run CLI | |
| env: | |
| POTPIE_VERSION: ${{ needs.preflight.outputs.potpie_version }} | |
| run: | | |
| ls -la dist | |
| python -m venv .release-smoke | |
| .release-smoke/bin/python -m pip install --upgrade pip | |
| .release-smoke/bin/python -m pip install --find-links dist "potpie==${POTPIE_VERSION}" | |
| .release-smoke/bin/python -c "import parsing.parsing_rs" | |
| PATH="$PWD/.release-smoke/bin:$PATH" potpie status | |
| - name: Smoke install and run CLI | |
| env: | |
| POTPIE_VERSION: ${{ needs.preflight.outputs.potpie_version }} | |
| CONTEXT_ENGINE_VERSION: ${{ needs.preflight.outputs.context_engine_version }} | |
| PARSING_VERSION: ${{ needs.preflight.outputs.parsing_version }} | |
| run: | | |
| ls -la dist | |
| python -m venv .release-smoke | |
| .release-smoke/bin/python -m pip install --upgrade pip | |
| .release-smoke/bin/python -m pip install --find-links dist "potpie==${POTPIE_VERSION}" | |
| .release-smoke/bin/python -m pip install --no-index --find-links dist --no-deps --force-reinstall \ | |
| "potpie==${POTPIE_VERSION}" \ | |
| "potpie-context-engine==${CONTEXT_ENGINE_VERSION}" \ | |
| "potpie-parsing==${PARSING_VERSION}" | |
| .release-smoke/bin/python -m pip check | |
| .release-smoke/bin/python - <<'PY' | |
| import importlib.metadata as md | |
| import os | |
| expected = { | |
| "potpie": os.environ["POTPIE_VERSION"], | |
| "potpie-context-engine": os.environ["CONTEXT_ENGINE_VERSION"], | |
| "potpie-parsing": os.environ["PARSING_VERSION"], | |
| } | |
| for name, version in expected.items(): | |
| actual = md.version(name) | |
| assert actual == version, f"{name}: expected {version}, got {actual}" | |
| PY | |
| .release-smoke/bin/python -c "import parsing.parsing_rs" | |
| PATH="$PWD/.release-smoke/bin:$PATH" potpie status |
🤖 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 @.github/workflows/release-python.yml around lines 261 - 270, The smoke test
currently installs potpie with --find-links dist but can still resolve
potpie-context-engine and potpie-parsing from PyPI, so update the release-python
workflow’s Smoke install and run CLI step to explicitly install and pin the
three local built artifacts from dist using the preflight version output. Make
sure the workflow verifies the built wheel versions for potpie,
potpie-context-engine, and potpie-parsing before running potpie status, so the
smoke test only exercises the artifacts produced in this release job.
| def validate_pep440(packages: list[PackageInfo], channel: str) -> None: | ||
| for package in packages: | ||
| try: | ||
| version = package.parsed_version | ||
| except InvalidVersion as exc: | ||
| fail(f"{package.name} version {package.version!r} is not PEP 440: {exc}") | ||
| if version.local is not None: | ||
| fail(f"{package.name} version {package.version!r} must not use a local '+...' segment") | ||
|
|
||
| if channel == "beta": | ||
| if version.pre is None or version.pre[0] != "b": | ||
| fail(f"{package.name} must use a beta version like 1.2.0b1") | ||
| if "b" not in package.version.lower() or "beta" in package.version.lower(): | ||
| fail(f"{package.name} beta version must use compact bN syntax, not {package.version!r}") | ||
| elif channel == "rc": | ||
| if version.pre is None or version.pre[0] != "rc": | ||
| fail(f"{package.name} must use a release-candidate version like 1.2.0rc1") | ||
| elif channel == "final": | ||
| if version.is_prerelease or version.is_devrelease: | ||
| fail(f"{package.name} must use a final release version for channel=final") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
python - <<'PY'
from packaging.version import Version
for raw in ("1.2.0b1.dev1", "1.2.0rc1.dev1"):
version = Version(raw)
print(raw, "pre=", version.pre, "is_devrelease=", version.is_devrelease)
PYRepository: potpie-ai/potpie
Length of output: 250
Reject .devN versions for beta/rc channels. version.pre still matches 1.2.0b1.dev1 and 1.2.0rc1.dev1, so add a version.is_devrelease check before the channel-specific beta/rc validation.
🤖 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 `@scripts/validate_python_release.py` around lines 86 - 105, Reject .devN
versions in validate_pep440 by checking version.is_devrelease before the
beta/rc-specific pre-release validation. Update validate_pep440 in
scripts/validate_python_release.py so the PackageInfo.parsed_version handling
fails for beta and rc channels when a dev release is present, alongside the
existing version.pre checks, while leaving the final-channel logic unchanged.
Summary
potpie-context-engineand rootpotpie, plus a main orchestrator workflow forall,context-engine, orpotpie.LINEAR_CLIENT_IDandPOTPIE_GITHUB_CLIENT_ID; require them before TestPyPI/PyPI context-engine publishes.testpypiandpypienvironments.Closes #934
Verification
python3 -m py_compile scripts/validate_python_release.pyuv run --with packaging python scripts/validate_python_release.py --package context-engine --publish-target build-only --output-dir /tmp/potpie-release-context-checkuv run --with packaging python scripts/validate_python_release.py --package potpie --publish-target build-only --output-dir /tmp/potpie-release-potpie-checkgo run github.com/rhysd/actionlint/cmd/actionlint@latest .github/workflows/release-python.yml .github/workflows/release-context-engine.yml .github/workflows/release-potpie.ymluvx --with build --with twine python -m build --sdist --wheel --outdir /tmp/potpie-release-context-build potpie/context-engineuvx --with build --with twine python -m twine check /tmp/potpie-release-context-build/*uvx --with build --with twine python -m build --sdist --wheel --outdir /tmp/potpie-release-root-deps potpie/context-engineuvx --with build --with twine python -m build --sdist --wheel --outdir /tmp/potpie-release-root-build .uvx --with build --with twine python -m twine check /tmp/potpie-release-root-deps/* /tmp/potpie-release-root-build/*git log -1 --show-signature