Skip to content

Commit 39b418e

Browse files
committed
create release workflow
1 parent a55f11e commit 39b418e

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
name: Create Release PR
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release-type:
7+
description: "Release type"
8+
required: true
9+
default: "stable"
10+
type: choice
11+
options:
12+
- Current
13+
- Beta
14+
- Alpha
15+
16+
jobs:
17+
bump-version:
18+
runs-on: ubuntu-latest
19+
20+
env:
21+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v5
26+
with:
27+
fetch-depth: 0
28+
fetch-tags: true
29+
30+
- name: Set up Bun
31+
uses: oven-sh/setup-bun@v2
32+
with:
33+
bun-version: latest
34+
35+
- name: Get current SDK version
36+
id: current_version
37+
run: |
38+
CURRENT_VERSION=$(bun -e "console.log(require('./package.json').version)")
39+
echo "current=$CURRENT_VERSION" >> $GITHUB_OUTPUT
40+
41+
- name: Get last release commit
42+
id: last_commit
43+
run: |
44+
LAST_RELEASE_DATE=$(git show -s --format=%cI "${{ steps.current_version.outputs.current }}")
45+
echo "date=$LAST_RELEASE_DATE" >> $GITHUB_OUTPUT
46+
47+
- name: Get merged PRs since last release
48+
id: get_prs
49+
uses: actions/github-script@v8
50+
with:
51+
script: |
52+
const lastReleaseDate = '${{ steps.last_commit.outputs.date }}';
53+
54+
// Get merged PRs
55+
const { data: prs } = await github.rest.pulls.list({
56+
owner: context.repo.owner,
57+
repo: context.repo.repo,
58+
state: 'closed',
59+
base: 'main',
60+
per_page: 100
61+
});
62+
63+
// Filter and process PRs
64+
const mergedPrs = prs
65+
.filter(pr => pr.merged_at && new Date(pr.merged_at) > new Date(lastReleaseDate))
66+
.map(pr => ({
67+
number: pr.number,
68+
title: pr.title,
69+
}));
70+
core.setOutput('prs', JSON.stringify(mergedPrs));
71+
72+
const hasFeatures = mergedPrs.some(pr => /^feat/i.test(pr.title));
73+
core.setOutput('isFeature', hasFeatures);
74+
75+
- name: Calculate new version
76+
id: new_version
77+
run: |
78+
CURRENT="${{ steps.current_version.outputs.current }}"
79+
RELEASE_TYPE="${{ inputs.release-type }}"
80+
IS_FEATURE='${{ steps.get_prs.outputs.isFeature }}'
81+
82+
# Extract base version and determine current pre-release type
83+
if [[ "$CURRENT" =~ -alpha\. ]]; then
84+
BASE_VERSION="${CURRENT%-alpha.*}"
85+
PRERELEASE_NUM="${CURRENT##*-alpha.}"
86+
PRERELEASE_TYPE="alpha"
87+
elif [[ "$CURRENT" =~ -beta\. ]]; then
88+
BASE_VERSION="${CURRENT%-beta.*}"
89+
PRERELEASE_NUM="${CURRENT##*-beta.}"
90+
PRERELEASE_TYPE="beta"
91+
else
92+
BASE_VERSION="$CURRENT"
93+
PRERELEASE_TYPE="stable"
94+
fi
95+
96+
# Helper function to bump version
97+
bump_version() {
98+
local base=$1
99+
local is_feature=$2
100+
local major=${base:0:2}
101+
local minor=${base:2:2}
102+
local patch=${base:4:2}
103+
104+
if [[ "$is_feature" == "true" ]]; then
105+
minor=$(printf "%02d" $((10#$minor + 1)))
106+
patch="00"
107+
else
108+
patch=$(printf "%02d" $((10#$patch + 1)))
109+
fi
110+
111+
echo "${major}${minor}${patch}"
112+
}
113+
114+
# Determine new version based on current and desired release types
115+
if [[ "$RELEASE_TYPE" == "Alpha" ]]; then
116+
if [[ "$PRERELEASE_TYPE" == "alpha" ]]; then
117+
# Increment alpha number
118+
NEW_VERSION="$BASE_VERSION-alpha.$((PRERELEASE_NUM + 1))"
119+
else
120+
# New alpha release from stable or beta
121+
NEW_VERSION="$(bump_version "$BASE_VERSION" "$IS_FEATURE")-alpha.1"
122+
fi
123+
elif [[ "$RELEASE_TYPE" == "Beta" ]]; then
124+
if [[ "$PRERELEASE_TYPE" == "beta" ]]; then
125+
# Increment beta number
126+
NEW_VERSION="$BASE_VERSION-beta.$((PRERELEASE_NUM + 1))"
127+
elif [[ "$PRERELEASE_TYPE" == "alpha" ]]; then
128+
# Promote alpha to beta
129+
NEW_VERSION="$BASE_VERSION-beta.1"
130+
else
131+
# New beta release from stable
132+
NEW_VERSION="$(bump_version "$BASE_VERSION" "$IS_FEATURE")-beta.1"
133+
fi
134+
else
135+
# Release type is Current (stable)
136+
if [[ "$PRERELEASE_TYPE" != "stable" ]]; then
137+
# Promote pre-release to stable
138+
NEW_VERSION="$BASE_VERSION"
139+
else
140+
# Bump stable version
141+
NEW_VERSION="$(bump_version "$CURRENT" "$IS_FEATURE")"
142+
fi
143+
fi
144+
145+
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
146+
147+
- name: Create release branch
148+
run: |
149+
git checkout -b rel/${{ steps.new_version.outputs.version }}
150+
git push -u origin rel/${{ steps.new_version.outputs.version }}
151+
152+
- name: Create temp branch
153+
if: inputs.release-type == 'Alpha' || inputs.release-type == 'Beta'
154+
run: |
155+
git checkout -b release-${{ steps.new_version.outputs.version }}
156+
git push -u origin release-${{ steps.new_version.outputs.version }}
157+
158+
# Cordova specific steps
159+
- name: Update sdk version
160+
run: |
161+
NEW_VERSION="${{ steps.new_version.outputs.version }}"
162+
git config user.name "github-actions[bot]"
163+
git config user.email "github-actions[bot]@users.noreply.github.com"
164+
165+
# Convert version format for OneSignal wrapper (e.g., 5.2.15 -> 050215)
166+
# For pre-releases, extract base version first (e.g., 5.2.15-alpha.1 -> 5.2.15)
167+
BASE_VERSION=$(echo "$NEW_VERSION" | sed 's/-[a-z].*//')
168+
WRAPPER_VERSION=$(echo "$BASE_VERSION" | sed 's/\.//g' | awk '{printf "%06d", $0}')
169+
170+
# Update package.json version
171+
npm pkg set version="$NEW_VERSION"
172+
173+
# Update plugin.xml cordova plugin version (target <plugin> element specifically)
174+
sed -i 's|<plugin \(xmlns="[^"]*" xmlns:android="[^"]*" id="[^"]*"\) version="[^"]*"|<plugin \1 version="'"$NEW_VERSION"'"|' plugin.xml
175+
176+
# Update OneSignalPush.java wrapper version
177+
sed -i "s/OneSignalWrapper\.setSdkVersion(\"[^\"]*\")/OneSignalWrapper.setSdkVersion(\"$WRAPPER_VERSION\")/g" src/android/com/onesignal/cordova/OneSignalPush.java
178+
179+
# Update OneSignalPush.m wrapper version
180+
sed -i "s/OneSignalWrapper\.sdkVersion = @\"[^\"]*\"/OneSignalWrapper.sdkVersion = @\"$WRAPPER_VERSION\"/g" src/ios/OneSignalPush.m
181+
182+
git add package.json plugin.xml src/android/com/onesignal/cordova/OneSignalPush.java src/ios/OneSignalPush.m
183+
184+
git commit -m "Release $NEW_VERSION"
185+
git push
186+
187+
- name: Check native SDK version changes
188+
id: native_deps
189+
run: |
190+
# Get the current plugin.xml
191+
CURRENT_PLUGIN=$(cat plugin.xml)
192+
193+
# Extract current Android SDK version
194+
ANDROID_VERSION=$(echo "$CURRENT_PLUGIN" | grep -oP 'com\.onesignal:OneSignal:\K[0-9.]+' | head -1)
195+
196+
# Extract current iOS SDK version
197+
IOS_VERSION=$(echo "$CURRENT_PLUGIN" | grep -oP 'OneSignalXCFramework.*spec="\K[0-9.]+' | head -1)
198+
199+
# Get previous plugin.xml from HEAD~1 (before the commit we just made)
200+
PREVIOUS_PLUGIN=$(git show HEAD~1:plugin.xml)
201+
202+
# Extract previous Android SDK version
203+
PREVIOUS_ANDROID=$(echo "$PREVIOUS_PLUGIN" | grep -oP 'com\.onesignal:OneSignal:\K[0-9.]+' | head -1)
204+
205+
# Extract previous iOS SDK version
206+
PREVIOUS_IOS=$(echo "$PREVIOUS_PLUGIN" | grep -oP 'OneSignalXCFramework.*spec="\K[0-9.]+' | head -1)
207+
208+
# Build output for native dependency changes
209+
NATIVE_UPDATES=""
210+
if [[ "$ANDROID_VERSION" != "$PREVIOUS_ANDROID" && ! -z "$PREVIOUS_ANDROID" ]]; then
211+
printf -v NATIVE_UPDATES '%sANDROID_UPDATE=true\nANDROID_FROM=%s\nANDROID_TO=%s\n' "$NATIVE_UPDATES" "$PREVIOUS_ANDROID" "$ANDROID_VERSION"
212+
fi
213+
214+
if [[ "$IOS_VERSION" != "$PREVIOUS_IOS" && ! -z "$PREVIOUS_IOS" ]]; then
215+
printf -v NATIVE_UPDATES '%sIOS_UPDATE=true\nIOS_FROM=%s\nIOS_TO=%s\n' "$NATIVE_UPDATES" "$PREVIOUS_IOS" "$IOS_VERSION"
216+
fi
217+
218+
# Output the variables
219+
echo "$NATIVE_UPDATES" >> $GITHUB_OUTPUT
220+
221+
- name: Generate release notes
222+
id: release_notes
223+
uses: actions/github-script@v8
224+
with:
225+
script: |
226+
// Trim whitespace from PR titles
227+
const prs = JSON.parse('${{ steps.get_prs.outputs.prs }}').map(pr => ({
228+
...pr,
229+
title: pr.title.trim()
230+
}));
231+
232+
// Categorize PRs
233+
const features = prs.filter(pr => /^feat/i.test(pr.title));
234+
const fixes = prs.filter(pr => /^fix/i.test(pr.title));
235+
const improvements = prs.filter(pr => /^(perf|refactor|chore)/i.test(pr.title));
236+
237+
// Helper function to build section
238+
const buildSection = (title, prs) => {
239+
if (prs.length === 0) return '';
240+
let section = `### ${title}\n\n`;
241+
prs.forEach(pr => {
242+
section += `- ${pr.title} (#${pr.number})\n`;
243+
});
244+
return section + '\n';
245+
};
246+
247+
let releaseNotes = `Channels: ${{ inputs.release-type }}\n\n`;
248+
releaseNotes += buildSection('🚀 New Features', features);
249+
releaseNotes += buildSection('🐛 Bug Fixes', fixes);
250+
releaseNotes += buildSection('✨ Improvements', improvements);
251+
252+
// Check for native dependency changes
253+
const hasAndroidUpdate = '${{ steps.native_deps.outputs.ANDROID_UPDATE }}' === 'true';
254+
const hasIosUpdate = '${{ steps.native_deps.outputs.IOS_UPDATE }}' === 'true';
255+
256+
if (hasAndroidUpdate || hasIosUpdate) {
257+
releaseNotes += '\n### 🛠️ Native Dependency Updates\n\n';
258+
if (hasAndroidUpdate) {
259+
releaseNotes += `- Update Android SDK from ${{ steps.native_deps.outputs.ANDROID_FROM }} to ${{ steps.native_deps.outputs.ANDROID_TO }}\n`;
260+
releaseNotes += `- See [release notes](https://github.com/OneSignal/OneSignal-Android-SDK/releases) for full details\n`;
261+
}
262+
if (hasIosUpdate) {
263+
releaseNotes += `- Update iOS SDK from ${{ steps.native_deps.outputs.IOS_FROM }} to ${{ steps.native_deps.outputs.IOS_TO }}\n`;
264+
releaseNotes += `- See [release notes](https://github.com/OneSignal/OneSignal-iOS-SDK/releases) for full details\n`;
265+
}
266+
releaseNotes += '\n';
267+
}
268+
269+
core.setOutput('notes', releaseNotes);
270+
271+
- name: Create release PR
272+
run: |
273+
NEW_VERSION="${{ steps.new_version.outputs.version }}"
274+
275+
# Write release notes to file to avoid shell interpretation
276+
cat > release_notes.md << 'EOF'
277+
${{ steps.release_notes.outputs.notes }}
278+
EOF
279+
280+
gh pr create \
281+
--title "Release $NEW_VERSION" \
282+
--body-file release_notes.md \
283+
--base main \
284+
--reviewer fadi-george,sherwinski,jkasten2

0 commit comments

Comments
 (0)