fix(*) #270
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: app-build-action | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| description: 'Tag name for the release' | |
| required: false | |
| default: 'v1.0.0' | |
| push: | |
| tags: | |
| - "v*" | |
| jobs: | |
| # ========================================================= | |
| # ANDROID | |
| # ========================================================= | |
| build-android: | |
| runs-on: macos-latest | |
| strategy: | |
| matrix: | |
| branch: [master, fvp] | |
| steps: | |
| - name: 签出代码 | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ matrix.branch }} | |
| - name: 下载Android keystore | |
| id: android_keystore | |
| uses: timheuer/base64-to-file@v1.2 | |
| with: | |
| fileName: key.jks | |
| encodedString: ${{ secrets.KEYSTORE_BASE64 }} | |
| - name: 创建key.properties | |
| run: | | |
| echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties | |
| echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> android/key.properties | |
| echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties | |
| echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties | |
| - name: 设置JAVA环境 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'zulu' | |
| java-version: "17" | |
| cache: 'gradle' | |
| - name: 设置Flutter环境 | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| cache: true | |
| - name: 更新Flutter packages | |
| run: flutter pub get | |
| - name: 打包 APK | |
| run: flutter build apk --release --split-per-abi | |
| - name: 重命名 APK | |
| shell: bash | |
| run: | | |
| cd build/app/outputs/flutter-apk | |
| if [ "${{ matrix.branch }}" = "fvp" ]; then | |
| for f in app-*-release.apk; do | |
| mv "$f" "${f/-release.apk/-fvp.apk}" | |
| done | |
| fi | |
| - name: 上传 APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-apks-${{ matrix.branch }} | |
| path: build/app/outputs/flutter-apk/*.apk | |
| retention-days: 1 | |
| # ========================================================= | |
| # WINDOWS | |
| # ========================================================= | |
| build-windows: | |
| runs-on: windows-latest | |
| strategy: | |
| matrix: | |
| branch: [master, fvp] | |
| steps: | |
| - name: 签出代码 | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ matrix.branch }} | |
| - name: Decode MSIX Certificate | |
| shell: pwsh | |
| run: | | |
| $certBase64 = "${{ secrets.CERTIFICATE }}".Trim() -replace '\s+', '' | |
| if ([string]::IsNullOrEmpty($certBase64)) { | |
| Write-Error "Secret is empty!" | |
| exit 1 | |
| } | |
| $certBytes = [System.Convert]::FromBase64String($certBase64) | |
| $certPath = Join-Path -Path (Get-Location) -ChildPath "certificate.pfx" | |
| [IO.File]::WriteAllBytes($certPath, $certBytes) | |
| echo "FINAL_CERT_PATH=$certPath" >> $env:GITHUB_ENV | |
| - name: Update make_config.yaml | |
| shell: pwsh | |
| run: | | |
| $configPath = "windows/packaging/msix/make_config.yaml" | |
| $absolutePath = "${{ env.FINAL_CERT_PATH }}".Replace('\', '/') | |
| if (Test-Path $configPath) { | |
| $content = Get-Content $configPath -Raw | |
| $content = $content -replace 'certificate_path:\s*.*', "certificate_path: $absolutePath" | |
| Set-Content $configPath $content | |
| Write-Host "Success: certificate_path set to $absolutePath" | |
| } | |
| else { | |
| Write-Error "Config file not found!" | |
| exit 1 | |
| } | |
| - name: 设置Flutter环境 | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| cache: true | |
| - name: 启用 Flutter Windows | |
| run: flutter config --enable-windows-desktop | |
| - name: 更新Flutter packages | |
| run: flutter pub get | |
| - name: Install Inno Setup | |
| run: | | |
| $url = "https://jrsoftware.org/download.php/is.exe" | |
| $output = "${{ runner.temp }}\innosetup.exe" | |
| Invoke-WebRequest -Uri $url -OutFile $output | |
| Start-Process -FilePath $output -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART" -Wait | |
| echo "C:\Program Files (x86)\Inno Setup 6" >> $env:GITHUB_PATH | |
| - name: Copy Chinese language pack | |
| run: | | |
| $source = "windows\packaging\exe\ChineseSimplified.isl" | |
| $target = "C:\Program Files (x86)\Inno Setup 6\Languages\ChineseSimplified.isl" | |
| if (Test-Path $source) { | |
| Copy-Item $source $target -Force | |
| } | |
| - name: Install fastforge | |
| run: dart pub global activate fastforge | |
| - name: Get version | |
| id: get_version | |
| shell: pwsh | |
| run: | | |
| $lines = Get-Content pubspec.yaml | |
| foreach ($line in $lines) { | |
| if ($line -match '^\s*version:\s*(\S+)') { | |
| $v = $matches[1] -replace '[`"''`]', '' | |
| "version=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| exit 0 | |
| } | |
| } | |
| Write-Error "Version not found" | |
| exit 1 | |
| - name: Package Windows | |
| run: fastforge package --platform windows --targets exe,msix | |
| - name: Rename installers | |
| shell: pwsh | |
| run: | | |
| $VERSION = "${{ steps.get_version.outputs.version }}" | |
| $DIST_DIR = "dist" | |
| $SUFFIX = "" | |
| if ("${{ matrix.branch }}" -eq "fvp") { | |
| $SUFFIX = "-fvp" | |
| } | |
| # EXE | |
| $EXE_FILE = Get-ChildItem $DIST_DIR -Recurse -Filter "*.exe" | Select-Object -First 1 | |
| if ($EXE_FILE) { | |
| Copy-Item $EXE_FILE.FullName "PureLive-$VERSION$SUFFIX-windows-x64-setup.exe" | |
| } | |
| # MSIX | |
| $MSIX_FILE = Get-ChildItem $DIST_DIR -Recurse -Filter "*.msix" | Select-Object -First 1 | |
| if ($MSIX_FILE) { | |
| Copy-Item $MSIX_FILE.FullName "PureLive-$VERSION$SUFFIX-windows-x64.msix" | |
| } | |
| - name: 上传 Windows 安装包 | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-installer-${{ matrix.branch }} | |
| path: | | |
| PureLive-*.exe | |
| PureLive-*.msix | |
| retention-days: 1 | |
| # ========================================================= | |
| # MACOS | |
| # ========================================================= | |
| build-macos: | |
| runs-on: macos-latest | |
| strategy: | |
| matrix: | |
| branch: [master, fvp] | |
| steps: | |
| - name: 签出代码 | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ matrix.branch }} | |
| - name: Set suffix | |
| id: suffix | |
| shell: bash | |
| run: | | |
| if [ "${{ matrix.branch }}" = "fvp" ]; then | |
| echo "suffix=-fvp" >> $GITHUB_OUTPUT | |
| else | |
| echo "suffix=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: 设置Flutter环境 | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| cache: true | |
| - name: 更新Flutter packages | |
| run: flutter pub get | |
| - name: Build macOS | |
| run: flutter build macos --release -v | |
| - name: Get version | |
| id: get_version | |
| run: | | |
| VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //; s/[`"'"'"']//g') | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Install create-dmg | |
| run: brew install create-dmg | |
| - name: Create DMG | |
| run: | | |
| create-dmg \ | |
| --volname "PureLive" \ | |
| --window-pos 200 120 \ | |
| --window-size 800 400 \ | |
| --icon-size 100 \ | |
| --app-drop-link 600 185 \ | |
| "PureLive-${{ steps.get_version.outputs.version }}${{ steps.suffix.outputs.suffix }}-macOS.dmg" \ | |
| "build/macos/Build/Products/Release/纯粹直播.app" | |
| - name: 上传 DMG | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-dmg-${{ matrix.branch }} | |
| path: PureLive-*.dmg | |
| retention-days: 1 | |
| # ========================================================= | |
| # RELEASE | |
| # ========================================================= | |
| publish-release: | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build-android | |
| - build-windows | |
| - build-macos | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: 签出代码 | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: master | |
| - name: 下载所有构建产物 | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: 读取版本描述 | |
| id: version | |
| uses: juliangruber/read-file-action@v1 | |
| with: | |
| path: assets/version.json | |
| - name: 构建 Release Body | |
| id: release_body | |
| run: | | |
| cat << 'EOF' > release_body.txt | |
| # 纯粹直播 ${{ github.ref_name }} | |
| ### 📥 快速下载 | |
| |版本|下载地址| | |
| |---|---| | |
| |TV版|[pure_live_TV](https://github.com/liuchuancong/pure_live_TV/releases/latest)| | |
| |Windows/macOS/Android版|[pure_live](https://github.com/liuchuancong/pure_live/releases/latest)| | |
| ### 🖥️ Windows 版 | |
| - **EXE 安装包**:适合所有用户,自动创建快捷方式 | |
| - **MSIX 包**:现代应用格式,支持干净卸载(需 Windows 10/11) | |
| - 适配:Win10/11 (x64),自动创建桌面快捷方式 | |
| - 功能:多直播源、WebDAV、弹幕显示 | |
| - 快捷键:空格(播放/暂停) \| ESC(全屏切换) \| 上下键(音量) \| R(刷新) | |
| ### 🍎 macOS 版 | |
| 感谢 RebornQ 开发 | 适配:macOS 10.15+ (x64) | 同 Windows 核心功能 | |
| ### 📱 Android 版 | |
| 适配:Android 6.0+ | 功能:WebDAV、多播放器切换、弹幕、应用内更新 | |
| ### 📺 TV 版 | |
| 适配:Android TV 6.0+ | 功能:直播源同步、多播放器、弹幕、应用内更新 | |
| ### 📝 本次更新 | |
| ${{ fromJson(steps.version.outputs.content).version_desc }} | |
| EOF | |
| echo "body_path=$(pwd)/release_body.txt" >> $GITHUB_OUTPUT | |
| - name: 上传至 Release | |
| uses: softprops/action-gh-release@v2.2.1 | |
| with: | |
| name: ${{ github.event.inputs.tag_name || github.ref_name }} | |
| body_path: ${{ steps.release_body.outputs.body_path }} | |
| prerelease: false | |
| token: ${{ secrets.TOKEN }} | |
| files: | | |
| artifacts/android-apks-master/*.apk | |
| artifacts/android-apks-fvp/*.apk | |
| artifacts/windows-installer-master/*.exe | |
| artifacts/windows-installer-master/*.msix | |
| artifacts/windows-installer-fvp/*.exe | |
| artifacts/windows-installer-fvp/*.msix | |
| artifacts/macos-dmg-master/*.dmg | |
| artifacts/macos-dmg-fvp/*.dmg | |
| - name: 输出状态 | |
| if: always() | |
| run: 'echo "✅ Release published with status: ${{ job.status }}"' |