Skip to content

chore: release 1.2.1 #75

chore: release 1.2.1

chore: release 1.2.1 #75

Workflow file for this run

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' });