name: Build and Release on: workflow_dispatch: inputs: platform: description: Build target required: true default: all type: choice options: [all, quality, android, ios, macos, windows] push: tags: ['*'] concurrency: group: build-${{ github.ref }} cancel-in-progress: false permissions: contents: write env: FLUTTER_VERSION: '3.41.9' RELEASE_TAG: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.sha }} jobs: quality: name: Analyze and test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - run: flutter pub get - run: flutter analyze - run: flutter test android: name: Android release needs: quality if: github.event_name != 'workflow_dispatch' || inputs.platform == 'all' || inputs.platform == 'android' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: temurin java-version: '17' cache: gradle - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - name: Restore Android release keystore shell: bash env: KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} run: | set -euo pipefail test -n "$KEYSTORE_BASE64" && test -n "$KEYSTORE_PASSWORD" && test -n "$KEY_PASSWORD" && test -n "$KEY_ALIAS" printf '%s' "$KEYSTORE_BASE64" | base64 --decode > android/app/release.jks cat > android/key.properties < "$CERT_PATH" printf '%s' "$PROFILE_BASE64" | base64 --decode > "$PROFILE_PATH" printf '%s' "$EXPORT_OPTIONS_BASE64" | base64 --decode > ios/ExportOptions.plist security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security import "$CERT_PATH" -P "$CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles UUID=$(security cms -D -i "$PROFILE_PATH" | plutil -extract UUID raw -) cp "$PROFILE_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/$UUID.mobileprovision - run: flutter pub get - run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist - run: cp build/ios/ipa/*.ipa guangya_flutter-${{ env.RELEASE_TAG }}-ios.ipa - uses: actions/upload-artifact@v4 with: name: ios-ipa path: guangya_flutter-*-ios.ipa - name: Publish iOS release if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: files: guangya_flutter-*-ios.ipa macos: name: macOS release needs: quality if: github.event_name != 'workflow_dispatch' || inputs.platform == 'all' || inputs.platform == 'macos' runs-on: macos-14 steps: - uses: actions/checkout@v4 - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - name: Install macOS Developer ID certificate shell: bash env: CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_BASE64 }} CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} run: | set -euo pipefail test -n "$CERTIFICATE_BASE64" && test -n "$CERTIFICATE_PASSWORD" && test -n "$KEYCHAIN_PASSWORD" CERT_PATH="$RUNNER_TEMP/macos-release.p12" KEYCHAIN_PATH="$RUNNER_TEMP/macos-signing.keychain-db" printf '%s' "$CERTIFICATE_BASE64" | base64 --decode > "$CERT_PATH" security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security import "$CERT_PATH" -P "$CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - run: flutter pub get - run: flutter build macos --release - name: Sign and package macOS app shell: bash env: SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }} run: | set -euo pipefail test -n "$SIGNING_IDENTITY" APP=build/macos/Build/Products/Release/小黄鸭.app test -d "$APP" codesign --force --deep --options runtime --timestamp --sign "$SIGNING_IDENTITY" "$APP" ditto -c -k --sequesterRsrc --keepParent "$APP" guangya_flutter-${{ env.RELEASE_TAG }}-macos.zip - uses: actions/upload-artifact@v4 with: name: macos-app path: guangya_flutter-*-macos.zip - name: Publish macOS release if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: files: guangya_flutter-*-macos.zip windows: name: Windows release needs: quality if: github.event_name != 'workflow_dispatch' || inputs.platform == 'all' || inputs.platform == 'windows' runs-on: windows-2022 steps: - uses: actions/checkout@v4 - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - run: flutter pub get - run: flutter build windows --release - name: Package Windows release shell: pwsh run: Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath guangya_flutter-${{ env.RELEASE_TAG }}-windows-x64.zip - uses: actions/upload-artifact@v4 with: name: windows-x64 path: guangya_flutter-*-windows-x64.zip - name: Publish Windows release if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: files: guangya_flutter-*-windows-x64.zip