diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 665c6ed..2b7208c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,17 +4,10 @@ on: push: tags: - 'v*' - workflow_dispatch: - inputs: - tag: - description: 'Existing release tag to update (e.g. v1.2.3)' - required: true - type: string - remove_old_assets: - description: 'Remove existing assets before uploading new ones' - required: false - default: true - type: boolean + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: true jobs: build-android: @@ -24,59 +17,33 @@ jobs: steps: #1 Checkout Repository - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 #2 Setup Java - name: Set Up Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: 'temurin' java-version: '21' + - name: Setup Gradle and caching + uses: gradle/actions/setup-gradle@v3 + #3 Setup Flutter - name: Set Up Flutter uses: subosito/flutter-action@v2 with: channel: 'stable' + cache: true #4 Install Dependencies - name: Install Dependencies - run: flutter pub get + run: flutter pub get --enforce-lockfile - - name: Generate Freezed Classes - run: flutter pub run build_runner build --delete-conflicting-outputs + - name: Generate code (build_runner) + run: dart run build_runner build --delete-conflicting-outputs -q - - name: Determine Release Tag and Version - id: meta - shell: bash - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - RELEASE_TAG="${{ inputs.tag }}" - else - RELEASE_TAG="${{ github.ref_name }}" - fi - echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV - # Derive VERSION_NAME (strip leading v) - VERSION_NAME="${RELEASE_TAG#v}" - echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV - - # Extract current build number from pubspec.yaml if present, otherwise 1 - CURRENT_VERSION_LINE=$(grep "^version:" pubspec.yaml || true) - CURRENT_BUILD=$(echo "$CURRENT_VERSION_LINE" | awk -F'+' '{print $2}') - if [[ -z "$CURRENT_BUILD" ]]; then CURRENT_BUILD=1; fi - - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - # Rebuild mode: compute a unique, monotonic build number without committing - # Use CI run number offset to avoid conflicts across multiple rebuilds - BASE_BUILD=$CURRENT_BUILD - RUN_NUM=${GITHUB_RUN_NUMBER:-1} - BUILD_NUMBER=$((BASE_BUILD + RUN_NUM)) - else - # Tag build: honor the build number committed in pubspec, default to CURRENT_BUILD - BUILD_NUMBER="$CURRENT_BUILD" - fi - echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV - echo "Using tag=$RELEASE_TAG version=$VERSION_NAME build=$BUILD_NUMBER" + #5 Setup Keystore - name: Create Keystore @@ -89,10 +56,10 @@ jobs: working-directory: android - name: Build APK - run: flutter build apk --split-per-abi --release --build-name "$VERSION_NAME" --build-number "$BUILD_NUMBER" + run: flutter build apk --split-per-abi --release - name: Build appBundle - run: flutter build appbundle --release --build-name "$VERSION_NAME" --build-number "$BUILD_NUMBER" + run: flutter build appbundle --release - name: Upload Artifacts uses: actions/upload-artifact@v4 @@ -104,50 +71,16 @@ jobs: build/app/outputs/flutter-apk/app-x86_64-release.apk build/app/outputs/bundle/release/app-release.aab - - name: Generate Release Notes - id: release_notes - run: | - # Get the previous tag - PREVIOUS_TAG=$(git tag --sort=-version:refname | head -2 | tail -1) - - # If no previous tag exists, use the first commit - if [ -z "$PREVIOUS_TAG" ]; then - PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD) - fi - - # Generate commit messages since the previous tag - echo "" >> release_notes.md - git log --pretty=format:"- %s (%h)" $PREVIOUS_TAG..${{ github.ref_name }} >> release_notes.md - - # Set the release notes as output - echo "RELEASE_NOTES<> $GITHUB_OUTPUT - cat release_notes.md >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - if: github.event_name == 'push' - - - name: Create or Update Release (tag push) - if: github.event_name == 'push' + - name: Create or Update Release uses: ncipollo/release-action@v1 with: artifacts: "build/app/outputs/flutter-apk/app-arm64-v8a-release.apk,build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk,build/app/outputs/flutter-apk/app-x86_64-release.apk,build/app/outputs/bundle/release/app-release.aab" - tag: ${{ env.RELEASE_TAG }} + tag: ${{ github.ref_name }} token: ${{ secrets.GITHUB_TOKEN }} - body: ${{ steps.release_notes.outputs.RELEASE_NOTES }} generateReleaseNotes: true allowUpdates: true makeLatest: true - - name: Update Existing Release (manual rebuild) - if: github.event_name == 'workflow_dispatch' - uses: ncipollo/release-action@v1 - with: - artifacts: "build/app/outputs/flutter-apk/app-arm64-v8a-release.apk,build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk,build/app/outputs/flutter-apk/app-x86_64-release.apk,build/app/outputs/bundle/release/app-release.aab" - tag: ${{ env.RELEASE_TAG }} - token: ${{ secrets.GITHUB_TOKEN }} - allowUpdates: true - removeArtifacts: ${{ inputs.remove_old_assets }} - makeLatest: true - omitBodyDuringUpdate: true build-ios: name: Build iOS @@ -156,52 +89,23 @@ jobs: steps: #1 Checkout Repository - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 #2 Setup Flutter - name: Set Up Flutter uses: subosito/flutter-action@v2 with: channel: 'stable' + cache: true #3 Install Dependencies - name: Install Dependencies - run: flutter pub get + run: flutter pub get --enforce-lockfile - - name: Generate Freezed Classes - run: flutter pub run build_runner build --delete-conflicting-outputs + - name: Generate code (build_runner) + run: dart run build_runner build --delete-conflicting-outputs -q - - name: Determine Release Tag and Version - id: meta - shell: bash - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - RELEASE_TAG="${{ inputs.tag }}" - else - RELEASE_TAG="${{ github.ref_name }}" - fi - echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV - # Derive VERSION_NAME (strip leading v) - VERSION_NAME="${RELEASE_TAG#v}" - echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV - - # Extract current build number from pubspec.yaml if present, otherwise 1 - CURRENT_VERSION_LINE=$(grep "^version:" pubspec.yaml || true) - CURRENT_BUILD=$(echo "$CURRENT_VERSION_LINE" | awk -F'+' '{print $2}') - if [[ -z "$CURRENT_BUILD" ]]; then CURRENT_BUILD=1; fi - - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - # Rebuild mode: compute a unique, monotonic build number without committing - # Use CI run number offset to avoid conflicts across multiple rebuilds - BASE_BUILD=$CURRENT_BUILD - RUN_NUM=${GITHUB_RUN_NUMBER:-1} - BUILD_NUMBER=$((BASE_BUILD + RUN_NUM)) - else - # Tag build: honor the build number committed in pubspec, default to CURRENT_BUILD - BUILD_NUMBER="$CURRENT_BUILD" - fi - echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV - echo "Using tag=$RELEASE_TAG version=$VERSION_NAME build=$BUILD_NUMBER" + #4 Setup Xcode - name: Setup Xcode @@ -209,16 +113,34 @@ jobs: with: xcode-version: latest-stable - #5 Install CocoaPods + #5 Cache CocoaPods + - name: Cache CocoaPods + uses: actions/cache@v4 + with: + path: | + ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('ios/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: Install CocoaPods run: | cd ios - pod install + pod install --verbose + + #6 Cache Xcode DerivedData + - name: Cache Xcode DerivedData + uses: actions/cache@v4 + with: + path: | + ~/Library/Developer/Xcode/DerivedData + key: ${{ runner.os }}-xcode-${{ hashFiles('ios/Podfile.lock', 'ios/Runner.xcodeproj/project.pbxproj', 'pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-xcode- - #6 Build iOS App (without signing) - name: Build iOS App run: | - flutter build ios --release --no-codesign --build-name "$VERSION_NAME" --build-number "$BUILD_NUMBER" + flutter build ios --release --no-codesign #7 Create IPA from App Bundle - name: Create IPA @@ -227,9 +149,8 @@ jobs: cd build/ios/Release-iphoneos mkdir Payload cp -r Runner.app Payload/ - zip -r ../ipa/conduit-${{ env.VERSION_NAME }}.ipa Payload + zip -r ../ipa/conduit.ipa Payload cd ../ipa - shasum -a 256 conduit-${{ env.VERSION_NAME }}.ipa > conduit-${{ env.VERSION_NAME }}.ipa.sha256 #8 Upload Artifacts - name: Upload Artifacts @@ -238,28 +159,13 @@ jobs: name: iOS-Release path: | build/ios/ipa/*.ipa - build/ios/ipa/*.sha256 - #9 Update Release (tag push) - - name: Update Release with IPA (tag push) - if: github.event_name == 'push' + #9 Update Release + - name: Update Release with IPA uses: ncipollo/release-action@v1 with: - artifacts: "build/ios/ipa/*.ipa,build/ios/ipa/*.sha256" - tag: ${{ env.RELEASE_TAG }} + artifacts: "build/ios/ipa/*.ipa" + tag: ${{ github.ref_name }} token: ${{ secrets.GITHUB_TOKEN }} allowUpdates: true makeLatest: true - - #10 Update Release (manual rebuild) - - name: Update Release with IPA (manual rebuild) - if: github.event_name == 'workflow_dispatch' - uses: ncipollo/release-action@v1 - with: - artifacts: "build/ios/ipa/*.ipa,build/ios/ipa/*.sha256" - tag: ${{ env.RELEASE_TAG }} - token: ${{ secrets.GITHUB_TOKEN }} - allowUpdates: true - removeArtifacts: ${{ inputs.remove_old_assets }} - makeLatest: true - omitBodyDuringUpdate: true diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile index df01d40..c48e0f2 100644 --- a/android/fastlane/Fastfile +++ b/android/fastlane/Fastfile @@ -15,24 +15,8 @@ default_platform(:android) -def write_android_changelog - require 'yaml' - pubspec_path = File.expand_path('../../pubspec.yaml', __dir__) - pubspec = YAML.load_file(pubspec_path) - version = pubspec['version'] - semver, build = version.split('+', 2) - tag = "v#{semver}" - link = "https://github.com/cogwheel0/conduit/releases/tag/#{tag}" - - changelog_dir = File.expand_path('metadata/android/en-US/changelogs', __dir__) - Dir.mkdir(changelog_dir) unless Dir.exist?(changelog_dir) - changelog_file = File.join(changelog_dir, "#{build}.txt") - File.write(changelog_file, link + "\n") -end - desc "Push a new release build to the Google Play" lane :release do - write_android_changelog upload_to_play_store( json_key: ENV['FASTLANE_JSON_KEY_PATH'], track: 'production', diff --git a/android/fastlane/metadata/android/en-US/changelogs/35.txt b/android/fastlane/metadata/android/en-US/changelogs/35.txt new file mode 100644 index 0000000..d51376b --- /dev/null +++ b/android/fastlane/metadata/android/en-US/changelogs/35.txt @@ -0,0 +1 @@ +https://github.com/cogwheel0/conduit/releases/tag/v2.1.10 diff --git a/ios/fastlane/Deliverfile b/ios/fastlane/Deliverfile index 653c44f..54697a7 100644 --- a/ios/fastlane/Deliverfile +++ b/ios/fastlane/Deliverfile @@ -6,3 +6,4 @@ skip_metadata(true) skip_screenshots(true) run_precheck_before_submit(false) ipa("../build/ios/ipa/conduit.ipa") +release_notes('en-US' => File.read('metadata/en-US/release_notes.txt')) diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index cb81751..0c67a81 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -14,15 +14,6 @@ # update_fastlane default_platform(:ios) lane :release do - require 'yaml' - pubspec_path = File.expand_path('../../pubspec.yaml', __dir__) - pubspec = YAML.load_file(pubspec_path) - version = pubspec['version'] # e.g., "2.1.6+31" - semver, _build = version.split('+', 2) - tag = "v#{semver}" - link = "https://github.com/cogwheel0/conduit/releases/tag/#{tag}" - notes_path = File.expand_path('metadata/en-US/release_notes.txt', __dir__) - File.write(notes_path, link + "\n") app_store_connect_api_key( key_id: ENV['FASTLANE_API_KEY_ID'], issuer_id: ENV['FASTLANE_API_KEY_ISSUER_ID'], diff --git a/scripts/release.sh b/scripts/release.sh index a8a57e8..2584837 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -142,9 +142,23 @@ print_status "Updating pubspec.yaml to version: $NEW_VERSION+$NEW_BUILD" sed -i.bak "s/^version: .*/version: $NEW_VERSION+$NEW_BUILD/" pubspec.yaml rm pubspec.yaml.bak +# Generate Fastlane changelogs +print_status "Generating Fastlane changelogs..." +LINK="https://github.com/cogwheel0/conduit/releases/tag/$TAG_VERSION" + +# Android changelog (by build number) +ANDROID_CHANGELOG_DIR="android/fastlane/metadata/android/en-US/changelogs" +mkdir -p "$ANDROID_CHANGELOG_DIR" +echo "$LINK" > "$ANDROID_CHANGELOG_DIR/$NEW_BUILD.txt" + +# iOS release notes +IOS_NOTES_PATH="ios/fastlane/metadata/en-US/release_notes.txt" +mkdir -p "$(dirname "$IOS_NOTES_PATH")" +echo "$LINK" > "$IOS_NOTES_PATH" + # Commit changes print_status "Committing changes..." -git add pubspec.yaml +git add pubspec.yaml "$ANDROID_CHANGELOG_DIR/$NEW_BUILD.txt" "$IOS_NOTES_PATH" git commit -m "chore: bump version to $NEW_VERSION" git push origin main