batch-deps-upgrade

star 237

Batch all open Dependabot dependency upgrade PRs into a single PR

XRPLF By XRPLF schedule Updated 5/26/2026

name: batch-deps-upgrade description: Batch all open Dependabot dependency upgrade PRs into a single PR disable-model-invocation: true

Batch all open Dependabot dependency upgrade PRs into a single PR for this repository.

Step 1: Discover

Run: gh pr list --repo XRPLF/xrpl-py --label dependencies --state open --limit 500 --json number,title,headRefName,body,url

Parse each PR to extract package names and versions. Dependabot PRs come in two formats:

  • Single-package PRs: title is bump <pkg> from <old> to <new> — parse from title
  • Grouped PRs: title is bump <pkg1> and <pkg2> with no versions — parse from PR body, which contains a structured list of package updates with version ranges

If any PR can't be parsed from either title or body, flag it for manual review. Build a table of all proposed upgrades. Report the table to the user before proceeding.

Step 2: Apply all upgrades

  1. Create a branch from main: deps/batch-deps-upgrade-YYYY-QN (use current year and quarter)
  2. Check for dependency conflicts before upgrading. For each proposed upgrade, review pyproject.toml constraints and run poetry show <pkg> to check if any other dependency pins a version range that would block the upgrade. Mark conflicts as Skipped (dependency conflict:
    ) and do not attempt them.
  3. For each remaining dependency, apply the upgrade:
    • Direct deps (listed in pyproject.toml under [tool.poetry.dependencies] or [tool.poetry.group.dev.dependencies]): update the version constraint in pyproject.toml to the new version using caret (^<new_version>), then run poetry update <pkg>. Always update pyproject.toml for direct deps — even if the current constraint already allows the new version — so the pinned minimum stays current.
    • Transitive deps (not in pyproject.toml): run poetry update <pkg> to update within the existing constraint range
  4. After all upgrades are applied, run poetry lock to regenerate poetry.lock. Do NOT delete poetry.lock and regenerate from scratch.
  5. Run poetry install to sync the virtual environment.
  6. Diff pyproject.toml and poetry.lock against main to classify each Dependabot PR as:
    • Upgraded: version changed
    • No-op: version was already current or newer
  7. If any upgrade changes the public API of the library (new errors, changed return types, removed functionality) and results in a breaking change, add an entry under ## [Unreleased] in CHANGELOG.md.
  8. Verify completeness: every PR from Step 1 must have a status (Upgraded, No-op, or Skipped). If any PR is unaccounted for, stop and report it before proceeding.

Step 3: Validate

Run the full validation suite across all Python versions from the CI matrix. Repeat until everything passes.

Determine Python versions

Read each workflow file under .github/workflows/ to determine the Python versions used:

  • .github/workflows/unit_test.yml — the unit-test job uses a matrix of Python versions; the lint-and-type-check job uses a single Python version (not a matrix)
  • .github/workflows/integration_test.yml — the integration-test job uses a matrix of Python versions
  • .github/workflows/faucet_test.yml — the faucet-test job uses a matrix of Python versions

Extract the exact Python versions from each workflow's matrix.python-version array (or the PYTHON_VERSION env var for lint). These versions are the source of truth for validation.

Switching between Python versions

To switch Python versions for testing, use pyenv and poetry:

pyenv install <version>    # install if not already present
pyenv local <version>      # set the local Python version
poetry env use python<version>  # point poetry to the correct interpreter
poetry install             # reinstall deps for this interpreter

Replace <version> with the target version (e.g. 3.10, 3.11, 3.12, 3.13, 3.14). After running all tests for one version, repeat these steps to switch to the next.

Validation order

Run validation in parallel across all Python versions from the unit test matrix to speed things up. For each Python version, create a separate working directory (e.g. using git worktree or by spawning parallel agents) so that each version's virtual environment does not interfere with the others.

For each Python version, run the following in order:

  1. Lint and type-check (only on the single lint Python version from the lint-and-type-check job):

    poetry run poe lint
    poetry run mypy --strict --implicit-reexport xrpl
    
  2. Unit tests:

    poetry run poe test_unit
    poetry run coverage report --fail-under=85
    
  3. Integration tests (requires a single shared xrpld Docker container — start it once before running integration tests for any Python version):

    • Pre-run cleanup: docker rm -f xrpld-service 2>/dev/null || true
    • Start the container:
      docker run \
        --detach \
        --publish 5005:5005 \
        --publish 6006:6006 \
        --volume "$PWD/.ci-config/:/etc/xrpld/" \
        --name xrpld-service \
        rippleci/xrpld:develop --standalone
      
    • Wait for port 6006 with a bounded timeout:
      SECONDS=0
      until nc -z localhost 6006 || [ $SECONDS -gt 120 ]; do sleep 2; done
      if ! nc -z localhost 6006; then
        echo "Error: xrpld did not start within 120s"
        docker logs xrpld-service
        exit 1
      fi
      
    • Run for each Python version:
      poetry run poe test_integration
      poetry run coverage report --fail-under=70
      
    • Stop container after all versions complete: docker logs xrpld-service && docker stop xrpld-service
  4. Faucet tests:

    poetry run poe test_faucet
    

Collect results from all parallel runs. All Python versions must pass.

Handling failures

If any step fails, attempt to fix the breaking change with code modifications before rolling back. Common patterns:

  • Type annotation changes: newer versions of type stubs or mypy may require updated annotations. Fix the annotations.
  • Deprecated API removals: if an upgraded dependency removes a previously deprecated function, update calls to use the replacement API.
  • Import path changes: some packages reorganize their module structure on major bumps. Update import statements.
  • Test compatibility: if a test utility changes behavior (e.g., aiounittest, coverage), update test configuration or code accordingly.

Only roll back and mark as Skipped if:

  • The fix requires a large-scale migration across the codebase
  • The upgrade is blocked by an external dependency constraint you cannot update

If a failure is traced to a specific dependency upgrade, revert that upgrade in pyproject.toml, re-run poetry lock && poetry install, mark it as Skipped, and re-run validation until green.

Step 4: Generate Outputs

After all upgrades are applied and validation passes, generate the following outputs:

4a. Code changes note

Write .claude/skills/batch-deps-upgrade/code-changes.md documenting every non-pyproject.toml source code change, explaining what broke, why, and the minimal fix applied.

4b. PR description

Write .claude/skills/batch-deps-upgrade/pr-description.md following the repo's PR template (.github/pull_request_template.md):

  • For "High Level Overview of Change", summarize the batch upgrade.
  • For "Context of Change", explain that this batches Dependabot PRs to reduce merge noise.
  • For "Type of Change", determine dynamically:
    • Check "Breaking change" ONLY if any upgrade visibly changes the library's public API (e.g., error messages, return types, removed functions). This aligns with whether a CHANGELOG.md entry was added in Step 2.7.
    • Otherwise, do not check any Type of Change — dependency upgrades are maintenance and don't fit "Refactor" (which means restructuring code without behavior change). Note in the PR body that the upgrade is maintenance.
  • For "Did you update CHANGELOG.md?", check "Yes" if an entry was added, otherwise check "No, this change does not impact library users".
  • Include a "Superseded Dependabot PRs" section with a table: PR (linked), Package, From, To, Status, MajorVersionUpgrade
    • Status values: Upgraded, No-op (reason), Skipped (dependency conflict / CI failure: error)
    • MajorVersionUpgrade: No if the major version number did not change. Otherwise Yes plus a link for each major version crossed. For example, 1.x → 3.x yields Yes ([v2](url), [v3](url)). Each link should point to the package's release notes or changelog for that major version. Verify each link returns HTTP 200 and has meaningful content (e.g., curl -sL -o /dev/null -w "%{http_code}" <url>); if a package doesn't publish per-version GitHub releases, fall back to the CHANGELOG file or the closest valid release tag.
  • For every major version upgrade, add a "Major version upgrade notes" section below the table. For each major-version package, include:
    • A link to the release notes
    • A brief summary of key changes (breaking changes, deprecations, new features)
    • An explanation of why no code changes were required, OR a summary of the code changes that were made. This helps reviewers understand the impact without having to read the full release notes themselves.
  • Closing instructions with two paragraphs:
    1. "After merging, close the following superseded PRs (Skipped ones remain open for future handling): #X, #Y, #Z" — list only Upgraded and No-op PRs.
    2. "The following PRs were Skipped and should remain open: #A (package-a), #B (package-b), ..." — annotate each with the package name. These stay open so Dependabot keeps rebasing them.
Install via CLI
npx skills add https://github.com/XRPLF/xrpl-py --skill batch-deps-upgrade
Repository Details
star Stars 237
call_split Forks 130
navigation Branch main
article Path SKILL.md
More from Creator