Conversation
Use exact downstream pins, preserve the OpenHands lockfile Poetry version, and migrate SDK skill imports in generated PRs. Co-authored-by: openhands <openhands@all-hands.dev>
Python API breakage checks — ✅ PASSEDResult: ✅ PASSED |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
all-hands-bot
left a comment
There was a problem hiding this comment.
LGTM! 🎯
Solid improvements to the version bump workflow:
- Dynamic Poetry version matching prevents lockfile generator mismatches
- Exact pins (
==) + pyproject-fmt config ensure patch versions survive formatting - Import migration handles SDK 1.21.0+ changes automatically
- Selective staging is much safer than
git add .
Error handling and idempotency look good.
all-hands-bot
left a comment
There was a problem hiding this comment.
✅ QA Report: PASS
All workflow improvements verified through local simulation of bash script logic and YAML validation.
Does this PR achieve its stated goal?
Yes. This PR successfully improves the SDK version bump workflow by:
- Detecting and using the target repo's Poetry version from poetry.lock (preventing lockfile incompatibility)
- Applying exact version pins (
==1.21.0instead of1.21.0) to prevent Poetry from resolving to newer versions - Configuring pyproject-fmt to preserve full version strings (preventing
1.21.0→1.21shortening) - Migrating legacy SDK skill imports (
openhands.sdk.context.skills→openhands.sdk.skills) - Staging only expected files instead of
git add .(preventing accidental commits) - Correcting the repo name from
All-Hands-AI/OpenHandstoOpenHands/OpenHands
Each improvement was tested through local simulation. The bash script logic is sound, YAML syntax is valid, and all sed/grep operations produce correct output.
| Phase | Result |
|---|---|
| Environment Setup | ✅ Checked out PR branch, validated YAML syntax |
| CI Status | ✅ All checks passing (29/29 pass, 1 pending QA) |
| Functional Verification | ✅ All 6 workflow improvements verified through local simulation |
Functional Verification
Test 1: Poetry Version Detection from Lockfile
Baseline: Before this PR, Poetry 2.3.3 was installed globally regardless of the target repo's lockfile version, potentially causing lockfile regeneration incompatibilities.
Test: Simulated the new Poetry version extraction logic:
POETRY_VERSION=$(sed -n -E 's/^# This file is automatically @generated by Poetry ([^ ]+) and should not be changed by hand\.$/\1/p' test_poetry.lock)
echo "Extracted Poetry version: '$POETRY_VERSION'"Result:
Extracted Poetry version: '1.8.5'
Interpretation: The sed pattern correctly extracts the Poetry version from the lockfile header. The workflow will now install the exact Poetry version used by the target repo, ensuring lockfile compatibility.
Test 2: Exact Version Pins with ==
Baseline: The old sed commands used bare version strings ("1.21.0"):
sed -i -E 's/^(openhands-sdk = )"[^"]*"/\1"1.21.0"/' pyproject.tomlThis allowed Poetry to interpret "1.21.0" as a caret constraint (^1.21.0), potentially resolving to 1.21.1 or 1.22.0.
Test: Compared old vs. new sed commands:
# OLD:
sed -i -E 's/^(openhands-sdk = )"[^"]*"/\1"1.21.0"/' pyproject.toml
# Result: openhands-sdk = "1.21.0"
# NEW:
sed -i -E 's/^(openhands-sdk = )"[^"]*"/\1"==1.21.0"/' pyproject.toml
# Result: openhands-sdk = "==1.21.0"Result:
OLD: openhands-sdk = "1.21.0"
NEW: openhands-sdk = "==1.21.0"
Interpretation: The new approach correctly adds == to create exact pins, preventing Poetry from resolving to newer versions.
Test 3: pyproject-fmt Configuration for Full Version Preservation
Baseline: Before this PR, pyproject-fmt would shorten 1.21.0 to 1.21 in the formatted output, losing patch version precision.
Test: Simulated adding the --keep-full-version argument to the pre-commit config:
if ! grep -q "args: \\[--keep-full-version\\]" test_pre_commit.yaml; then
sed -i '/^[[:space:]]*- id: pyproject-fmt[[:space:]]*$/a\ args: [--keep-full-version]' test_pre_commit.yaml
fiResult:
hooks:
- id: pyproject-fmt
args: [--keep-full-version]
additional_dependencies: ["tox>=4.24.1"]Interpretation: The sed command correctly inserts the args line after the id: pyproject-fmt line, configuring pyproject-fmt to preserve full version strings like 1.21.0 instead of shortening to 1.21.
Test 4: SDK Skill Import Migration
Baseline: SDK 1.21.0 moved skills exports from openhands.sdk.context.skills to openhands.sdk.skills. The OpenHands repo may still use the old import paths.
Test: Simulated finding and migrating old imports:
# Find files with old imports
mapfile -t SDK_IMPORT_FILES < <(grep -RIl "openhands\\.sdk\\.context\\.skills" openhands tests || true)
# Migrate imports
for file in "${SDK_IMPORT_FILES[@]}"; do
sed -i 's/openhands\.sdk\.context\.skills/openhands.sdk.skills/g' "$file"
doneBefore:
from openhands.sdk.context.skills import load_skill
from openhands.sdk.context.skills.manager import SkillManager
import openhands.sdk.context.skills as skills_moduleAfter:
from openhands.sdk.skills import load_skill
from openhands.sdk.skills.manager import SkillManager
import openhands.sdk.skills as skills_moduleInterpretation: The grep + sed pipeline correctly identifies files with legacy imports and updates all occurrences to the new path. The workflow makes this idempotent so reruns don't fail if the migration was already applied.
Test 5: Selective Git Staging
Baseline: The old workflow used git add . which would stage ALL modified files, including unintended changes like temporary files or unrelated edits.
Test: Compared git add . vs. selective staging:
# OLD: git add .
# Result: Stages ALL 5 modified files including extra_file.txt
# NEW: Selective staging
git add pyproject.toml poetry.lock sandbox_spec_service.py test_pre_commit.yaml
# Result: Stages only 4 expected files, excludes extra_file.txtResult:
OLD approach stages: pyproject.toml, poetry.lock, sandbox_spec_service.py, test_pre_commit.yaml, extra_file.txt (5 files)
NEW approach stages: pyproject.toml, poetry.lock, sandbox_spec_service.py, test_pre_commit.yaml (4 files)
Interpretation: The new approach only stages the files that the workflow intentionally modified, preventing accidental commits of unrelated changes.
Test 6: Repo Name Correction and Message Updates
Verification:
- ✅ All references to
All-Hands-AI/OpenHandschanged toOpenHands/OpenHands - ✅ Global Poetry installation step removed
- ✅ Per-repo Poetry installation added with version detection
- ✅ Commit messages updated to mention "exact pins" and "SDK skill import paths"
- ✅ PR descriptions updated to mention "with exact pins" and "target repo's Poetry version"
Interpretation: The repo name is now correct, and all user-facing messages accurately describe the improvements made in this PR.
Issues Found
None.
The version bump workflow should only care about updating dependency versions and regenerating lockfiles, not migrating import paths. Version-specific export changes are handled manually when needed. Co-authored-by: openhands <openhands@all-hands.dev>
Summary
Validation
Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.13-nodejs22-slimgolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:852d86e-pythonRun
All tags pushed for this build
About Multi-Architecture Support
852d86e-python) is a multi-arch manifest supporting both amd64 and arm64852d86e-python-amd64) are also available if needed