name: Auto-retarget on: pull_request_target: types: [opened, synchronize, reopened] branches: [main] permissions: {} jobs: retarget: if: > github.repository_owner == 'better-auth' && !startsWith(github.event.pull_request.head.ref, 'changeset-release/') && github.event.pull_request.head.ref != 'next' && github.actor != 'github-actions[bot]' && github.actor != 'better-release[bot]' runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - name: Generate App Token id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 if: vars.RELEASE_APP_ID != '' with: app-id: ${{ vars.RELEASE_APP_ID }} private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} - name: Detect max bump type from changesets id: bump env: GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | MAX="patch" FILES=$(gh pr diff "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --name-only | grep '^\.changeset/.*\.md$' | grep -v 'README.md' || true) if [ -z "$FILES" ]; then echo "No changeset files in PR" echo "max=none" >> "$GITHUB_OUTPUT" exit 0 fi while IFS= read -r f; do [ -z "$f" ] && continue CONTENT=$(gh api "repos/$GITHUB_REPOSITORY/contents/$f?ref=${HEAD_SHA}" --jq '.content' | base64 -d 2>/dev/null || true) [ -z "$CONTENT" ] && continue BUMPS=$(echo "$CONTENT" | sed -n '/^---$/,/^---$/p' | grep -oE '"[^"]+"\s*:\s*(major|minor|patch)' | grep -oE '(major|minor|patch)$' | sort -u) if echo "$BUMPS" | grep -q "major"; then MAX="major" break fi if echo "$BUMPS" | grep -q "minor"; then MAX="minor" fi done <<< "$FILES" echo "max=$MAX" >> "$GITHUB_OUTPUT" - name: Check next branch exists if: steps.bump.outputs.max == 'minor' || steps.bump.outputs.max == 'major' id: next-check env: GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} run: | if gh api "repos/$GITHUB_REPOSITORY/branches/next" --silent 2>/dev/null; then echo "exists=true" >> "$GITHUB_OUTPUT" else echo "exists=false" >> "$GITHUB_OUTPUT" echo "::warning::next branch does not exist. Cannot retarget." fi - name: Retarget PR to next if: (steps.bump.outputs.max == 'minor' || steps.bump.outputs.max == 'major') && steps.next-check.outputs.exists == 'true' env: GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} MAX_BUMP: ${{ steps.bump.outputs.max }} run: | gh pr edit "$PR_NUMBER" --base next --repo "$GITHUB_REPOSITORY" gh pr edit "$PR_NUMBER" --add-label "retargeted-to-next" --repo "$GITHUB_REPOSITORY" || true gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body \ "This PR's base branch was automatically changed from \`main\` to \`next\` because its changeset requests a **${MAX_BUMP}** bump. \`main\` accepts patch changes. Minor and major changes are tested on \`next\` before promotion to stable."