Skip to content

Commit ff2c0c5

Browse files
author
David Crow
committed
Plugin release automation
1 parent 3f6b01f commit ff2c0c5

2 files changed

Lines changed: 293 additions & 9 deletions

File tree

.github/workflows/prep-release.yaml

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,14 @@ jobs:
4040
fetch-depth: 0
4141
token: ${{ secrets.GITHUB_TOKEN }}
4242

43-
- name: Run Updates
44-
run: |
45-
./scripts/update_version.sh "${{ github.event.inputs.cordova_version }}" || exit 1
46-
if [ -n "${{ github.event.inputs.proxy_version }}" ]; then
47-
./scripts/update_proxy_version.sh "${{ github.event.inputs.proxy_version }}" || exit 1
48-
fi
49-
./scripts/update_changelog.sh "${{ github.event.inputs.cordova_version }}" \
50-
$([ -n "${{ github.event.inputs.ios_version }}" ] && echo "--ios ${{ github.event.inputs.ios_version }}") \
51-
$([ -n "${{ github.event.inputs.android_version }}" ] && echo "--android ${{ github.event.inputs.android_version }}") || exit 1
43+
- name: Prepare Release
44+
run: ./scripts/prep_release.sh
45+
env:
46+
PLUGIN_VERSION: ${{ github.event.inputs.cordova_version }}
47+
PROXY_VERSION: ${{ github.event.inputs.proxy_version }}
48+
IOS_VERSION: ${{ github.event.inputs.ios_version }}
49+
ANDROID_VERSION: ${{ github.event.inputs.android_version }}
50+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
5251

5352
- name: Verify Changes
5453
id: verify
@@ -96,6 +95,65 @@ jobs:
9695
echo "PR Number: ${{ steps.create-pr.outputs.pull-request-number }}"
9796
echo "PR URL: ${{ steps.create-pr.outputs.pull-request-url }}"
9897
98+
- name: Gemini PR Review
99+
if: success() && steps.create-pr.outputs.pull-request-number && env.GEMINI_API_KEY != ''
100+
continue-on-error: true
101+
env:
102+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
103+
run: |
104+
# Get PR diff
105+
PR_DIFF=$(git diff main...cordova-${{ github.event.inputs.cordova_version }})
106+
107+
# Create review prompt
108+
PROMPT="Review this Cordova Airship plugin release PR. Check for:
109+
1. Version consistency across plugin.xml, package.json, and version files
110+
2. Changelog format and completeness
111+
3. SDK version links are correct
112+
4. Proxy version is updated correctly in both core and HMS packages
113+
114+
PR Details:
115+
- Plugin version: ${{ github.event.inputs.cordova_version }}
116+
- Proxy version: ${{ github.event.inputs.proxy_version }}
117+
- iOS SDK: ${{ github.event.inputs.ios_version }}
118+
- Android SDK: ${{ github.event.inputs.android_version }}
119+
120+
Diff:
121+
\`\`\`
122+
${PR_DIFF}
123+
\`\`\`
124+
125+
Provide a concise review with any issues or suggestions."
126+
127+
# Call Gemini API
128+
RESPONSE=$(curl -s -X POST \
129+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${GEMINI_API_KEY}" \
130+
-H "Content-Type: application/json" \
131+
-d "{
132+
\"contents\": [{
133+
\"parts\": [{\"text\": $(echo "$PROMPT" | jq -Rs .)}]
134+
}],
135+
\"generationConfig\": {
136+
\"temperature\": 0.3,
137+
\"maxOutputTokens\": 2048
138+
}
139+
}")
140+
141+
# Extract review text
142+
REVIEW=$(echo "$RESPONSE" | jq -r '.candidates[0].content.parts[0].text // empty')
143+
144+
if [ -n "$REVIEW" ]; then
145+
# Post review as PR comment
146+
gh pr comment ${{ steps.create-pr.outputs.pull-request-number }} \
147+
--body "## 🤖 Gemini AI Review
148+
149+
${REVIEW}
150+
151+
---
152+
*This is an automated review. Please verify all changes manually.*"
153+
else
154+
echo "Gemini review failed or returned empty response"
155+
fi
156+
99157
- name: Slack Notification (Success)
100158
if: success() && steps.create-pr.outputs.pull-request-number
101159
uses: homoluctus/slatify@master

scripts/prep_release.sh

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Unified release preparation script for Cordova Airship
5+
# Combines: update_version.sh, update_proxy_version.sh, update_changelog.sh
6+
# Usage: ./prep_release.sh [--dry-run]
7+
# Env vars: PLUGIN_VERSION, PROXY_VERSION, IOS_VERSION, ANDROID_VERSION, GEMINI_API_KEY
8+
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11+
12+
# Parse arguments
13+
DRY_RUN=false
14+
if [ "$1" = "--dry-run" ]; then
15+
DRY_RUN=true
16+
echo "🔍 DRY RUN MODE - No changes will be made"
17+
echo ""
18+
fi
19+
20+
# Required env vars
21+
if [ -z "$PLUGIN_VERSION" ]; then
22+
echo "Error: PLUGIN_VERSION environment variable required"
23+
exit 1
24+
fi
25+
26+
# Optional env vars
27+
PROXY_VERSION="${PROXY_VERSION:-}"
28+
IOS_VERSION="${IOS_VERSION:-}"
29+
ANDROID_VERSION="${ANDROID_VERSION:-}"
30+
GEMINI_API_KEY="${GEMINI_API_KEY:-}"
31+
32+
echo "Cordova Airship Release Preparation"
33+
echo "===================================="
34+
echo "Plugin version: $PLUGIN_VERSION"
35+
echo "Proxy version: ${PROXY_VERSION:-not specified}"
36+
echo "iOS SDK: ${IOS_VERSION:-not specified}"
37+
echo "Android SDK: ${ANDROID_VERSION:-not specified}"
38+
echo ""
39+
40+
# Function to polish changelog with Gemini (graceful degradation)
41+
polish_changelog() {
42+
local changelog_text="$1"
43+
44+
if [ -z "$GEMINI_API_KEY" ]; then
45+
echo "$changelog_text"
46+
return 0
47+
fi
48+
49+
local prompt="Polish this Cordova Airship changelog entry. Keep it concise and professional.
50+
51+
Changelog:
52+
$changelog_text
53+
54+
Return ONLY the polished changelog text."
55+
56+
local response
57+
response=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=$GEMINI_API_KEY" \
58+
-H "Content-Type: application/json" \
59+
-d "{
60+
\"contents\": [{
61+
\"parts\": [{\"text\": \"$(echo "$prompt" | sed 's/"/\\"/g' | tr '\n' ' ')\"}]
62+
}],
63+
\"generationConfig\": {
64+
\"temperature\": 0.3,
65+
\"maxOutputTokens\": 1024
66+
}
67+
}" 2>&1)
68+
69+
if echo "$response" | grep -q "error"; then
70+
echo "$changelog_text"
71+
return 0
72+
fi
73+
74+
local polished
75+
polished=$(echo "$response" | grep -o '"text"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"text"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//' | head -1)
76+
77+
if [ -n "$polished" ]; then
78+
echo "$polished"
79+
else
80+
echo "$changelog_text"
81+
fi
82+
}
83+
84+
# File paths
85+
CORE_PACKAGE_PATH="$REPO_ROOT/cordova-airship"
86+
HMS_PACKAGE_PATH="$REPO_ROOT/cordova-airship-hms"
87+
ANDROID_VERSION_PATH="$REPO_ROOT/cordova-airship/src/android/AirshipCordovaVersion.kt"
88+
IOS_VERSION_PATH="$REPO_ROOT/cordova-airship/src/ios/AirshipCordovaVersion.swift"
89+
HMS_PLUGIN_XML_PATH="$REPO_ROOT/cordova-airship-hms/plugin.xml"
90+
CORE_PLUGIN_XML_PATH="$REPO_ROOT/cordova-airship/plugin.xml"
91+
92+
# Step 1: Update plugin version
93+
echo "[1/4] Updating plugin version..."
94+
if [ "$DRY_RUN" = "false" ]; then
95+
sed -i '' "s/var version = \"[-0-9.a-zA-Z]*\"/var version = \"$PLUGIN_VERSION\"/" "$ANDROID_VERSION_PATH"
96+
sed -i '' "s/static let version = \"[-0-9.a-zA-Z]*\"/static let version = \"$PLUGIN_VERSION\"/" "$IOS_VERSION_PATH"
97+
sed -i '' "s/<plugin id=\"@ua\/cordova-airship\" version=\"[0-9.]*\"/<plugin id=\"@ua\/cordova-airship\" version=\"$PLUGIN_VERSION\"/" "$CORE_PLUGIN_XML_PATH"
98+
sed -i '' "s/<plugin id=\"@ua\/cordova-airship-hms\" version=\"[0-9.]*\"/<plugin id=\"@ua\/cordova-airship-hms\" version=\"$PLUGIN_VERSION\"/" "$HMS_PLUGIN_XML_PATH"
99+
sed -i '' "s/<dependency id=\"@ua\/cordova-airship\" version=\"[0-9.]*\"\/>/<dependency id=\"@ua\/cordova-airship\" version=\"$PLUGIN_VERSION\"\/>/" "$HMS_PLUGIN_XML_PATH"
100+
npm --prefix "$CORE_PACKAGE_PATH" version "$PLUGIN_VERSION" --no-git-tag-version
101+
npm --prefix "$HMS_PACKAGE_PATH" version "$PLUGIN_VERSION" --no-git-tag-version
102+
echo " ✓ Updated version files and package.json"
103+
else
104+
echo " Would update:"
105+
echo " - $ANDROID_VERSION_PATH"
106+
echo " - $IOS_VERSION_PATH"
107+
echo " - $CORE_PLUGIN_XML_PATH"
108+
echo " - $HMS_PLUGIN_XML_PATH"
109+
echo " - $CORE_PACKAGE_PATH/package.json"
110+
echo " - $HMS_PACKAGE_PATH/package.json"
111+
fi
112+
113+
# Step 2: Update proxy version (if specified)
114+
if [ -n "$PROXY_VERSION" ]; then
115+
echo "[2/4] Updating proxy version..."
116+
if [ "$DRY_RUN" = "false" ]; then
117+
sed -i '' -E "s/(pod name=\"AirshipFrameworkProxy\" spec=\")[^\"]*\"/\1$PROXY_VERSION\"/" "$CORE_PLUGIN_XML_PATH"
118+
sed -i '' -E "s/(api \"com.urbanairship.android:airship-framework-proxy:)[^\"]*\"/\1$PROXY_VERSION\"/" "$REPO_ROOT/cordova-airship/src/android/build-extras.gradle"
119+
sed -i '' -E "s/(implementation \"com.urbanairship.android:airship-framework-proxy-hms:)[^\"]*\"/\1$PROXY_VERSION\"/" "$REPO_ROOT/cordova-airship-hms/src/android/build-extras.gradle"
120+
echo " ✓ Updated plugin.xml and build-extras.gradle"
121+
else
122+
echo " Would update proxy version to $PROXY_VERSION"
123+
fi
124+
else
125+
echo "[2/4] Skipping proxy version update (not specified)"
126+
fi
127+
128+
# Step 3: Generate changelog
129+
echo "[3/4] Generating changelog..."
130+
131+
RELEASE_DATE=$(date +"%B %-d, %Y")
132+
133+
# Determine release type
134+
if [[ $PLUGIN_VERSION =~ \.0\.0$ ]]; then
135+
RELEASE_TYPE="Major"
136+
elif [[ $PLUGIN_VERSION =~ \.0$ ]]; then
137+
RELEASE_TYPE="Minor"
138+
else
139+
RELEASE_TYPE="Patch"
140+
fi
141+
142+
# Build changelog entry
143+
NEW_ENTRY="## Version $PLUGIN_VERSION - $RELEASE_DATE\n\n"
144+
145+
if [ -n "$IOS_VERSION" ] || [ -n "$ANDROID_VERSION" ]; then
146+
NEW_ENTRY+="$RELEASE_TYPE release that updates"
147+
148+
if [ -n "$ANDROID_VERSION" ]; then
149+
NEW_ENTRY+=" the Android SDK to $ANDROID_VERSION"
150+
fi
151+
152+
if [ -n "$IOS_VERSION" ] && [ -n "$ANDROID_VERSION" ]; then
153+
NEW_ENTRY+=" and"
154+
fi
155+
156+
if [ -n "$IOS_VERSION" ]; then
157+
NEW_ENTRY+=" the iOS SDK to $IOS_VERSION"
158+
fi
159+
160+
NEW_ENTRY+="\n\n### Changes\n"
161+
162+
if [ -n "$ANDROID_VERSION" ]; then
163+
NEW_ENTRY+="- Updated Android SDK to [$ANDROID_VERSION](https://github.com/urbanairship/android-library/releases/tag/$ANDROID_VERSION)"
164+
fi
165+
166+
if [ -n "$IOS_VERSION" ]; then
167+
NEW_ENTRY+="\n"
168+
NEW_ENTRY+="- Updated iOS SDK to [$IOS_VERSION](https://github.com/urbanairship/ios-library/releases/tag/$IOS_VERSION)"
169+
fi
170+
else
171+
NEW_ENTRY+="$RELEASE_TYPE release."
172+
fi
173+
174+
# Polish with Gemini if available
175+
if [ "$DRY_RUN" = "false" ]; then
176+
POLISHED_ENTRY=$(polish_changelog "$(echo -e "$NEW_ENTRY")")
177+
178+
# Update CHANGELOG.md
179+
TEMP_FILE=$(mktemp)
180+
echo "# Cordova Plugin Changelog" > "$TEMP_FILE"
181+
echo -e "\n$POLISHED_ENTRY" >> "$TEMP_FILE"
182+
tail -n +2 "$REPO_ROOT/CHANGELOG.md" >> "$TEMP_FILE"
183+
mv "$TEMP_FILE" "$REPO_ROOT/CHANGELOG.md"
184+
echo " ✓ Updated CHANGELOG.md"
185+
else
186+
echo " Would add to CHANGELOG.md:"
187+
echo -e "$NEW_ENTRY" | sed 's/^/ /'
188+
fi
189+
190+
# Step 4: Validation
191+
echo "[4/4] Validation..."
192+
if [ "$DRY_RUN" = "false" ]; then
193+
# Verify changes
194+
if grep -q "var version = \"$PLUGIN_VERSION\"" "$ANDROID_VERSION_PATH"; then
195+
echo " ✓ Android version verified"
196+
else
197+
echo " ✗ Android version mismatch"
198+
exit 1
199+
fi
200+
201+
if grep -q "static let version = \"$PLUGIN_VERSION\"" "$IOS_VERSION_PATH"; then
202+
echo " ✓ iOS version verified"
203+
else
204+
echo " ✗ iOS version mismatch"
205+
exit 1
206+
fi
207+
208+
if [ -n "$PROXY_VERSION" ]; then
209+
if grep -q "pod name=\"AirshipFrameworkProxy\" spec=\"$PROXY_VERSION\"" "$CORE_PLUGIN_XML_PATH"; then
210+
echo " ✓ Proxy version verified"
211+
else
212+
echo " ✗ Proxy version mismatch"
213+
exit 1
214+
fi
215+
fi
216+
217+
echo ""
218+
echo "✅ Release preparation complete!"
219+
echo ""
220+
echo "Next steps:"
221+
echo "1. Review changes: git diff"
222+
echo "2. Commit changes"
223+
echo "3. Create PR"
224+
else
225+
echo " Dry-run complete - no changes made"
226+
fi

0 commit comments

Comments
 (0)