mirror of
https://github.com/jellyfin/jellyfin-android.git
synced 2026-09-02 21:04:10 +03:00
Sign APK/AAB via Gradle build
This commit is contained in:
committed by
Niels van Velzen
parent
da02e7c93b
commit
fb7ebed903
@@ -10,93 +10,75 @@ jobs:
|
||||
name: Publish
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ contains(github.repository_owner, 'jellyfin') }}
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version-file: .tools-versions
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
|
||||
- name: Set JELLYFIN_VERSION
|
||||
run: echo "JELLYFIN_VERSION=$(echo ${GITHUB_REF#refs/tags/v} | tr / -)" >> $GITHUB_ENV
|
||||
|
||||
- name: Decode keystore
|
||||
run: echo "${{ secrets.KEYSTORE }}" | base64 --decode > keystore.jks
|
||||
|
||||
- name: Assemble release files
|
||||
run: ./gradlew assemble bundleProprietaryRelease versionTxt
|
||||
- name: Sign libre APK
|
||||
id: libreSign
|
||||
uses: r0adkll/sign-android-release@349ebdef58775b1e0d8099458af0816dc79b6407 # tag=v1
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "34.0.0"
|
||||
with:
|
||||
releaseDirectory: app/build/outputs/apk/libre/release
|
||||
signingKeyBase64: ${{ secrets.KEYSTORE }}
|
||||
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Sign proprietary APK
|
||||
id: proprietarySign
|
||||
uses: r0adkll/sign-android-release@349ebdef58775b1e0d8099458af0816dc79b6407 # tag=v1
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "34.0.0"
|
||||
with:
|
||||
releaseDirectory: app/build/outputs/apk/proprietary/release
|
||||
signingKeyBase64: ${{ secrets.KEYSTORE }}
|
||||
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Sign proprietary app bundle
|
||||
id: proprietaryBundleSign
|
||||
uses: r0adkll/sign-android-release@349ebdef58775b1e0d8099458af0816dc79b6407 # tag=v1
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "34.0.0"
|
||||
with:
|
||||
releaseDirectory: app/build/outputs/bundle/proprietaryRelease
|
||||
signingKeyBase64: ${{ secrets.KEYSTORE }}
|
||||
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
KEYSTORE_FILE: ${{ github.workspace }}/keystore.jks
|
||||
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
SIGNING_KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
|
||||
SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
run: ./gradlew assemble bundleRelease versionTxt
|
||||
|
||||
- name: Prepare release archive
|
||||
run: |
|
||||
mkdir -p build/jellyfin-publish
|
||||
mv app/build/outputs/apk/*/*/jellyfin-android-*-libre-debug.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/*/*/jellyfin-android-*-proprietary-debug.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/*/*/jellyfin-android-*-libre-release-unsigned.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/*/*/jellyfin-android-*-proprietary-release-unsigned.apk build/jellyfin-publish/
|
||||
mv ${{ steps.libreSign.outputs.signedReleaseFile }} build/jellyfin-publish/jellyfin-android-v${{ env.JELLYFIN_VERSION }}-libre-release.apk
|
||||
mv ${{ steps.proprietarySign.outputs.signedReleaseFile }} build/jellyfin-publish/jellyfin-android-v${{ env.JELLYFIN_VERSION }}-proprietary-release.apk
|
||||
mv ${{ steps.proprietaryBundleSign.outputs.signedReleaseFile }} build/jellyfin-publish/jellyfin-android-v${{ env.JELLYFIN_VERSION }}-proprietary-release.aab
|
||||
mv app/build/outputs/apk/libre/debug/jellyfin-android-*-libre-debug.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/libre/release/jellyfin-android-*-libre-release.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/bundle/libreRelease/jellyfin-android-*-libre-release.aab build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/proprietary/debug/jellyfin-android-*-proprietary-debug.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/apk/proprietary/release/jellyfin-android-*-proprietary-release.apk build/jellyfin-publish/
|
||||
mv app/build/outputs/bundle/proprietaryRelease/jellyfin-android-*-proprietary-release.aab build/jellyfin-publish/
|
||||
mv app/build/version.txt build/jellyfin-publish/
|
||||
|
||||
- name: Upload release archive to GitHub release
|
||||
uses: alexellis/upload-assets@13926a61cdb2cb35f5fdef1c06b8b591523236d3 # 0.4.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
|
||||
with:
|
||||
asset_paths: '["build/jellyfin-publish/*"]'
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh release upload "$GITHUB_REF_NAME" build/jellyfin-publish/* --clobber
|
||||
|
||||
- name: Configure deployment
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.REPO_KEY }}" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
- name: Upload release archive to repo.jellyfin.org
|
||||
uses: burnett01/rsync-deployments@66257cad6bfeb2171d3b6bfa6c9a22279dd9c3a1 # 8.0.5
|
||||
with:
|
||||
switches: -vrptz
|
||||
path: build/jellyfin-publish/
|
||||
remote_path: /srv/incoming/android/v${{ env.JELLYFIN_VERSION }}/
|
||||
remote_host: ${{ secrets.REPO_HOST }}
|
||||
remote_user: ${{ secrets.REPO_USER }}
|
||||
remote_key: ${{ secrets.REPO_KEY }}
|
||||
env:
|
||||
TARGET_PATH: /srv/incoming/android/v${{ env.JELLYFIN_VERSION }}/
|
||||
SOURCE_PATH: build/jellyfin-publish/
|
||||
run: rsync -vrptz -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no" "$SOURCE_PATH" "${{ secrets.REPO_USER }}@${{ secrets.REPO_HOST }}:$TARGET_PATH"
|
||||
|
||||
- name: Update repo.jellyfin.org symlinks
|
||||
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
||||
with:
|
||||
host: ${{ secrets.REPO_HOST }}
|
||||
username: ${{ secrets.REPO_USER }}
|
||||
key: ${{ secrets.REPO_KEY }}
|
||||
envs: JELLYFIN_VERSION
|
||||
script_stop: true
|
||||
script: |
|
||||
env:
|
||||
REPO_HOST: ${{ secrets.REPO_HOST }}
|
||||
REPO_USER: ${{ secrets.REPO_USER }}
|
||||
run: |
|
||||
ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no "${REPO_USER}@${REPO_HOST}" "bash -s" <<EOF
|
||||
if [ -d "/srv/repository/main/client/android/versions/v${{ env.JELLYFIN_VERSION }}" ] && [ -n "${{ env.JELLYFIN_VERSION }}" ]; then
|
||||
sudo rm -r /srv/repository/main/client/android/versions/v${{ env.JELLYFIN_VERSION }}
|
||||
fi
|
||||
sudo mv /srv/incoming/android/v${{ env.JELLYFIN_VERSION }} /srv/repository/main/client/android/versions/v${{ env.JELLYFIN_VERSION }}
|
||||
cd /srv/repository/main/client/android;
|
||||
sudo rm -rf *.apk version.txt;
|
||||
sudo ln -s versions/v${JELLYFIN_VERSION}/jellyfin-android-v${JELLYFIN_VERSION}-*.apk .;
|
||||
sudo ln -s versions/v${JELLYFIN_VERSION}/version.txt .;
|
||||
sudo ln -s versions/v${{ env.JELLYFIN_VERSION }}/jellyfin-android-v${{ env.JELLYFIN_VERSION }}-*.apk .;
|
||||
sudo ln -s versions/v${{ env.JELLYFIN_VERSION }}/version.txt .;
|
||||
EOF
|
||||
|
||||
+20
-7
@@ -39,23 +39,36 @@ android {
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
||||
val releaseSigningConfig = SigningHelper.loadSigningConfig(project)?.let { config ->
|
||||
signingConfigs.create("release") {
|
||||
storeFile = config.storeFile
|
||||
storePassword = config.storePassword
|
||||
keyAlias = config.keyAlias
|
||||
keyPassword = config.keyPassword
|
||||
signingConfigs {
|
||||
val keystoreFile = getProperty("keystore.file")
|
||||
val keystorePassword = getProperty("keystore.password")
|
||||
val signingKeyAlias = getProperty("signing.key.alias")
|
||||
val signingKeyPassword = getProperty("signing.key.password")
|
||||
|
||||
if (keystoreFile != null && keystorePassword != null && signingKeyAlias != null && signingKeyPassword != null) {
|
||||
create("release") {
|
||||
storeFile = file(keystoreFile)
|
||||
storePassword = keystorePassword
|
||||
keyAlias = signingKeyAlias
|
||||
keyPassword = signingKeyPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependenciesInfo {
|
||||
includeInBundle = false
|
||||
includeInApk = false
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
signingConfig = releaseSigningConfig
|
||||
signingConfig = signingConfigs.findByName("release")
|
||||
}
|
||||
|
||||
getByName("debug") {
|
||||
applicationIdSuffix = ".debug"
|
||||
isDebuggable = true
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* Helper function to retrieve configuration variable values
|
||||
*/
|
||||
fun Project.getProperty(name: String): String? {
|
||||
// sample.var --> SAMPLE_VAR
|
||||
val environmentName = name.uppercase().replace(".", "_")
|
||||
|
||||
return findProperty(name)?.toString() ?: System.getenv(environmentName) ?: null
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import org.gradle.api.Project
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
object SigningHelper {
|
||||
|
||||
fun loadSigningConfig(project: Project): Config? {
|
||||
val serializedKeystore = System.getenv("KEYSTORE") ?: return null
|
||||
val storeFile = try {
|
||||
project.file("/tmp/keystore.jks").apply {
|
||||
writeBytes(Base64.getDecoder().decode(serializedKeystore))
|
||||
}
|
||||
} catch (e: RuntimeException) {
|
||||
return null
|
||||
}
|
||||
val storePassword = System.getenv("KEYSTORE_PASSWORD") ?: return null
|
||||
val keyAlias = System.getenv("KEY_ALIAS") ?: return null
|
||||
val keyPassword = System.getenv("KEY_PASSWORD") ?: return null
|
||||
|
||||
return Config(
|
||||
storeFile,
|
||||
storePassword,
|
||||
keyAlias,
|
||||
keyPassword
|
||||
)
|
||||
}
|
||||
|
||||
data class Config(
|
||||
/**
|
||||
* Store file used when signing.
|
||||
*/
|
||||
val storeFile: File,
|
||||
|
||||
/**
|
||||
* Store password used when signing.
|
||||
*/
|
||||
val storePassword: String,
|
||||
|
||||
/**
|
||||
* Key alias used when signing.
|
||||
*/
|
||||
val keyAlias: String,
|
||||
|
||||
/**
|
||||
* Key password used when signing.
|
||||
*/
|
||||
val keyPassword: String
|
||||
)
|
||||
}
|
||||
@@ -10,29 +10,26 @@ import org.gradle.api.Project
|
||||
* v2.0.0 -> 2.0.0
|
||||
* null -> 0.0.0-dev.1 (unless different fallback set)
|
||||
*/
|
||||
fun Project.getVersionName(fallback: String = "0.0.0-dev.1"): String {
|
||||
val configuredVersion = System.getenv("JELLYFIN_VERSION")
|
||||
?: findProperty("jellyfin.version")?.toString()
|
||||
|
||||
return configuredVersion?.removePrefix("v") ?: fallback
|
||||
}
|
||||
fun Project.getVersionName(fallback: String = "0.0.0-dev.1") =
|
||||
getProperty("jellyfin.version")
|
||||
?.removePrefix("v")
|
||||
?: fallback
|
||||
|
||||
/**
|
||||
* Get the version code for a given semantic version.
|
||||
* Does not validate the input and thus will throw an exception when parts are missing.
|
||||
*
|
||||
* The pre-release part ("-rc.1", "-beta.1" etc.) defaults to 99 when not specified.
|
||||
* The pre-release part ("-rc.1", "-beta.1" etc.) defaults to 99
|
||||
*
|
||||
* Sample output:
|
||||
* MA.MI.PA-PR > MA MI PA PR
|
||||
* 0.0.0-dev.1 > 1
|
||||
* 0.0.0 > 99
|
||||
* 1.1.1 > 1 01 01 99
|
||||
* 0.7.0 > 7 00 99
|
||||
* 99.99.99 > 99 99 99 99
|
||||
* 2.0.0-rc.3 > 2 00 00 03
|
||||
* 2.0.0 > 2 00 00 99
|
||||
* 99.99.99-rc.1 > 99 99 99 01
|
||||
* MA.MI.PA-PR -> MAMIPAPR
|
||||
* 0.0.0 -> 99
|
||||
* 1.1.1 -> 1010199
|
||||
* 0.7.0 -> 70099
|
||||
* 99.99.99 -> 99999999
|
||||
* 2.0.0-rc.3 -> 2000003
|
||||
* 2.0.0 -> 2000099
|
||||
* 99.99.99-rc.1 -> 99999901
|
||||
*/
|
||||
fun getVersionCode(versionName: String): Int {
|
||||
// Split to core and pre release parts with a default for pre release (null)
|
||||
|
||||
Reference in New Issue
Block a user