Repository navigation
chore: release 1.2.1 #75
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: Build | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [master] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [master] | |
| permissions: | |
| contents: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: macos-latest | |
| args: --bundles dmg | |
| - platform: ubuntu-22.04 | |
| args: --bundles appimage,deb | |
| - platform: windows-latest | |
| args: --no-bundle | |
| runs-on: ${{ matrix.platform }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Linux system dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libappindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 11.13.1 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: src/celemod-ui/pnpm-lock.yaml | |
| - uses: dtolnay/rust-toolchain@nightly | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: src-tauri -> target | |
| - name: Install frontend dependencies | |
| run: pnpm --dir src/celemod-ui install --frozen-lockfile | |
| - name: Typecheck frontend | |
| run: pnpm --dir src/celemod-ui typecheck | |
| - name: Validate locked Rust dependencies | |
| run: cargo tree --locked | |
| - name: Build Windows executable | |
| if: runner.os == 'Windows' | |
| env: | |
| CMAKE_POLICY_VERSION_MINIMUM: 3.5 | |
| run: node src/celemod-ui/scripts/tauri.mjs build --no-bundle -- --locked | |
| - uses: tauri-apps/tauri-action@v0.6.2 | |
| if: runner.os != 'Windows' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CMAKE_POLICY_VERSION_MINIMUM: 3.5 | |
| with: | |
| projectPath: . | |
| args: ${{ matrix.args }} -- --locked | |
| tagName: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }} | |
| releaseName: ${{ startsWith(github.ref, 'refs/tags/') && format('CeleMod {0}', github.ref_name) || '' }} | |
| releaseDraft: false | |
| prerelease: false | |
| - name: Upload macOS bundles | |
| if: runner.os == 'macOS' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CeleMod-macos | |
| path: target/release/bundle/dmg/*.dmg | |
| if-no-files-found: error | |
| - name: Upload Linux bundles | |
| if: runner.os == 'Linux' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CeleMod-linux | |
| path: | | |
| target/release/bundle/appimage/*.AppImage | |
| target/release/bundle/deb/*.deb | |
| if-no-files-found: error | |
| - name: Rename Windows executable | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $version = (Get-Content version.txt -Raw).Trim() | |
| Move-Item target/release/cele-mod.exe "target/release/CeleMod_$version.exe" | |
| - name: Upload Windows executable artifact | |
| if: runner.os == 'Windows' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CeleMod-windows-exe | |
| path: target/release/CeleMod_*.exe | |
| if-no-files-found: error | |
| - name: Upload Windows executable to release | |
| if: runner.os == 'Windows' && startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: CeleMod ${{ github.ref_name }} | |
| body_path: CHANGELOG.md | |
| files: target/release/CeleMod_*.exe | |
| android: | |
| runs-on: windows-latest | |
| defaults: | |
| run: | |
| shell: pwsh | |
| env: | |
| # Share the toolchain installed by the action with android-env.ps1. | |
| CARGO_HOME: ${{ github.workspace }}/.local/cargo | |
| RUSTUP_HOME: ${{ github.workspace }}/.local/rustup | |
| CMAKE_POLICY_VERSION_MINIMUM: 3.5 | |
| IS_RELEASE: ${{ github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate Android release configuration | |
| if: env.IS_RELEASE == 'true' | |
| env: | |
| RELEASE_TAG: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }} | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| run: | | |
| $version = (Get-Content version.txt -Raw).Trim() | |
| if ($env:RELEASE_TAG -and $env:RELEASE_TAG -ne "v$version") { throw 'Release tag must match version.txt.' } | |
| foreach ($name in 'ANDROID_KEYSTORE_BASE64', 'ANDROID_KEYSTORE_PASSWORD', 'ANDROID_KEY_ALIAS', 'ANDROID_KEY_PASSWORD') { | |
| if (![Environment]::GetEnvironmentVariable($name)) { | |
| throw "Missing release signing secret: $name. See docs/android-release.md." | |
| } | |
| } | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 11.13.1 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: src/celemod-ui/pnpm-lock.yaml | |
| - uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: 8.0.x | |
| - uses: android-actions/setup-android@v3 | |
| with: | |
| # Google removed the legacy "tools" package from the SDK repository. | |
| packages: platform-tools | |
| - name: Install Android SDK and NDK | |
| run: | | |
| sdkmanager 'platforms;android-36' 'build-tools;36.0.0' 'ndk;28.2.13676358' | |
| if ($LASTEXITCODE) { throw 'Android SDK installation failed' } | |
| "NDK_HOME=$env:ANDROID_HOME/ndk/28.2.13676358" >> $env:GITHUB_ENV | |
| # Runtime asset preparation uses 7-Zip from the Windows runner image. | |
| 'C:/Program Files/7-Zip' >> $env:GITHUB_PATH | |
| - uses: dtolnay/rust-toolchain@nightly | |
| with: | |
| targets: aarch64-linux-android | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: . -> target | |
| key: android-arm64 | |
| # Fail before downloading/repacking the runtime if Cargo.lock is stale. | |
| - name: Validate locked Android dependencies | |
| run: cargo tree --locked --target aarch64-linux-android | |
| - name: Install frontend dependencies | |
| run: pnpm --dir src/celemod-ui install --frozen-lockfile | |
| - name: Test managed Android hooks | |
| run: dotnet run --project android/runtime/tests/managed -c Release | |
| - name: Prepare pinned Android runtime | |
| run: ./scripts/prepare-android-runtime.ps1 | |
| - name: Build Android APK | |
| run: ./scripts/build-android.ps1 -Release:($env:IS_RELEASE -eq 'true') | |
| - name: Collect debug APK | |
| if: env.IS_RELEASE != 'true' | |
| run: | | |
| $version = (Get-Content version.txt -Raw).Trim() | |
| New-Item -ItemType Directory -Force target/android | Out-Null | |
| Copy-Item src-tauri/gen/android/app/build/outputs/apk/arm64/debug/app-arm64-debug.apk "target/android/CeleMod_${version}_android-arm64-debug.apk" | |
| - name: Test Android runtime | |
| run: | | |
| . ./scripts/android-env.ps1 | |
| Push-Location src-tauri/gen/android | |
| try { | |
| ./gradlew.bat :app:testArm64DebugUnitTest -PcelemodPrebuiltRust=true --console=plain --no-daemon | |
| if ($LASTEXITCODE) { throw 'Android runtime tests failed' } | |
| } finally { Pop-Location } | |
| - name: Sign and verify release APK | |
| if: env.IS_RELEASE == 'true' | |
| env: | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| run: | | |
| $version = (Get-Content version.txt -Raw).Trim() | |
| $buildTools = "$env:ANDROID_HOME/build-tools/36.0.0" | |
| $keystore = Join-Path $env:RUNNER_TEMP 'celemod-release.keystore' | |
| $aligned = Join-Path $env:RUNNER_TEMP 'celemod-aligned.apk' | |
| $unsigned = 'src-tauri/gen/android/app/build/outputs/apk/arm64/release/app-arm64-release-unsigned.apk' | |
| New-Item -ItemType Directory -Force target/android | Out-Null | |
| $apk = "target/android/CeleMod_${version}_android-arm64.apk" | |
| try { | |
| [IO.File]::WriteAllBytes($keystore, [Convert]::FromBase64String($env:ANDROID_KEYSTORE_BASE64)) | |
| & "$buildTools/zipalign.exe" -f -P 16 4 $unsigned $aligned | |
| if ($LASTEXITCODE) { throw 'APK alignment failed' } | |
| & "$buildTools/apksigner.bat" sign --ks $keystore --ks-key-alias $env:ANDROID_KEY_ALIAS ` | |
| --ks-pass env:ANDROID_KEYSTORE_PASSWORD --key-pass env:ANDROID_KEY_PASSWORD --out $apk $aligned | |
| if ($LASTEXITCODE) { throw 'APK signing failed' } | |
| & "$buildTools/apksigner.bat" verify --verbose --print-certs $apk | |
| if ($LASTEXITCODE) { throw 'APK signature verification failed' } | |
| & "$buildTools/zipalign.exe" -c -P 16 4 $apk | |
| if ($LASTEXITCODE) { throw 'Signed APK alignment verification failed' } | |
| } finally { | |
| Remove-Item -LiteralPath $keystore, $aligned -Force -ErrorAction SilentlyContinue | |
| } | |
| - name: Generate APK checksums | |
| run: | | |
| Get-ChildItem target/android/*.apk | ForEach-Object { | |
| $hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| "$hash $($_.Name)" | Set-Content "$($_.FullName).sha256" -Encoding ascii | |
| } | |
| - name: Upload Android APK artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CeleMod-android-arm64 | |
| path: | | |
| target/android/*.apk | |
| target/android/*.sha256 | |
| if-no-files-found: error | |
| - name: Upload Android APK to release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: CeleMod ${{ github.ref_name }} | |
| body_path: CHANGELOG.md | |
| fail_on_unmatched_files: true | |
| files: | | |
| target/android/*.apk | |
| target/android/*.sha256 | |
| nightly: | |
| name: Publish nightly release | |
| needs: [build, android] | |
| if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| # Only the publisher is serialized; every push still gets a build. | |
| concurrency: | |
| group: nightly-release | |
| cancel-in-progress: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Test nightly publisher | |
| run: node --test scripts/publish-nightly.test.cjs | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: CeleMod-* | |
| path: nightly-artifacts | |
| - name: Replace nightly release | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const publish = require('./scripts/publish-nightly.cjs'); | |
| await publish({ github, context, core, directory: 'nightly-artifacts' }); |