|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Check if a Python package has a newer version on PyPI than what's |
| 4 | +# locked in uv.lock. If so, upgrade the lockfile and open a PR. |
| 5 | +# |
| 6 | +# Usage: ./update-package.sh <package-name> |
| 7 | +# |
| 8 | +# Requires: uv, gh (GitHub CLI), curl, jq, git |
| 9 | +# Environment: GH_TOKEN must be set for gh CLI |
| 10 | + |
| 11 | +set -euo pipefail |
| 12 | + |
| 13 | +PACKAGE="${1:?Usage: update-package.sh <package-name>}" |
| 14 | + |
| 15 | +# 1. Get current locked version from uv.lock |
| 16 | +CURRENT=$(grep -A1 "^name = \"${PACKAGE}\"$" uv.lock | grep 'version' | head -1 | sed 's/.*"\(.*\)"/\1/') |
| 17 | +if [[ -z "$CURRENT" ]]; then |
| 18 | + echo "ERROR: Package '${PACKAGE}' not found in uv.lock" |
| 19 | + exit 1 |
| 20 | +fi |
| 21 | +echo "Current locked version: ${PACKAGE}==${CURRENT}" |
| 22 | + |
| 23 | +# 2. Get latest version from PyPI |
| 24 | +LATEST=$(curl -sf "https://pypi.org/pypi/${PACKAGE}/json" | jq -r .info.version) |
| 25 | +if [[ -z "$LATEST" ]]; then |
| 26 | + echo "ERROR: Could not fetch latest version for '${PACKAGE}' from PyPI" |
| 27 | + exit 1 |
| 28 | +fi |
| 29 | +echo "Latest PyPI version: ${PACKAGE}==${LATEST}" |
| 30 | + |
| 31 | +# 3. Compare |
| 32 | +if [[ "$CURRENT" == "$LATEST" ]]; then |
| 33 | + echo "Already up to date. Nothing to do." |
| 34 | + exit 0 |
| 35 | +fi |
| 36 | +echo "Update available: ${CURRENT} -> ${LATEST}" |
| 37 | + |
| 38 | +# 4. Check if a PR already exists for this package+version |
| 39 | +EXISTING_PR=$(gh pr list --search "in:title update ${PACKAGE} to ${LATEST}" --state open --json number --jq '.[0].number' 2>/dev/null || true) |
| 40 | +if [[ -n "$EXISTING_PR" ]]; then |
| 41 | + echo "PR #${EXISTING_PR} already exists for this update. Skipping." |
| 42 | + exit 0 |
| 43 | +fi |
| 44 | + |
| 45 | +# 5. Configure git author |
| 46 | +git config user.name "github-actions[bot]" |
| 47 | +git config user.email "github-actions[bot]@users.noreply.github.com" |
| 48 | + |
| 49 | +# 6. Update pinned version in pyproject.toml and upgrade lockfile |
| 50 | +echo "Updating ${PACKAGE} pin in pyproject.toml: ==${CURRENT} -> ==${LATEST}" |
| 51 | +sed -i "s/\"${PACKAGE}==${CURRENT}\"/\"${PACKAGE}==${LATEST}\"/" pyproject.toml |
| 52 | + |
| 53 | +echo "Running: uv lock --upgrade-package ${PACKAGE}" |
| 54 | +uv lock --upgrade-package "${PACKAGE}" |
| 55 | + |
| 56 | +if git diff --quiet uv.lock pyproject.toml; then |
| 57 | + echo "No changes after upgrade. Nothing to do." |
| 58 | + exit 0 |
| 59 | +fi |
| 60 | + |
| 61 | +# 7. Create branch, commit, push, open PR |
| 62 | +BRANCH="auto/update-${PACKAGE}-${LATEST}" |
| 63 | +git checkout -b "$BRANCH" |
| 64 | +git add uv.lock pyproject.toml |
| 65 | +git commit -m "chore(deps): update ${PACKAGE} to ${LATEST}" |
| 66 | +git push -u origin "$BRANCH" |
| 67 | + |
| 68 | +gh pr create \ |
| 69 | + --title "chore(deps): update ${PACKAGE} to ${LATEST}" \ |
| 70 | + --body "Update ${PACKAGE} to ${LATEST}" |
| 71 | + |
| 72 | +echo "PR created for ${PACKAGE} ${CURRENT} -> ${LATEST}" |
0 commit comments