name: Release # Triggered by pushing a version tag, e.g. `git tag v0.22.0 && git push origin v0.22.0`. # Builds a Linux x86_64 tarball and a signed Android APK, then publishes # both as assets on a GitHub Release. Obtainium can track this repo's # releases and download the APK automatically. # # Required repository secrets (Settings → Secrets and variables → Actions): # ANDROID_KEYSTORE_BASE64 base64-encoded .jks file (see README for gen command) # ANDROID_KEYSTORE_PASSWORD password used with -storepass when creating the keystore # ANDROID_KEY_ALIAS alias used with -alias when creating the keystore # ANDROID_KEY_PASSWORD password used with -keypass when creating the keystore on: push: tags: - 'v*' permissions: contents: write # gh release create needs write access env: CARGO_TERM_COLOR: always RUSTFLAGS: "-D warnings" # --------------------------------------------------------------------------- # Job 1: Linux x86_64 binary + assets tarball # --------------------------------------------------------------------------- jobs: build-linux: name: Build · Linux x86_64 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust stable uses: dtolnay/rust-toolchain@stable - name: Install system deps run: | sudo apt-get update -qq sudo apt-get install -y --no-install-recommends \ libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev - name: Cache cargo registry + build artifacts uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: linux-release-${{ hashFiles('**/Cargo.lock') }} restore-keys: linux-release- - name: Build release binary run: cargo build --release -p solitaire_app - name: Package tarball run: | mkdir solitaire-quest cp target/release/solitaire_app solitaire-quest/ cp -r assets solitaire-quest/ tar -czf solitaire-quest-linux-x86_64.tar.gz solitaire-quest - uses: actions/upload-artifact@v4 with: name: linux path: solitaire-quest-linux-x86_64.tar.gz # --------------------------------------------------------------------------- # Job 2: Android APK (multi-arch) — release-built and signed via cargo-apk # --------------------------------------------------------------------------- build-android: name: Build · Android APK runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust stable + Android targets uses: dtolnay/rust-toolchain@stable with: targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android - name: Expose NDK root to cargo-apk # ANDROID_NDK_LATEST_HOME is set by the GitHub-hosted runner. # cargo-apk reads ANDROID_NDK_ROOT; write it to GITHUB_ENV so # all subsequent steps in this job inherit it. run: echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV - name: Cache cargo registry + cargo-apk binary + build artifacts uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git ~/.cargo/bin target key: android-release-${{ hashFiles('**/Cargo.lock') }} restore-keys: android-release- - name: Install cargo-apk # --locked: use the dependency versions cargo-apk was tested with. # cargo install is a no-op when the cached binary is already current. run: cargo install --locked cargo-apk - name: Inject release signing config # cargo-apk --release requires [package.metadata.android.signing.release] # in solitaire_app/Cargo.toml. Appended at CI time so secrets never # live in the repo. printf keeps every line inside the YAML run block, # avoiding the YAML parse error a heredoc with column-0 content causes. 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: | echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > release.keystore { printf '\n[package.metadata.android.signing.release]\n' printf 'path = "%s"\n' "${GITHUB_WORKSPACE}/release.keystore" printf 'keystore_password = "%s"\n' "$ANDROID_KEYSTORE_PASSWORD" printf 'key_alias = "%s"\n' "$ANDROID_KEY_ALIAS" printf 'key_password = "%s"\n' "$ANDROID_KEY_PASSWORD" } >> solitaire_app/Cargo.toml - name: Build and sign APK (release profile) run: cargo apk build -p solitaire_app --release - name: Stage APK for upload run: | cp target/release/apk/solitaire-quest.apk \ "solitaire-quest-${{ github.ref_name }}.apk" rm release.keystore - uses: actions/upload-artifact@v4 with: name: android path: solitaire-quest-${{ github.ref_name }}.apk # --------------------------------------------------------------------------- # Job 3: Create the GitHub Release once both builds succeed # --------------------------------------------------------------------------- release: name: Publish GitHub Release runs-on: ubuntu-latest needs: [build-linux, build-android] steps: - uses: actions/download-artifact@v4 with: name: linux - uses: actions/download-artifact@v4 with: name: android - name: Create GitHub Release env: GH_TOKEN: ${{ github.token }} run: | gh release create "${{ github.ref_name }}" \ --repo "${{ github.repository }}" \ --title "Solitaire Quest ${{ github.ref_name }}" \ --generate-notes \ "solitaire-quest-linux-x86_64.tar.gz" \ "solitaire-quest-${{ github.ref_name }}.apk"