From 8f14ff169a429260734ef437799a13c1e1db3aec Mon Sep 17 00:00:00 2001 From: Amonoman Date: Sat, 2 May 2026 18:24:03 +0200 Subject: [PATCH] Aktualisieren von release.yml --- .github/workflows/release.yml | 505 +--------------------------------- 1 file changed, 5 insertions(+), 500 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4769f2ec..e2d0a080 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Release +name: Build Android on: push: @@ -12,52 +12,18 @@ on: default: "v1.0.0" jobs: - # Get version first (quick job) - get-version: - runs-on: ubuntu-latest - outputs: - version: ${{ steps.version.outputs.version }} - is_prerelease: ${{ steps.version.outputs.is_prerelease }} - steps: - - name: Get version - id: version - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - VERSION="${{ github.event.inputs.version }}" - else - VERSION="${GITHUB_REF#refs/tags/}" - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - - # Check if version contains -preview, -beta, -rc, or -alpha (NOT -hotfix) - VERSION_LOWER=$(echo "$VERSION" | tr '[:upper:]' '[:lower:]') - if [[ "$VERSION_LOWER" == *"-preview"* ]] || [[ "$VERSION_LOWER" == *"-beta"* ]] || [[ "$VERSION_LOWER" == *"-rc"* ]] || [[ "$VERSION_LOWER" == *"-alpha"* ]]; then - echo "is_prerelease=true" >> $GITHUB_OUTPUT - echo "Detected pre-release version: $VERSION" - else - echo "is_prerelease=false" >> $GITHUB_OUTPUT - echo "Detected stable version: $VERSION" - fi - - # Android and iOS build in PARALLEL build-android: runs-on: ubuntu-latest - needs: get-version - steps: - name: Free disk space run: | - # Remove large unused tools (~15GB total) sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc sudo rm -rf /opt/hostedtoolcache/CodeQL sudo rm -rf /usr/local/share/boost sudo rm -rf /usr/share/swift sudo rm -rf /usr/local/.ghcup - # Clean docker images sudo docker image prune --all --force - # Show available space - df -h - name: Checkout repository uses: actions/checkout@v6 @@ -74,7 +40,6 @@ jobs: go-version: "1.25.8" cache-dependency-path: go_backend/go.sum - # Cache Gradle for faster builds - name: Cache Gradle uses: actions/cache@v5 with: @@ -82,22 +47,11 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: gradle-${{ runner.os }}- - name: Install Android SDK & NDK run: | - # Use pre-installed Android SDK on GitHub runners - echo "ANDROID_HOME=$ANDROID_HOME" - echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" - - # Accept licenses yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses || true - - # Install NDK r29 (supports 16KB page size for Android 15+) - # Platform android-36 and build-tools 36.0.0 for targetSdk 36 (Android 16) $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "ndk;29.0.14206865" "platforms;android-36" "build-tools;36.0.0" - - # Set NDK path echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> $GITHUB_ENV - name: Install gomobile @@ -122,460 +76,11 @@ jobs: - name: Get Flutter dependencies run: flutter pub get - - name: Generate app icons - run: dart run flutter_launcher_icons - - - name: Build APK (Release - unsigned) - run: | - flutter build apk --release --split-per-abi || true - # Verify APKs were created - ls -la build/app/outputs/flutter-apk/ - if [ ! -f "build/app/outputs/flutter-apk/app-arm64-v8a-release.apk" ]; then - echo "ERROR: APK not found!" - exit 1 - fi - - - name: Sign APKs - uses: r0adkll/sign-android-release@v1 - id: sign_arm64 - with: - releaseDirectory: build/app/outputs/flutter-apk - signingKeyBase64: ${{ secrets.KEYSTORE_BASE64 }} - alias: ${{ secrets.KEY_ALIAS }} - keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }} - keyPassword: ${{ secrets.KEY_PASSWORD }} - env: - BUILD_TOOLS_VERSION: "36.0.0" - - - name: Rename APKs - run: | - VERSION=${{ needs.get-version.outputs.version }} - cd build/app/outputs/flutter-apk - # Signed files have -signed suffix - mv app-arm64-v8a-release-signed.apk SpotiFLAC-${VERSION}-arm64.apk || mv app-arm64-v8a-release.apk SpotiFLAC-${VERSION}-arm64.apk || true - mv app-armeabi-v7a-release-signed.apk SpotiFLAC-${VERSION}-arm32.apk || mv app-armeabi-v7a-release.apk SpotiFLAC-${VERSION}-arm32.apk || true - mv app-release-signed.apk SpotiFLAC-${VERSION}-universal.apk || mv app-release.apk SpotiFLAC-${VERSION}-universal.apk || true - ls -la + - name: Build APK (Only arm64) + run: flutter build apk --release --target-platform android-arm64 - name: Upload APK artifact uses: actions/upload-artifact@v6 with: - name: android-apk - path: build/app/outputs/flutter-apk/SpotiFLAC-*.apk - - build-ios: - runs-on: macos-15 - needs: get-version # Only depends on version, NOT android build! - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Select Xcode 26.1.1 - run: | - sudo xcode-select -s /Applications/Xcode_26.1.1.app - xcodebuild -version - - - name: Setup Go - uses: actions/setup-go@v6 - with: - go-version: "1.25.8" - cache-dependency-path: go_backend/go.sum - - # Cache CocoaPods - - name: Cache CocoaPods - uses: actions/cache@v5 - with: - path: ios/Pods - key: pods-${{ runner.os }}-${{ hashFiles('ios/Podfile.lock') }} - restore-keys: pods-${{ runner.os }}- - - - name: Install gomobile - run: | - go install golang.org/x/mobile/cmd/gomobile@latest - gomobile init - - - name: Build Go backend for iOS - working-directory: go_backend - run: | - mkdir -p ../ios/Frameworks - gomobile bind -target=ios -tags ios -o ../ios/Frameworks/Gobackend.xcframework . - env: - CGO_ENABLED: 1 - - - name: Verify XCFramework created - run: | - ls -la ios/Frameworks/ - ls -la ios/Frameworks/Gobackend.xcframework/ || (echo "ERROR: XCFramework not found!" && exit 1) - - - name: Add XCFramework to Xcode project - run: | - # Install xcodeproj gem for modifying Xcode project - sudo gem install xcodeproj - - # Create Ruby script to add framework - cat > add_framework.rb << 'EOF' - require 'xcodeproj' - - project_path = 'ios/Runner.xcodeproj' - project = Xcodeproj::Project.open(project_path) - - # Get the main target - target = project.targets.find { |t| t.name == 'Runner' } - - # Get or create Frameworks group - frameworks_group = project.main_group.find_subpath('Frameworks', true) - frameworks_group ||= project.main_group.new_group('Frameworks') - - # Add XCFramework reference - framework_path = 'Frameworks/Gobackend.xcframework' - framework_ref = frameworks_group.new_file(framework_path, :project) - - # Add to frameworks build phase - frameworks_build_phase = target.frameworks_build_phase - frameworks_build_phase.add_file_reference(framework_ref) - - # Add to embed frameworks build phase - embed_phase = target.build_phases.find { |p| p.is_a?(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase) && p.name == 'Embed Frameworks' } - if embed_phase - build_file = embed_phase.add_file_reference(framework_ref) - build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] } - end - - project.save - puts "Successfully added Gobackend.xcframework to Xcode project" - EOF - - ruby add_framework.rb - - - name: Setup Flutter - uses: subosito/flutter-action@v2 - with: - channel: "stable" - cache: true - - - name: Get Flutter dependencies - run: flutter pub get - - - name: Generate app icons - run: dart run flutter_launcher_icons - - - name: Build iOS (unsigned) - run: | - # Build Flutter iOS without codesigning - flutter build ios --release --no-codesign --config-only - - # Use xcodebuild with code signing disabled - cd ios - xcodebuild -workspace Runner.xcworkspace \ - -scheme Runner \ - -configuration Release \ - -sdk iphoneos \ - -destination 'generic/platform=iOS' \ - -archivePath build/Runner.xcarchive \ - archive \ - CODE_SIGNING_ALLOWED=NO \ - CODE_SIGNING_REQUIRED=NO \ - CODE_SIGN_IDENTITY="" \ - DEVELOPMENT_TEAM="" - - - name: Create IPA - run: | - VERSION=${{ needs.get-version.outputs.version }} - mkdir -p build/ios/ipa - cd ios/build/Runner.xcarchive/Products/Applications - mkdir Payload - cp -r Runner.app Payload/ - # Use absolute path to avoid relative path issues - zip -r $GITHUB_WORKSPACE/build/ios/ipa/SpotiFLAC-${VERSION}-ios-unsigned.ipa Payload - rm -rf Payload - - - name: Verify IPA created - run: | - ls -la build/ios/ipa/ - VERSION=${{ needs.get-version.outputs.version }} - if [ ! -f "build/ios/ipa/SpotiFLAC-${VERSION}-ios-unsigned.ipa" ]; then - echo "ERROR: IPA not created!" - exit 1 - fi - - - name: Upload IPA artifact - uses: actions/upload-artifact@v6 - with: - name: ios-ipa - path: build/ios/ipa/SpotiFLAC-*.ipa - - create-release: - runs-on: ubuntu-latest - needs: [get-version, build-android, build-ios] - permissions: - contents: write - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 # Full history needed for git-cliff - - - name: Generate changelog with git-cliff - id: changelog - uses: orhun/git-cliff-action@v4 - with: - config: cliff.toml - args: --latest --strip header - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OUTPUT: /tmp/changelog.txt - - - name: Show generated changelog - run: | - echo "Generated changelog:" - cat /tmp/changelog.txt - - - name: Download Android APK - uses: actions/download-artifact@v7 - with: - name: android-apk - path: ./release - - - name: Download iOS IPA - uses: actions/download-artifact@v7 - with: - name: ios-ipa - path: ./release - - - name: Prepare release body - run: | - VERSION=${{ needs.get-version.outputs.version }} - REPO_OWNER="${{ github.repository_owner }}" - REPO_NAME="${{ github.event.repository.name }}" - CURRENT_REF=$(git rev-list -n 1 "$VERSION" 2>/dev/null || git rev-parse HEAD) - PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${CURRENT_REF}^" 2>/dev/null || true) - - # Start with git-cliff changelog, but replace its compare footer with a - # deterministic previous-tag lookup from git. - sed '/^## [0-9][0-9.[:alpha:]-]*$/d; /^\*\*Full Changelog\*\*/d' /tmp/changelog.txt > /tmp/release_body.txt - - if [ -n "$PREVIOUS_TAG" ]; then - printf '\n**Full Changelog**: [%s...%s](https://github.com/%s/%s/compare/%s...%s)\n' \ - "$PREVIOUS_TAG" "$VERSION" "$REPO_OWNER" "$REPO_NAME" "$PREVIOUS_TAG" "$VERSION" \ - >> /tmp/release_body.txt - fi - - # Append download section - cat >> /tmp/release_body.txt << FOOTER - - --- - - ### Downloads - - #### Android - - **arm64**: \`SpotiFLAC-${VERSION}-arm64.apk\` (recommended for modern devices) - - **arm32**: \`SpotiFLAC-${VERSION}-arm32.apk\` (older devices) - - #### iOS - - **iOS**: \`SpotiFLAC-${VERSION}-ios-unsigned.ipa\` (sideload required) - - ### Installation - **Android**: Enable "Install from unknown sources" and install the APK - **iOS**: Use AltStore, Sideloadly, or similar tools to sideload the IPA - - ![arm64](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-arm64.apk?style=flat-square&logo=android&label=arm64&color=3DDC84) ![arm32](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-arm32.apk?style=flat-square&logo=android&label=arm32&color=3DDC84) ![iOS](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-ios-unsigned.ipa?style=flat-square&logo=apple&label=iOS&color=0078D6) - FOOTER - - echo "Release body:" - cat /tmp/release_body.txt - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.get-version.outputs.version }} - name: SpotiFLAC ${{ needs.get-version.outputs.version }} - body_path: /tmp/release_body.txt - files: ./release/* - draft: false - prerelease: ${{ needs.get-version.outputs.is_prerelease == 'true' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - update-altstore: - runs-on: ubuntu-latest - needs: [get-version, build-ios, create-release] - if: ${{ needs.get-version.outputs.is_prerelease != 'true' }} - permissions: - contents: write - - steps: - - name: Checkout main branch - uses: actions/checkout@v6 - with: - ref: main - - - name: Download iOS IPA - uses: actions/download-artifact@v7 - with: - name: ios-ipa - path: ./release - - - name: Update apps.json - run: | - VERSION="${{ needs.get-version.outputs.version }}" - VERSION_NUM="${VERSION#v}" - DATE=$(date -u +%Y-%m-%d) - IPA_FILE=$(find ./release -name "*ios*.ipa" | head -1) - - if [ -z "$IPA_FILE" ]; then - echo "WARNING: IPA file not found, skipping apps.json update" - exit 0 - fi - - IPA_SIZE=$(stat -c%s "$IPA_FILE" 2>/dev/null || stat -f%z "$IPA_FILE") - - if [ ! -f apps.json ]; then - echo "WARNING: apps.json not found on main, skipping" - exit 0 - fi - - jq --arg ver "$VERSION_NUM" \ - --arg date "$DATE" \ - --arg url "https://github.com/zarzet/SpotiFLAC-Mobile/releases/download/${VERSION}/SpotiFLAC-${VERSION}-ios-unsigned.ipa" \ - --argjson size "$IPA_SIZE" \ - '.apps[0].version = $ver | .apps[0].versionDate = $date | .apps[0].downloadURL = $url | .apps[0].size = $size' \ - apps.json > apps.json.tmp && mv apps.json.tmp apps.json - - echo "Updated apps.json:" - cat apps.json - - - name: Commit and push - run: | - VERSION="${{ needs.get-version.outputs.version }}" - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add apps.json - git diff --cached --quiet && echo "No changes to commit" || \ - (git commit -m "chore: update AltStore source to ${VERSION}" && git push) - - notify-telegram: - runs-on: ubuntu-latest - needs: [get-version, create-release] - if: ${{ needs.get-version.outputs.is_prerelease != 'true' }} - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Download Android APK - uses: actions/download-artifact@v7 - with: - name: android-apk - path: ./release - - - name: Download iOS IPA - uses: actions/download-artifact@v7 - with: - name: ios-ipa - path: ./release - - - name: Generate changelog with git-cliff for Telegram - uses: orhun/git-cliff-action@v4 - with: - config: cliff.toml - args: --latest --strip all - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OUTPUT: /tmp/cliff_tg.txt - - - name: Convert changelog for Telegram - id: changelog - run: | - if [ ! -s /tmp/cliff_tg.txt ]; then - echo "See release notes on GitHub for details." > /tmp/changelog.txt - else - # Convert Markdown to Telegram HTML - CHANGELOG=$(cat /tmp/cliff_tg.txt | \ - sed '/^## [0-9][0-9.[:alpha:]-]*$/d' | \ - sed '/^\*\*Full Changelog\*\*/d' | \ - sed 's/ by \[@[^]]*\](https:\/\/github\.com\/[^)]*)//g' | \ - sed 's/ by @[A-Za-z0-9_-]\+//g' | \ - sed 's/\[#\([0-9]*\)\]([^)]*)/#\1/g' | \ - sed 's/\[@\([^]]*\)\]([^)]*)/@\1/g' | \ - sed 's/&/\&/g' | \ - sed 's//\>/g' | \ - sed 's/\*\*\([^*]*\)\*\*/\1<\/b>/g' | \ - sed 's/^### \(.*\)$/\1<\/b>/g' | \ - sed 's/^## \(.*\)$/\1<\/b>/g' | \ - sed 's/^- /• /g') - - # Truncate for Telegram 4096 char limit - CHANGELOG=$(echo "$CHANGELOG" | head -c 2500 | sed '$d') - echo "$CHANGELOG" > /tmp/changelog.txt - fi - - echo "Telegram changelog:" - cat /tmp/changelog.txt - - - name: Send to Telegram Channel - env: - TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} - TELEGRAM_CHANNEL_ID: ${{ secrets.TELEGRAM_CHANNEL_ID }} - run: | - VERSION=${{ needs.get-version.outputs.version }} - CHANGELOG=$(cat /tmp/changelog.txt) - - # Find APK files - ARM64_APK=$(find ./release -name "*arm64*.apk" | head -1) - ARM32_APK=$(find ./release -name "*arm32*.apk" | head -1) - - # Prepare message with changelog (HTML format) - printf '%s\n' \ - "SpotiFLAC Mobile ${VERSION} Released!" \ - "" \ - "What's New:" \ - "${CHANGELOG}" \ - "" \ - "View Release Notes" \ - > /tmp/telegram_message.txt - - MESSAGE=$(cat /tmp/telegram_message.txt) - - # Send message first (using HTML parse mode) - # Use --data-urlencode for proper encoding of special chars (+, &, etc.) - # Use || true to ensure file uploads continue even if message fails - curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ - --data-urlencode "chat_id=${TELEGRAM_CHANNEL_ID}" \ - --data-urlencode "text=${MESSAGE}" \ - --data-urlencode "parse_mode=HTML" \ - --data-urlencode "disable_web_page_preview=true" || true - - # Upload arm64 APK to channel - if [ -f "$ARM64_APK" ]; then - echo "Uploading arm64 APK to Telegram..." - curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \ - -F chat_id="${TELEGRAM_CHANNEL_ID}" \ - -F document=@"${ARM64_APK}" \ - -F caption="SpotiFLAC ${VERSION} - arm64 (recommended)" - fi - - # Upload arm32 APK to channel - if [ -f "$ARM32_APK" ]; then - echo "Uploading arm32 APK to Telegram..." - curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \ - -F chat_id="${TELEGRAM_CHANNEL_ID}" \ - -F document=@"${ARM32_APK}" \ - -F caption="SpotiFLAC ${VERSION} - arm32" - fi - - # Upload iOS IPA to channel - IOS_IPA=$(find ./release -name "*ios*.ipa" | head -1) - if [ -f "$IOS_IPA" ]; then - echo "Uploading iOS IPA to Telegram..." - curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \ - -F chat_id="${TELEGRAM_CHANNEL_ID}" \ - -F document=@"${IOS_IPA}" \ - -F caption="SpotiFLAC ${VERSION} - iOS (unsigned, sideload required)" - fi - - echo "Telegram notification sent!" + name: SpotiFLAC-arm64-apk + path: build/app/outputs/flutter-apk/app-release.apk