diff --git a/.github/workflows/prep-release.yml b/.github/workflows/prep-release.yml new file mode 100644 index 00000000..25d412ea --- /dev/null +++ b/.github/workflows/prep-release.yml @@ -0,0 +1,121 @@ +name: Prepare Release + +on: + workflow_dispatch: + inputs: + react_native_version: + description: 'React Native Version (x.y.z)' + required: true + pattern: '^\d+\.\d+\.\d+$' + proxy_version: + description: 'Airship Framework Proxy Version (x.y.z)' + required: true + pattern: '^\d+\.\d+\.\d+$' + ios_version: + description: 'iOS SDK Version (x.y.z)' + required: false + pattern: '^\d+\.\d+\.\d+$' + android_version: + description: 'Android SDK Version (x.y.z)' + required: false + pattern: '^\d+\.\d+\.\d+$' + draft: + description: 'Create as draft PR' + type: boolean + default: false + +permissions: + contents: write + pull-requests: write + +jobs: + prepare-release: + runs-on: macos-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Run Updates + run: | + ./scripts/update_version.sh "${{ github.event.inputs.react_native_version }}" || exit 1 + if [ -n "${{ github.event.inputs.proxy_version }}" ]; then + ./scripts/update_proxy_version.sh "${{ github.event.inputs.proxy_version }}" || exit 1 + fi + ./scripts/update_changelog.sh "${{ github.event.inputs.react_native_version }}" \ + $([ -n "${{ github.event.inputs.ios_version }}" ] && echo "--ios ${{ github.event.inputs.ios_version }}") \ + $([ -n "${{ github.event.inputs.android_version }}" ] && echo "--android ${{ github.event.inputs.android_version }}") || exit 1 + + - name: Verify Changes + id: verify + run: | + CHANGED_FILES=$(git diff --name-only) + if [ -z "$CHANGED_FILES" ]; then + echo "No files were changed!" + exit 1 + fi + echo "Changed files:" + echo "$CHANGED_FILES" + echo "changed_files<> $GITHUB_OUTPUT + echo "$CHANGED_FILES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Create Pull Request + id: create-pr + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: | + Release ${{ github.event.inputs.react_native_version }} + title: "Release ${{ github.event.inputs.react_native_version }}" + body: | + - Framework Proxy: ${{ github.event.inputs.proxy_version }} + - iOS SDK: ${{ github.event.inputs.ios_version }} + - Android SDK: ${{ github.event.inputs.android_version }} + + ## Changed Files: + ``` + ${{ steps.verify.outputs.changed_files }} + ``` + branch: release-${{ github.event.inputs.react_native_version }} + base: main + labels: | + release + automated pr + draft: ${{ github.event.inputs.draft }} + delete-branch: true + + - name: Handle Success + if: success() && steps.create-pr.outputs.pull-request-number + run: | + echo "Pull request created successfully" + echo "PR Number: ${{ steps.create-pr.outputs.pull-request-number }}" + echo "PR URL: ${{ steps.create-pr.outputs.pull-request-url }}" + + - name: Slack Notification (Success) + if: success() && steps.create-pr.outputs.pull-request-number + uses: homoluctus/slatify@master + with: + type: success + job_name: ":tada: React Native plugin release pull request generated :tada:" + message: "@mobile-team A new React Native plugin release pull request for (v${{ github.event.inputs.react_native_version }}) is ready! :rocket:" + url: ${{ secrets.MOBILE_SLACK_WEBHOOK }} + + - name: Handle Failure + if: failure() + run: | + echo "::error::Release preparation failed. Please check the logs above for details." + exit 1 + + - name: Slack Notification (Failure) + if: failure() + uses: homoluctus/slatify@master + with: + type: failure + job_name: ":disappointed: React Native Plugin Release Failed :disappointed:" + message: "@crow The release preparation failed. Please check the workflow logs. :sob:" + url: ${{ secrets.MOBILE_SLACK_WEBHOOK }} diff --git a/scripts/update_changelog.sh b/scripts/update_changelog.sh new file mode 100755 index 00000000..d3bf43fc --- /dev/null +++ b/scripts/update_changelog.sh @@ -0,0 +1,90 @@ +#!/bin/bash +set -e +set -x + +SCRIPT_DIRECTORY="$(dirname "$0")" +ROOT_PATH=$SCRIPT_DIRECTORY/../ + +# First argument is always the version +VERSION=$1 +shift + +# Process remaining arguments as named parameters +while [[ $# -gt 0 ]]; do + case $1 in + --ios) + IOS_VERSION="$2" + shift 2 + ;; + --android) + ANDROID_VERSION="$2" + shift 2 + ;; + *) + echo "Unknown parameter: $1" + exit 1 + ;; + esac +done + +if [ -z "$VERSION" ]; then + echo "Error: Version is required" + exit 1 +fi + +RELEASE_DATE=$(date +"%B %-d, %Y") + +# Determine release type based on version +if [[ $VERSION =~ \.0\.0$ ]]; then + RELEASE_TYPE="Major" +elif [[ $VERSION =~ \.0$ ]]; then + RELEASE_TYPE="Minor" +else + RELEASE_TYPE="Patch" +fi + +# Create changelog entry +NEW_ENTRY="## Version $VERSION - $RELEASE_DATE\n\n" + +if [ -n "$IOS_VERSION" ] || [ -n "$ANDROID_VERSION" ]; then + NEW_ENTRY+="$RELEASE_TYPE release that updates" + + if [ -n "$ANDROID_VERSION" ]; then + NEW_ENTRY+=" the Android SDK to $ANDROID_VERSION" + fi + + if [ -n "$IOS_VERSION" ] && [ -n "$ANDROID_VERSION" ]; then + NEW_ENTRY+=" and" + fi + + if [ -n "$IOS_VERSION" ]; then + NEW_ENTRY+=" the iOS SDK to $IOS_VERSION" + fi + + NEW_ENTRY+="\n\n### Changes\n" + + if [ -n "$ANDROID_VERSION" ]; then + NEW_ENTRY+="- Updated Android SDK to [$ANDROID_VERSION](https://github.com/urbanairship/android-library/releases/tag/$ANDROID_VERSION" + fi + + if [ -n "$IOS_VERSION" ]; then + NEW_ENTRY+="\n" + NEW_ENTRY+="- Updated iOS SDK to [$IOS_VERSION](https://github.com/urbanairship/ios-library/releases/tag/$IOS_VERSION" + fi + +else + NEW_ENTRY+="$RELEASE_TYPE release." +fi + +# Create temporary file with new content +TEMP_FILE=$(mktemp) + +# Add the header line +echo "# React Native Module Changelog" > "$TEMP_FILE" +echo -e "\n$NEW_ENTRY" >> "$TEMP_FILE" + +# Append the rest of the existing changelog (skipping the header) +tail -n +2 "$ROOT_PATH/CHANGELOG.md" >> "$TEMP_FILE" + +# Replace original file with new content +mv "$TEMP_FILE" "$ROOT_PATH/CHANGELOG.md" diff --git a/scripts/update_proxy_version.sh b/scripts/update_proxy_version.sh new file mode 100755 index 00000000..1253383a --- /dev/null +++ b/scripts/update_proxy_version.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euxo pipefail + +SCRIPT_DIRECTORY="$(cd "$(dirname "$0")" && pwd)" +ROOT_PATH="$SCRIPT_DIRECTORY/.." + +PROXY_VERSION="$1" +if [ -z "$PROXY_VERSION" ]; then + echo "No proxy version supplied" + exit 1 +fi + +# Update Android gradle.properties +sed -i.bak -E "s/(Airship_airshipProxyVersion=)([^$]*)/\1$PROXY_VERSION/" "$ROOT_PATH/android/gradle.properties" + +# Update iOS podspec +sed -i.bak -E "s/(s\.dependency *\"AirshipFrameworkProxy\", *\")([^\"]*)(\")/\1$PROXY_VERSION\3/" "$ROOT_PATH/react-native-airship.podspec" + +find "$ROOT_PATH" -name "*.bak" -delete diff --git a/scripts/update_version.sh b/scripts/update_version.sh index 4ca530c3..f04570ec 100755 --- a/scripts/update_version.sh +++ b/scripts/update_version.sh @@ -1,30 +1,21 @@ -#!/bin/bash -ex - -REPO_PATH=`dirname "${0}"`/.. +REPO_PATH=$(dirname "${0}")/.. print_usage() { - echo "usage: $0 -p " + echo "usage: $0 " } -while getopts p:i:a: FLAG -do - case "${FLAG}" in - p) VERSION=${OPTARG} ;; - *) print_usage - exit 1 ;; - esac -done - -if [ -z $VERSION ] -then +if [ $# -lt 1 ]; then echo "$0: A package version is required" print_usage exit 1 fi +VERSION=$1 + +echo "Updating package version to $VERSION in package.json..." +sed -i '' "s/\"version\": \".*\",/\"version\": \"$VERSION\",/g" "$REPO_PATH/package.json" -sed -i '' "s/\version\": \".*\",/\version\": \"$VERSION\",/g" "$REPO_PATH/package.json" +echo "Updating version to $VERSION in ios/AirshipReactNative.swift..." sed -i '' "s/\(version:\ String *= *\)\".*\"/\1\"$VERSION\"/g" "$REPO_PATH/ios/AirshipReactNative.swift" -# Update iOS example dependencies -# sed -i '' "s/\(pod *'AirshipExtensions\/NotificationService', *'~> *\).*'/\1$IOS_VERSION'/g" example/ios/Podfile +echo "Version update complete."