44 push :
55 branches : [main]
66
7- # contents:write is required for autotag-from-changelog to push tags.
87permissions :
9- contents : write
8+ contents : write # Push tags and create branches
9+ pull-requests : write # Retarget PRs to pending deploy branch
1010
1111jobs :
1212 release :
1313 runs-on : ubuntu-latest
14+ outputs :
15+ tag-created : ${{ steps.autotag.outputs.tag-created }}
1416 steps :
1517 - uses : actions/checkout@v6
1618 with :
@@ -28,10 +30,176 @@ jobs:
2830 env :
2931 GH_TOKEN : ${{ secrets.CCLOUD_PRIVATE_DISPATCH_PAT }}
3032 run : |
33+ source scripts/lib/actions-helpers.sh
34+
3135 if [ -z "$GH_TOKEN" ]; then
32- echo "::warning:: CCLOUD_PRIVATE_DISPATCH_PAT secret is not set . Skipping dispatch to ccloud-private for ${{ steps.autotag.outputs.tag }}."
36+ log_warning " CCLOUD_PRIVATE_DISPATCH_PAT secret is required . Skipping dispatch to ccloud-private for ${{ steps.autotag.outputs.tag }}."
3337 exit 0
3438 fi
3539 gh api repos/cockroachdb/ccloud-private/dispatches \
36- -f event_type=sdk-release \
37- -f "client_payload[version]=${{ steps.autotag.outputs.tag }}"
40+ --field event_type=sdk-release \
41+ --field "client_payload[version]=${{ steps.autotag.outputs.tag }}"
42+
43+ # After a successful release, this job ensures there's always a fresh pending deploy
44+ # branch ready for the next release cycle. It:
45+ # 1. Finds the most recently merged pending deploy branch (from PRs to main)
46+ # 2. Finds any existing live pending deploy branches
47+ # 3. Creates a new pending deploy branch if there are no live ones or if the live
48+ # ones are stale (associated with an older date than the last merged one)
49+ # 4. Retargets all open PRs to point to the current pending deploy branch
50+ manage-pending-deploy :
51+ needs : release
52+ if : needs.release.outputs.tag-created == 'true'
53+ runs-on : ubuntu-latest
54+ steps :
55+ - uses : actions/checkout@v6
56+ with :
57+ fetch-depth : 0
58+
59+ # Step 1: Determine the previous pending deploy branch timestamp from main
60+ # Find the most recent merged PR to main where the head branch was automation/pending-deploy-YYYYMMDD-hhmmss
61+ - name : Find previous pending deploy branch from merged PRs
62+ id : previous
63+ env :
64+ GH_TOKEN : ${{ github.token }}
65+ run : |
66+ source scripts/lib/actions-helpers.sh
67+
68+ log_info "Searching for previous pending deploy branch from merged PRs..."
69+
70+ # Fetch last 50 merged PRs to find the most recent pending deploy branch.
71+ # 50 should be sufficient given typical API change and SDK release cadence.
72+ previous_branch=$(gh pr list \
73+ --state merged \
74+ --base main \
75+ --limit 50 \
76+ --json headRefName,mergedAt \
77+ --jq '[.[] | select(.headRefName | test("^automation/pending-deploy-[0-9]{8}-[0-9]{6}$"))] | sort_by(.mergedAt) | reverse | .[0].headRefName')
78+
79+ if [ -z "$previous_branch" ] || [ "$previous_branch" = "null" ]; then
80+ log_info "No previous pending deploy branch found from merged PRs"
81+ set_output previous_branch_timestamp ""
82+ else
83+ log_info "Found previous pending deploy branch: $previous_branch"
84+
85+ # Extract timestamp from the branch name: automation/pending-deploy-YYYYMMDD-hhmmss
86+ previous_branch_timestamp=$(echo "$previous_branch" | sed --regexp-extended 's/^automation\/pending-deploy-([0-9]{8}-[0-9]{6})$/\1/' | tr --delete '-')
87+
88+ set_output previous_branch_timestamp "$previous_branch_timestamp"
89+
90+ log_info " Timestamp: $previous_branch_timestamp"
91+ fi
92+
93+ # Step 2: Determine the current live pending deploy branch in the main repository
94+ # Look for live remote branches matching automation/pending-deploy-YYYYMMDD-hhmmss
95+ # If multiple exist, select the one with the latest timestamp
96+ - name : Find current live pending deploy branch
97+ id : current
98+ run : |
99+ source scripts/lib/actions-helpers.sh
100+
101+ log_info "Searching for live pending deploy branches in the main repository..."
102+
103+ # List all remote branches matching the pattern, sorted by timestamp descending
104+ current_branch=$(git ls-remote --heads origin | \
105+ grep --only-matching --extended-regexp 'automation/pending-deploy-[0-9]{8}-[0-9]{6}$' | \
106+ sort --reverse | \
107+ head --lines=1)
108+
109+ if [ -z "$current_branch" ]; then
110+ log_info "No live pending deploy branch found"
111+ set_output current_branch ""
112+ set_output current_branch_timestamp ""
113+ else
114+ log_info "Found current live pending deploy branch: $current_branch"
115+
116+ # Extract timestamp
117+ current_branch_timestamp=$(echo "$current_branch" | sed --regexp-extended 's/^automation\/pending-deploy-([0-9]{8}-[0-9]{6})$/\1/' | tr --delete '-')
118+
119+ set_output current_branch "$current_branch"
120+ set_output current_branch_timestamp "$current_branch_timestamp"
121+
122+ log_info " Timestamp: $current_branch_timestamp"
123+ fi
124+
125+ # Step 3: Decide which pending deploy branch should be used now
126+ # If previous timestamp >= current timestamp, create a new branch
127+ - name : Select pending deploy branch
128+ id : selected
129+ env :
130+ PREVIOUS_BRANCH_TIMESTAMP : ${{ steps.previous.outputs.previous_branch_timestamp }}
131+ CURRENT_BRANCH : ${{ steps.current.outputs.current_branch }}
132+ CURRENT_BRANCH_TIMESTAMP : ${{ steps.current.outputs.current_branch_timestamp }}
133+ run : |
134+ source scripts/lib/actions-helpers.sh
135+
136+ # Get current UTC timestamp in YYYYMMDD-hhmmss format
137+ current_timestamp=$(date --utc +%Y%m%d-%H%M%S)
138+ log_info "Current UTC timestamp: $current_timestamp"
139+
140+ # Decision logic: create new branch if previous >= current, otherwise use current
141+ if [ -z "$CURRENT_BRANCH" ]; then
142+ # No current live branch exists, create new
143+ log_info "No current live branch exists, creating new branch..."
144+ selected_branch="automation/pending-deploy-${current_timestamp}"
145+ needs_creation=true
146+ elif [ -n "$PREVIOUS_BRANCH_TIMESTAMP" ] && [ "$PREVIOUS_BRANCH_TIMESTAMP" -ge "$CURRENT_BRANCH_TIMESTAMP" ]; then
147+ # Previous timestamp >= current timestamp, create new branch
148+ log_info "Previous timestamp ($PREVIOUS_BRANCH_TIMESTAMP) >= current timestamp ($CURRENT_BRANCH_TIMESTAMP), creating new branch..."
149+ selected_branch="automation/pending-deploy-${current_timestamp}"
150+ needs_creation=true
151+ else
152+ # Use current live branch
153+ log_info "Using current live branch"
154+ selected_branch="$CURRENT_BRANCH"
155+ needs_creation=false
156+ fi
157+
158+ log_info "Selected pending deploy branch: $selected_branch"
159+ log_info "Needs creation: $needs_creation"
160+
161+ set_output selected_branch "$selected_branch"
162+ set_output needs_creation "$needs_creation"
163+
164+ # Step 4: Ensure the selected pending deploy branch exists in the main repository
165+ # Create it from main if it doesn't already exist remotely
166+ - name : Create pending deploy branch if needed
167+ if : steps.selected.outputs.needs_creation == 'true'
168+ env :
169+ SELECTED_BRANCH : ${{ steps.selected.outputs.selected_branch }}
170+ run : |
171+ source scripts/lib/actions-helpers.sh
172+
173+ log_info "Creating pending deploy branch: $SELECTED_BRANCH"
174+
175+ # Create the branch from main and push it to the main repository
176+ git switch --create "$SELECTED_BRANCH" origin/main
177+ git push origin "$SELECTED_BRANCH"
178+
179+ log_info "Branch $SELECTED_BRANCH created and pushed to origin"
180+
181+ # Step 5: Retarget open PRs from any pending deploy branch to the selected branch
182+ - name : Retarget open PRs
183+ env :
184+ GH_TOKEN : ${{ github.token }}
185+ SELECTED_BRANCH : ${{ steps.selected.outputs.selected_branch }}
186+ run : |
187+ source scripts/lib/actions-helpers.sh
188+
189+ log_info "Looking for open PRs targeting pending deploy branches..."
190+
191+ # Find all open PRs and filter for those targeting automation/pending-deploy-YYYYMMDD-hhmmss branches
192+ prs_to_retarget=$(gh pr list --state open --json number,baseRefName --jq '.[] | select(.baseRefName | test("^automation/pending-deploy-[0-9]{8}-[0-9]{6}$")) | select(.baseRefName != "'$SELECTED_BRANCH'") | "\(.number):\(.baseRefName)"')
193+
194+ if [ -z "$prs_to_retarget" ]; then
195+ log_info "No open PRs found targeting pending deploy branches"
196+ else
197+ log_info "Found PRs to retarget to $SELECTED_BRANCH:"
198+ echo "$prs_to_retarget" | while IFS=: read -r pr_number base_branch; do
199+ log_info " PR #$pr_number (from $base_branch)"
200+ gh pr edit "$pr_number" --base "$SELECTED_BRANCH"
201+ log_info " Retargeted PR #$pr_number to $SELECTED_BRANCH"
202+ done
203+
204+ log_info "All PRs retargeted successfully"
205+ fi
0 commit comments