Skip to content

Commit f674bab

Browse files
[CNSL-2134] Add pending deploy branch management to release workflow
After a successful release (tag creation), the workflow now automatically manages pending deploy branches: - Finds the most recent merged PR with a pending-deploy-YYYYMMDD-hhmmss head branch to identify what the last pending deploy branch was - Compares its timestamp with any current live pending deploy branch - Creates a new pending deploy branch if a newer one was already merged to main (indicating the current live branch is stale), or if none exists - Retargets all open PRs from old pending deploy branches to the current one. (As of now, workflow does not resolve conflicts caused by this.) This ensures that after each release, there's always a fresh pending deploy branch based on the latest main, and PRs are automatically pointed to the right target. Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
1 parent 7777b8d commit f674bab

2 files changed

Lines changed: 157 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ on:
55
branches: [main]
66

77
# contents:write is required for autotag-from-changelog to push tags.
8+
# pull-requests:write is required for retargeting PRs to pending deploy branches.
89
permissions:
910
contents: write
11+
pull-requests: write
1012

1113
jobs:
1214
release:
1315
runs-on: ubuntu-latest
16+
outputs:
17+
tag-created: ${{ steps.autotag.outputs.tag-created }}
1418
steps:
1519
- uses: actions/checkout@v6
1620
with:
@@ -35,3 +39,150 @@ jobs:
3539
gh api repos/cockroachdb/ccloud-private/dispatches \
3640
-f event_type=sdk-release \
3741
-f "client_payload[version]=${{ steps.autotag.outputs.tag }}"
42+
43+
manage-pending-deploy:
44+
needs: release
45+
if: needs.release.outputs.tag-created == 'true'
46+
runs-on: ubuntu-latest
47+
steps:
48+
- uses: actions/checkout@v6
49+
with:
50+
fetch-depth: 0
51+
52+
# Step 1: Determine the previous pending deploy branch timestamp from main
53+
# Find the most recent merged PR to main where the head branch was pending-deploy-YYYYMMDD-hhmmss
54+
- name: Find previous pending deploy branch from merged PRs
55+
id: previous
56+
env:
57+
GH_TOKEN: ${{ github.token }}
58+
run: |
59+
echo "Searching for previous pending deploy branch from merged PRs..."
60+
61+
# Fetch last 50 merged PRs to find the most recent pending deploy branch.
62+
# 50 should be sufficient given typical API change and SDK release cadence.
63+
previous_branch=$(gh pr list \
64+
--state merged \
65+
--base main \
66+
--limit 50 \
67+
--json headRefName,mergedAt \
68+
--jq '[.[] | select(.headRefName | test("^pending-deploy-[0-9]{8}-[0-9]{6}$"))] | sort_by(.mergedAt) | reverse | .[0].headRefName')
69+
70+
if [ -z "$previous_branch" ] || [ "$previous_branch" = "null" ]; then
71+
echo "No previous pending deploy branch found from merged PRs"
72+
echo "previous_branch_timestamp=" >> "$GITHUB_OUTPUT"
73+
else
74+
echo "Found previous pending deploy branch: $previous_branch"
75+
76+
# Extract timestamp from the branch name: pending-deploy-YYYYMMDD-hhmmss
77+
previous_branch_timestamp=$(echo "$previous_branch" | sed -E 's/^pending-deploy-([0-9]{8}-[0-9]{6})$/\1/' | tr -d '-')
78+
79+
echo "previous_branch_timestamp=$previous_branch_timestamp" >> "$GITHUB_OUTPUT"
80+
81+
echo " Timestamp: $previous_branch_timestamp"
82+
fi
83+
84+
# Step 2: Determine the current live pending deploy branch in the main repository
85+
# Look for live remote branches matching pending-deploy-YYYYMMDD-hhmmss
86+
# If multiple exist, select the one with the latest timestamp
87+
- name: Find current live pending deploy branch
88+
id: current
89+
run: |
90+
echo "Searching for live pending deploy branches in the main repository..."
91+
92+
# List all remote branches matching the pattern, sorted by timestamp descending
93+
current_branch=$(git ls-remote --heads origin | \
94+
grep -oE 'pending-deploy-[0-9]{8}-[0-9]{6}$' | \
95+
sort -r | \
96+
head -n 1)
97+
98+
if [ -z "$current_branch" ]; then
99+
echo "No live pending deploy branch found"
100+
echo "current_branch=" >> "$GITHUB_OUTPUT"
101+
echo "current_branch_timestamp=" >> "$GITHUB_OUTPUT"
102+
else
103+
echo "Found current live pending deploy branch: $current_branch"
104+
105+
# Extract timestamp
106+
current_branch_timestamp=$(echo "$current_branch" | sed -E 's/^pending-deploy-([0-9]{8}-[0-9]{6})$/\1/' | tr -d '-')
107+
108+
echo "current_branch=$current_branch" >> "$GITHUB_OUTPUT"
109+
echo "current_branch_timestamp=$current_branch_timestamp" >> "$GITHUB_OUTPUT"
110+
111+
echo " Timestamp: $current_branch_timestamp"
112+
fi
113+
114+
# Step 3: Decide which pending deploy branch should be used now
115+
# If previous timestamp >= current timestamp, create a new branch
116+
- name: Select pending deploy branch
117+
id: selected
118+
env:
119+
PREVIOUS_BRANCH_TIMESTAMP: ${{ steps.previous.outputs.previous_branch_timestamp }}
120+
CURRENT_BRANCH: ${{ steps.current.outputs.current_branch }}
121+
CURRENT_BRANCH_TIMESTAMP: ${{ steps.current.outputs.current_branch_timestamp }}
122+
run: |
123+
# Get current UTC timestamp in YYYYMMDD-hhmmss format
124+
current_timestamp=$(date -u +%Y%m%d-%H%M%S)
125+
echo "Current UTC timestamp: $current_timestamp"
126+
127+
# Decision logic: create new branch if previous >= current, otherwise use current
128+
if [ -z "$CURRENT_BRANCH" ]; then
129+
# No current live branch exists, create new
130+
echo "No current live branch exists, creating new branch..."
131+
selected_branch="pending-deploy-${current_timestamp}"
132+
needs_creation=true
133+
elif [ -n "$PREVIOUS_BRANCH_TIMESTAMP" ] && [ "$PREVIOUS_BRANCH_TIMESTAMP" -ge "$CURRENT_BRANCH_TIMESTAMP" ]; then
134+
# Previous timestamp >= current timestamp, create new branch
135+
echo "Previous timestamp ($PREVIOUS_BRANCH_TIMESTAMP) >= current timestamp ($CURRENT_BRANCH_TIMESTAMP), creating new branch..."
136+
selected_branch="pending-deploy-${current_timestamp}"
137+
needs_creation=true
138+
else
139+
# Use current live branch
140+
echo "Using current live branch"
141+
selected_branch="$CURRENT_BRANCH"
142+
needs_creation=false
143+
fi
144+
145+
echo "Selected pending deploy branch: $selected_branch"
146+
echo "Needs creation: $needs_creation"
147+
148+
echo "selected_branch=$selected_branch" >> "$GITHUB_OUTPUT"
149+
echo "needs_creation=$needs_creation" >> "$GITHUB_OUTPUT"
150+
151+
# Step 4: Ensure the selected pending deploy branch exists in the main repository
152+
# Create it from main if it doesn't already exist remotely
153+
- name: Create pending deploy branch if needed
154+
if: steps.selected.outputs.needs_creation == 'true'
155+
env:
156+
SELECTED_BRANCH: ${{ steps.selected.outputs.selected_branch }}
157+
run: |
158+
echo "Creating pending deploy branch: $SELECTED_BRANCH"
159+
160+
# Create the branch from main and push it to the main repository
161+
git checkout -b "$SELECTED_BRANCH" origin/main
162+
git push origin "$SELECTED_BRANCH"
163+
164+
echo "Branch $SELECTED_BRANCH created and pushed to origin"
165+
166+
# Step 5: Retarget open PRs from any pending deploy branch to the selected branch
167+
- name: Retarget open PRs
168+
env:
169+
GH_TOKEN: ${{ github.token }}
170+
SELECTED_BRANCH: ${{ steps.selected.outputs.selected_branch }}
171+
run: |
172+
echo "Looking for open PRs targeting pending deploy branches..."
173+
174+
# Find all open PRs and filter for those targeting pending-deploy-YYYYMMDD-hhmmss branches
175+
prs_to_retarget=$(gh pr list --state open --json number,baseRefName --jq '.[] | select(.baseRefName | test("^pending-deploy-[0-9]{8}-[0-9]{6}$")) | select(.baseRefName != "'$SELECTED_BRANCH'") | "\(.number):\(.baseRefName)"')
176+
177+
if [ -z "$prs_to_retarget" ]; then
178+
echo "No open PRs found targeting pending deploy branches"
179+
else
180+
echo "Found PRs to retarget to $SELECTED_BRANCH:"
181+
echo "$prs_to_retarget" | while IFS=: read -r pr_number base_branch; do
182+
echo " PR #$pr_number (from $base_branch)"
183+
gh pr edit "$pr_number" --base "$SELECTED_BRANCH"
184+
echo " Retargeted PR #$pr_number to $SELECTED_BRANCH"
185+
done
186+
187+
echo "All PRs retargeted successfully"
188+
fi

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added pending deploy branch management to release workflow to ensure automated
13+
PRs that remain open after an SDK release are retargeted to the latest pending
14+
deploy branch
15+
1016
## [7.1.0] - 2026-04-14
1117

1218
### Added

0 commit comments

Comments
 (0)