Skip to content

Commit beaf529

Browse files
fix: reorder release-please jobs and fix enhance-release-pr workflow (#15)
- Reorder jobs: handle-untagged-releases now runs FIRST before release-please This prevents Release Please from aborting with 'untagged PRs outstanding' - Replace grep -oP with sed -E for portability (BSD grep doesn't support -P) - Fix enhance-release-pr: Use github.event.pull_request.head.ref instead of github.head_ref - Add workflow_dispatch trigger to enhance-release-pr for manual triggering - Improve version detection with multi-method fallback (base branch manifest, GitHub releases, Git tags) - Update verify-release to check both release-please and handle-untagged-releases outputs
1 parent 856c50c commit beaf529

File tree

2 files changed

+143
-64
lines changed

2 files changed

+143
-64
lines changed

.github/workflows/enhance-release-pr.yml

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
types: [opened, synchronize, reopened]
66
branches:
77
- main
8+
workflow_dispatch: # Added to allow manual triggering
89

910
# Cancel in-progress runs when a new commit is pushed to the same PR
1011
concurrency:
@@ -20,20 +21,21 @@ permissions:
2021
jobs:
2122
enhance-release-pr:
2223
name: 🤖 Claude AI Enhancement
23-
if: startsWith(github.head_ref, 'release-please--')
24+
if: startsWith(github.event.pull_request.head.ref, 'release-please--')
2425
runs-on: ubuntu-latest
2526
steps:
2627
- name: 📥 Checkout PR Branch
2728
uses: actions/checkout@v5
2829
with:
29-
ref: ${{ github.head_ref }}
30+
ref: ${{ github.event.pull_request.head.ref }}
3031
fetch-depth: 0
3132
token: ${{ secrets.GITHUB_TOKEN }}
3233

3334
- name: 🏷️ Extract Version from PR Title
3435
id: version
3536
run: |
36-
VERSION=$(echo "${{ github.event.pull_request.title }}" | grep -oP '\d+\.\d+\.\d+' || echo "")
37+
# Extract version using sed -E (extended regex, more portable than grep -P)
38+
VERSION=$(echo "${{ github.event.pull_request.title }}" | sed -E 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/' || echo "")
3739
if [ -z "$VERSION" ]; then
3840
echo "⚠️ Could not extract version from PR title"
3941
echo "skip=true" >> $GITHUB_OUTPUT
@@ -46,8 +48,68 @@ jobs:
4648
- name: ⬅️ Get Previous Version
4749
id: prev_version
4850
if: steps.version.outputs.skip != 'true'
51+
env:
52+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4953
run: |
50-
PREV=$(cat .release-please-manifest.json | grep -oP '"\.: "\K[^"]+' || echo "0.0.0")
54+
echo "🔍 Determining previous version..."
55+
56+
# Method 1: Try to get from base branch's manifest (most reliable)
57+
# Uses GitHub API to read .release-please-manifest.json from the base branch
58+
echo "📋 Checking base branch (${{ github.event.pull_request.base.ref }}) manifest..."
59+
BASE_MANIFEST=$(gh api repos/${{ github.repository }}/contents/.release-please-manifest.json?ref=${{ github.event.pull_request.base.ref }} 2>/dev/null | jq -r '.content' | base64 -d 2>/dev/null || echo "")
60+
if [ -n "$BASE_MANIFEST" ]; then
61+
PREV=$(echo "$BASE_MANIFEST" | jq -r '."."' 2>/dev/null || echo "")
62+
if [ -n "$PREV" ] && [ "$PREV" != "null" ] && [ "$PREV" != "0.0.0" ]; then
63+
echo "✅ Found version from base branch manifest: $PREV"
64+
echo "prev_version=$PREV" >> $GITHUB_OUTPUT
65+
echo "📦 Previous version: $PREV"
66+
exit 0
67+
fi
68+
fi
69+
70+
# Method 2: Get latest GitHub release tag
71+
echo "🏷️ Checking GitHub releases..."
72+
LATEST_RELEASE=$(gh api repos/${{ github.repository }}/releases/latest 2>/dev/null | jq -r '.tag_name' | sed 's/^v//' || echo "")
73+
if [ -n "$LATEST_RELEASE" ] && [ "$LATEST_RELEASE" != "null" ]; then
74+
echo "✅ Found version from GitHub releases: $LATEST_RELEASE"
75+
echo "prev_version=$LATEST_RELEASE" >> $GITHUB_OUTPUT
76+
echo "📦 Previous version: $LATEST_RELEASE"
77+
exit 0
78+
fi
79+
80+
# Method 3: Get latest tag (even if no release exists)
81+
echo "🏷️ Checking Git tags..."
82+
# Use sed instead of grep -oP for portability (BSD grep doesn't support -P)
83+
LATEST_TAG=$(git ls-remote --tags origin | sed -nE 's|.*refs/tags/v([0-9]+\.[0-9]+\.[0-9]+).*|\1|p' | sort -V | tail -1 || echo "")
84+
if [ -n "$LATEST_TAG" ]; then
85+
echo "✅ Found version from Git tags: $LATEST_TAG"
86+
echo "prev_version=$LATEST_TAG" >> $GITHUB_OUTPUT
87+
echo "📦 Previous version: $LATEST_TAG"
88+
exit 0
89+
fi
90+
91+
# Method 4: Fallback to PR branch manifest (might have new version, but better than 0.0.0)
92+
echo "📋 Checking PR branch manifest (fallback)..."
93+
PREV=$(jq -r '."."' .release-please-manifest.json 2>/dev/null || echo "0.0.0")
94+
if [ "$PREV" = "null" ] || [ -z "$PREV" ]; then
95+
PREV="0.0.0"
96+
fi
97+
98+
# If we got the same version as proposed, try to decrement patch version
99+
if [ "$PREV" = "${{ steps.version.outputs.version }}" ]; then
100+
echo "⚠️ PR branch has same version as proposed, attempting to infer previous..."
101+
# Try to get from git log or fallback to decrementing patch
102+
MAJOR=$(echo "$PREV" | cut -d. -f1)
103+
MINOR=$(echo "$PREV" | cut -d. -f2)
104+
PATCH=$(echo "$PREV" | cut -d. -f3)
105+
if [ "$PATCH" -gt 0 ]; then
106+
PREV="$MAJOR.$MINOR.$((PATCH - 1))"
107+
echo "📉 Decremented patch version: $PREV"
108+
else
109+
PREV="0.0.0"
110+
fi
111+
fi
112+
51113
echo "prev_version=$PREV" >> $GITHUB_OUTPUT
52114
echo "📦 Previous version: $PREV"
53115
@@ -80,7 +142,7 @@ jobs:
80142
REPO: ${{ github.repository }}
81143
PROPOSED_VERSION: ${{ steps.version.outputs.version }}
82144
PREVIOUS_VERSION: ${{ steps.prev_version.outputs.prev_version }}
83-
PR_BRANCH: ${{ github.head_ref }}
145+
PR_BRANCH: ${{ github.event.pull_request.head.ref }}
84146
PR_NUMBER: ${{ github.event.pull_request.number }}
85147
86148
# 🤖 CLAUDE CODE: RELEASE MANAGER FOR open-runtime/grpc-dart
@@ -254,7 +316,7 @@ jobs:
254316
255317
3. **Push All Changes:**
256318
```bash
257-
git push origin ${{ github.head_ref }}
319+
git push origin ${{ github.event.pull_request.head.ref }}
258320
```
259321
260322
4. **Be Conservative** - this is a critical infrastructure package

.github/workflows/release-please.yml

Lines changed: 75 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -32,54 +32,19 @@ permissions:
3232
actions: write
3333

3434
jobs:
35-
release-please:
36-
name: 📦 Release Please
37-
runs-on: ubuntu-latest
38-
outputs:
39-
release_created: ${{ steps.release.outputs.release_created }}
40-
releases_created: ${{ steps.release.outputs.releases_created }}
41-
tag_name: ${{ steps.release.outputs.tag_name }}
42-
version: ${{ steps.release.outputs.version }}
43-
major: ${{ steps.release.outputs.major }}
44-
minor: ${{ steps.release.outputs.minor }}
45-
patch: ${{ steps.release.outputs.patch }}
46-
sha: ${{ steps.release.outputs.sha }}
47-
pr: ${{ steps.release.outputs.pr }}
48-
prs_created: ${{ steps.release.outputs.prs_created }}
49-
steps:
50-
- name: 📥 Checkout source code
51-
uses: actions/checkout@v4
52-
53-
- name: 🤖 Run Release Please
54-
id: release
55-
uses: googleapis/release-please-action@v4
56-
with:
57-
token: ${{ secrets.GITHUB_TOKEN }}
58-
config-file: release-please-config.json
59-
manifest-file: .release-please-manifest.json
60-
target-branch: ${{ github.ref_name }}
61-
62-
- name: 📝 Log Release Info
63-
if: ${{ steps.release.outputs.releases_created == 'true' }}
64-
run: |
65-
echo "🎉 Release created!"
66-
echo "📦 Version: ${{ steps.release.outputs.version }}"
67-
echo "🏷️ Tag: ${{ steps.release.outputs.tag_name }}"
68-
echo "🔗 https://github.com/${{ github.repository }}/releases/tag/${{ steps.release.outputs.tag_name }}"
69-
7035
# =============================================================================
71-
# Fallback: Handle Untagged Merged Release PRs
72-
# =============================================================================
73-
# If Release Please aborts due to "untagged merged release PRs", this job
74-
# will find those PRs, create the missing tags, and create GitHub releases.
75-
# This handles edge cases like when Claude changes the version in a Release PR.
36+
# Step 1: Handle Untagged Merged Release PRs FIRST
7637
# =============================================================================
38+
# This MUST run before release-please to prevent "untagged PRs outstanding" abort
39+
# Release Please aborts if it finds merged PRs with "autorelease: pending" label
40+
# By running this first, we ensure all untagged PRs are tagged before Release Please checks
7741
handle-untagged-releases:
78-
name: 🔧 Handle Untagged Releases (Fallback)
79-
needs: release-please
80-
# Run if Release Please didn't create a release (might have aborted)
81-
if: ${{ needs.release-please.outputs.releases_created != 'true' }}
42+
name: 🔧 Handle Untagged Releases (Pre-Check)
8243
runs-on: ubuntu-latest
44+
outputs:
45+
release_created: ${{ steps.process.outputs.release_created }}
46+
tag_name: ${{ steps.process.outputs.tag_name }}
47+
version: ${{ steps.process.outputs.version }}
8348
steps:
8449
- name: 📥 Checkout source code
8550
uses: actions/checkout@v4
@@ -127,7 +92,6 @@ jobs:
12792
echo " SHA: $MERGE_SHA"
12893
echo " Tag: $TAG_NAME"
12994
130-
# Check if tag already exists
13195
if gh api repos/${{ github.repository }}/git/refs/tags/$TAG_NAME 2>/dev/null; then
13296
echo "✅ Tag $TAG_NAME already exists"
13397
else
@@ -138,13 +102,14 @@ jobs:
138102
-f sha="$MERGE_SHA"
139103
fi
140104
141-
# Check if release already exists
142105
if gh release view $TAG_NAME --repo ${{ github.repository }} 2>/dev/null; then
143106
echo "✅ Release $TAG_NAME already exists"
144107
else
145108
echo "🎉 Creating GitHub Release $TAG_NAME"
109+
RELEASE_CREATED=true
110+
LATEST_TAG="$TAG_NAME"
111+
LATEST_VERSION="$VERSION"
146112
147-
# Extract changelog for this version
148113
CHANGELOG=$(awk -v ver="$VERSION" '
149114
/^## \[/ {
150115
if (found) exit
@@ -157,7 +122,6 @@ jobs:
157122
CHANGELOG="Release v$VERSION - See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ github.ref_name }}/CHANGELOG.md) for details."
158123
fi
159124
160-
# Create release notes file using printf (heredocs break YAML indentation)
161125
{
162126
echo "## 📦 Installation"
163127
echo ""
@@ -185,36 +149,88 @@ jobs:
185149
echo "$CHANGELOG"
186150
} > /tmp/release_notes.md
187151
188-
# Create the release
189152
gh release create $TAG_NAME \
190153
--repo ${{ github.repository }} \
191154
--title "v$VERSION" \
192155
--notes-file /tmp/release_notes.md
193156
fi
194157
195-
# Update label to autorelease: tagged
196158
echo "🏷️ Updating PR #$PR_NUM label to autorelease: tagged"
197159
gh pr edit $PR_NUM \
198160
--repo ${{ github.repository }} \
199161
--remove-label "autorelease: pending" \
200162
--add-label "autorelease: tagged" || true
201163
202164
echo "✅ Processed PR #$PR_NUM"
203-
done
165+
done < <(echo "$PENDING_PRS" | jq -c '.')
166+
167+
# Output the latest release info (if any was created)
168+
if [ "$RELEASE_CREATED" = "true" ]; then
169+
echo "release_created=true" >> $GITHUB_OUTPUT
170+
echo "tag_name=$LATEST_TAG" >> $GITHUB_OUTPUT
171+
echo "version=$LATEST_VERSION" >> $GITHUB_OUTPUT
172+
else
173+
echo "release_created=false" >> $GITHUB_OUTPUT
174+
fi
175+
176+
# =============================================================================
177+
# Step 2: Run Release Please (after untagged PRs are handled)
178+
# =============================================================================
179+
release-please:
180+
name: 📦 Release Please
181+
needs: handle-untagged-releases
182+
runs-on: ubuntu-latest
183+
outputs:
184+
release_created: ${{ steps.release.outputs.release_created }}
185+
releases_created: ${{ steps.release.outputs.releases_created }}
186+
tag_name: ${{ steps.release.outputs.tag_name }}
187+
version: ${{ steps.release.outputs.version }}
188+
major: ${{ steps.release.outputs.major }}
189+
minor: ${{ steps.release.outputs.minor }}
190+
patch: ${{ steps.release.outputs.patch }}
191+
sha: ${{ steps.release.outputs.sha }}
192+
pr: ${{ steps.release.outputs.pr }}
193+
prs_created: ${{ steps.release.outputs.prs_created }}
194+
steps:
195+
- name: 📥 Checkout source code
196+
uses: actions/checkout@v4
197+
198+
- name: 🤖 Run Release Please
199+
id: release
200+
uses: googleapis/release-please-action@v4
201+
with:
202+
token: ${{ secrets.GITHUB_TOKEN }}
203+
config-file: release-please-config.json
204+
manifest-file: .release-please-manifest.json
205+
target-branch: ${{ github.ref_name }}
206+
207+
- name: 📝 Log Release Info
208+
if: ${{ steps.release.outputs.releases_created == 'true' }}
209+
run: |
210+
echo "🎉 Release created!"
211+
echo "📦 Version: ${{ steps.release.outputs.version }}"
212+
echo "🏷️ Tag: ${{ steps.release.outputs.tag_name }}"
213+
echo "🔗 https://github.com/${{ github.repository }}/releases/tag/${{ steps.release.outputs.tag_name }}"
214+
215+
# =============================================================================
216+
# Step 3: Verify Release
217+
# =============================================================================
204218

205219
# =============================================================================
206220
# Verify Release
207221
# =============================================================================
208222
verify-release:
209223
name: ✅ Verify Release
210-
needs: release-please
211-
if: ${{ needs.release-please.outputs.releases_created == 'true' }}
224+
needs: [release-please, handle-untagged-releases]
225+
if: |
226+
needs.release-please.outputs.releases_created == 'true' ||
227+
(needs.handle-untagged-releases.outputs.release_created == 'true' && needs.handle-untagged-releases.result == 'success')
212228
runs-on: ubuntu-latest
213229
steps:
214230
- name: 📥 Checkout source code
215231
uses: actions/checkout@v4
216232
with:
217-
ref: ${{ needs.release-please.outputs.tag_name }}
233+
ref: ${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.tag_name || needs.handle-untagged-releases.outputs.tag_name }}
218234

219235
- name: 🎯 Install Dart SDK
220236
uses: dart-lang/setup-dart@v1
@@ -228,7 +244,7 @@ jobs:
228244
run: |
229245
echo "📦 Verifying package version..."
230246
VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}')
231-
EXPECTED="${{ needs.release-please.outputs.version }}"
247+
EXPECTED="${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.version || needs.handle-untagged-releases.outputs.version }}"
232248
if [ "$VERSION" != "$EXPECTED" ]; then
233249
echo "❌ Version mismatch: pubspec.yaml has $VERSION, expected $EXPECTED"
234250
exit 1
@@ -243,7 +259,8 @@ jobs:
243259

244260
- name: 📋 Release Summary
245261
run: |
246-
echo "## 🎉 Release v${{ needs.release-please.outputs.version }} Verified!" >> $GITHUB_STEP_SUMMARY
262+
VERSION="${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.version || needs.handle-untagged-releases.outputs.version }}"
263+
echo "## 🎉 Release v$VERSION Verified!" >> $GITHUB_STEP_SUMMARY
247264
echo "" >> $GITHUB_STEP_SUMMARY
248265
echo "### 📦 Installation" >> $GITHUB_STEP_SUMMARY
249266
echo "" >> $GITHUB_STEP_SUMMARY
@@ -254,9 +271,9 @@ jobs:
254271
echo " git:" >> $GITHUB_STEP_SUMMARY
255272
echo " url: https://github.com/open-runtime/grpc-dart" >> $GITHUB_STEP_SUMMARY
256273
echo " tag_pattern: \"^v\"" >> $GITHUB_STEP_SUMMARY
257-
echo " version: ^${{ needs.release-please.outputs.version }}" >> $GITHUB_STEP_SUMMARY
274+
echo " version: ^$VERSION" >> $GITHUB_STEP_SUMMARY
258275
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
259276
echo "" >> $GITHUB_STEP_SUMMARY
260277
echo "### 🔗 Links" >> $GITHUB_STEP_SUMMARY
261-
echo "- [GitHub Release](https://github.com/${{ github.repository }}/releases/tag/v${{ needs.release-please.outputs.version }})" >> $GITHUB_STEP_SUMMARY
278+
echo "- [GitHub Release](https://github.com/${{ github.repository }}/releases/tag/v$VERSION)" >> $GITHUB_STEP_SUMMARY
262279
echo "- [Changelog](https://github.com/${{ github.repository }}/blob/${{ github.ref_name }}/CHANGELOG.md)" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)