.github/workflows/bump_uv_pin.yml YAML 206 lines View on github.com → Search inside
1# Monthly bump of the uv pin in `.github/actions/uv_setup/action.yml`.2#3# We pin uv (rather than letting setup-uv resolve latest) because4# `releases.astral.sh` lags GitHub Releases on new uv versions, causing CI5# to flap on fresh-release days. This workflow keeps the pin fresh without6# exposing that race.7#8# Dependabot's `github-actions` ecosystem only updates `uses:` SHA pins, not9# the `UV_VERSION` env value the action passes to `astral-sh/setup-uv`, so we10# open the PR ourselves. Idempotent: if a PR for the target version already11# exists, the workflow exits without creating a duplicate.1213name: "Bump uv pin"1415on:16  schedule:17    - cron: "0 9 1 * *"18  workflow_dispatch:1920permissions:21  contents: read2223concurrency:24  group: bump-uv-pin25  cancel-in-progress: false2627jobs:28  bump:29    if: github.repository_owner == 'langchain-ai'30    name: "Open PR if uv has a newer release"31    runs-on: ubuntu-latest32    permissions:33      contents: write34      pull-requests: write35    steps:36      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v63738      - name: Resolve current and latest uv versions39        id: versions40        env:41          GH_TOKEN: ${{ github.token }}42        run: |43          set -euo pipefail44          action_file=".github/actions/uv_setup/action.yml"45          current=$(grep -oE 'UV_VERSION: "[0-9]+\.[0-9]+\.[0-9]+"' "$action_file" \46            | sed -E 's/UV_VERSION: "([^"]+)"/\1/' | head -n1)47          latest=$(gh api repos/astral-sh/uv/releases/latest --jq .tag_name)48          semver='^[0-9]+\.[0-9]+\.[0-9]+$'49          if [[ ! "$current" =~ $semver ]]; then50            echo "::error::Could not parse current uv pin from $action_file (got '$current')"51            exit 152          fi53          if [[ ! "$latest" =~ $semver ]]; then54            echo "::error::Unexpected uv tag from GitHub API (got '$latest')"55            exit 156          fi57          echo "current=$current" >> "$GITHUB_OUTPUT"58          echo "latest=$latest" >> "$GITHUB_OUTPUT"59          echo "branch=chore/bump-uv-$latest" >> "$GITHUB_OUTPUT"60          echo "Current pin: $current"61          echo "Latest uv:   $latest"6263      - name: Log if already up to date64        # The actual skip is implemented by the `if:` guards on every65        # subsequent step; this step only emits a log line so the run66        # history shows why no PR was opened.67        if: steps.versions.outputs.current == steps.versions.outputs.latest68        run: echo "uv pin already at ${{ steps.versions.outputs.latest }}; nothing to do."6970      - name: Skip if PR already open for this version71        id: existing72        if: steps.versions.outputs.current != steps.versions.outputs.latest73        env:74          GH_TOKEN: ${{ github.token }}75          BRANCH: ${{ steps.versions.outputs.branch }}76        run: |77          set -euo pipefail78          count=$(gh pr list --head "$BRANCH" --state open --json number --jq 'length')79          echo "count=$count" >> "$GITHUB_OUTPUT"80          if [ "$count" -gt 0 ]; then81            echo "Open PR already exists for $BRANCH; skipping."82          fi8384      - name: Wait for astral mirror to replicate85        id: mirror86        if: steps.versions.outputs.current != steps.versions.outputs.latest && steps.existing.outputs.count == '0'87        env:88          LATEST: ${{ steps.versions.outputs.latest }}89        run: |90          set -euo pipefail91          # The mirror can lag GitHub Releases. If it hasn't replicated yet,92          # defer the bump rather than landing a pin that races the mirror93          # on every CI run. We probe several arches because partial94          # replication (linux ready, macOS/aarch64 not) would still race95          # CI on other runners.96          assets=(97            "uv-x86_64-unknown-linux-gnu.tar.gz"98            "uv-aarch64-unknown-linux-gnu.tar.gz"99            "uv-x86_64-apple-darwin.tar.gz"100            "uv-aarch64-apple-darwin.tar.gz"101          )102          ready=true103          for asset in "${assets[@]}"; do104            url="https://releases.astral.sh/github/uv/releases/download/${LATEST}/${asset}"105            # `curl -sI` returns nothing on stderr at -s; capture exit code so a106            # permanently broken DNS/TLS path is surfaced instead of collapsing107            # to an opaque "000".108            set +e109            status=$(curl -sIo /dev/null -w '%{http_code}' --max-time 30 "$url" 2>/tmp/curl.err)110            curl_rc=$?111            set -e112            echo "Mirror HEAD $url -> HTTP $status (curl exit=$curl_rc)"113            if [ "$status" != "200" ]; then114              ready=false115              if [ "$curl_rc" -ne 0 ]; then116                echo "::warning::curl failed for $asset (exit=$curl_rc): $(cat /tmp/curl.err 2>/dev/null || true)"117              else118                echo "::warning::astral mirror has not replicated $asset for uv $LATEST yet (HTTP $status)."119              fi120            fi121          done122          if [ "$ready" = "true" ]; then123            echo "ready=true" >> "$GITHUB_OUTPUT"124          else125            echo "ready=false" >> "$GITHUB_OUTPUT"126            echo "::warning::Deferring uv bump to $LATEST until all probed arches are mirrored."127          fi128129      - name: Open bump PR130        if: steps.versions.outputs.current != steps.versions.outputs.latest && steps.existing.outputs.count == '0' && steps.mirror.outputs.ready == 'true'131        env:132          GH_TOKEN: ${{ github.token }}133          CURRENT: ${{ steps.versions.outputs.current }}134          LATEST: ${{ steps.versions.outputs.latest }}135          BRANCH: ${{ steps.versions.outputs.branch }}136          DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}137        run: |138          set -euo pipefail139          action_file=".github/actions/uv_setup/action.yml"140141          # `grep -c` returns 1 on no-match and 2 on read errors. We want142          # "no match" surfaced as the explicit count-of-zero check below;143          # read errors must abort. Capture the exit code separately so144          # `set -e` doesn't swallow either case.145          set +e146          before=$(grep -cE "UV_VERSION: \"${CURRENT}\"" "$action_file")147          before_rc=$?148          set -e149          if [ "$before_rc" -gt 1 ]; then150            echo "::error::grep read error on $action_file (exit=$before_rc)"151            exit 1152          fi153          if [ "$before" -ne 1 ]; then154            echo "::error::Expected exactly 1 'UV_VERSION: \"$CURRENT\"' in $action_file, found $before"155            exit 1156          fi157          sed -i -E "s/UV_VERSION: \"${CURRENT}\"/UV_VERSION: \"${LATEST}\"/" "$action_file"158          set +e159          after=$(grep -cE "UV_VERSION: \"${LATEST}\"" "$action_file")160          after_rc=$?161          set -e162          if [ "$after_rc" -gt 1 ]; then163            echo "::error::grep read error on $action_file (exit=$after_rc)"164            exit 1165          fi166          if [ "$after" -ne 1 ]; then167            echo "::error::Expected exactly 1 'UV_VERSION: \"$LATEST\"' after sed, found $after"168            exit 1169          fi170          if git diff --quiet "$action_file"; then171            echo "No changes after sed; bailing out (current=$CURRENT, latest=$LATEST)."172            exit 1173          fi174175          # Reuse-or-recreate orphan branch from a prior run that pushed176          # but failed before `gh pr create` (no open PR sits on it).177          # The delete can race a concurrent run (manual workflow_dispatch178          # firing while the cron is mid-flight, since concurrency group179          # does not cancel-in-progress); fall through with a warning so a180          # losing race does not kill an otherwise-clean job mid-state.181          if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then182            echo "::warning::Branch $BRANCH exists on origin without an open PR; deleting before recreating."183            if ! git push origin --delete "$BRANCH"; then184              echo "::warning::Delete of $BRANCH failed (concurrent run, or branch already gone); the subsequent push will surface any real conflict."185            fi186          fi187188          git config --local user.name "github-actions[bot]"189          git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"190          git checkout -b "$BRANCH"191          git add "$action_file"192          git commit -m "chore(deps): bump uv to $LATEST"193          git push --set-upstream origin "$BRANCH"194195          body_file="$(mktemp)"196          {197            printf 'Bumps the uv pin in `.github/actions/uv_setup/action.yml` from `%s` to [`%s`](https://github.com/astral-sh/uv/releases/tag/%s).\n\n' "$CURRENT" "$LATEST" "$LATEST"198            printf 'Opened automatically by `bump_uv_pin.yml`. Mirror availability on `releases.astral.sh` was verified before this PR was created, so CI should not race the fallback.\n'199          } > "$body_file"200201          gh pr create \202            --head "$BRANCH" \203            --base "$DEFAULT_BRANCH" \204            --title "chore(deps): bump uv to $LATEST" \205            --body-file "$body_file"

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.