diff --git a/.github/workflows/app-build.yml b/.github/workflows/app-build.yml new file mode 100644 index 0000000000..32f8cb7419 --- /dev/null +++ b/.github/workflows/app-build.yml @@ -0,0 +1,42 @@ +name: App Build + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-20.04 + if: ${{ github.repository == 'jellyfin/jellyfin-android' }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Setup Java + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: 11 + + - name: Set dev JELLYFIN_VERISON + run: | + VERSION=$(curl --silent "https://api.github.com/repos/${{ env.GITHUB_REPOSITORY }}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + echo "JELLYFIN_VERSION=$(echo ${VERSION#v} | tr / -)-dev" >> $GITHUB_ENV + + - name: Build Unsigned Release + run: ./gradlew --no-daemon --info assembleRelease versionTxt + + - name: Split APK release types + run: | + mkdir -p build/jellyfin-publish/release-libre build/jellyfin-publish/release-proprietary; + mv app/build/outputs/apk/**/jellyfin-android-*-libre-release-unsigned.apk build/jellyfin-publish/release-libre/; + mv app/build/outputs/apk/**/jellyfin-android-*-proprietary-release-unsigned.apk build/jellyfin-publish/release-proprietary/; + mv app/build/version.txt build/jellyfin-publish/; + + - uses: actions/upload-artifact@v2 + with: + name: build-publish-artifact + retention-days: 30 + if-no-files-found: error + path: build/jellyfin-publish diff --git a/.github/workflows/app-publish.yaml b/.github/workflows/app-publish.yaml new file mode 100644 index 0000000000..dba582a69e --- /dev/null +++ b/.github/workflows/app-publish.yaml @@ -0,0 +1,73 @@ +name: App Publish + +on: + push: + tags: + - v* + +jobs: + build: + runs-on: ubuntu-20.04 + environment: release + if: ${{ github.repository == 'jellyfin/jellyfin-android' }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Setup Java + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: 11 + + - name: Set JELLYFIN_VERSION + run: echo "JELLYFIN_VERSION=$(echo ${GITHUB_REF#refs/tags/v} | tr / -)" >> $GITHUB_ENV + + - name: Build Signed Release + env: + KEYSTORE: ${{ secrets.KEYSTORE }} + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: ./gradlew --no-daemon --info assembleRelease versionTxt + + - name: Split APK release types + run: | + mkdir -p build/jellyfin-publish/release-libre build/jellyfin-publish/release-proprietary; + mv app/build/outputs/apk/**/jellyfin-android-*-libre-release.apk build/jellyfin-publish/release-libre/; + mv app/build/outputs/apk/**/jellyfin-android-*-proprietary-release.apk build/jellyfin-publish/release-proprietary/; + mv app/build/version.txt build/jellyfin-publish/; + + - name: Upload Release Artifacts + uses: alexellis/upload-assets@0.3.0 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + asset_paths: >- + '["build/jellyfin-publish/release-libre/*", + "build/jellyfin-publish/release-proprietary/*", + "build/jellyfin-publish/version.txt"]' + + - name: Upload to repo.jellyfin.org + uses: burnett01/rsync-deployments@4.1 + with: + switches: -rltgoDzvO --delete --exclude='*' --include='**/*.apk' --include='*.txt' + path: build/jellyfin-publish/ + remote_path: /srv/repository/releases/client/android/versions/v${{ env.JELLYFIN_VERSION }} + remote_host: ${{ secrets.DEPLOY_HOST }} + remote_user: ${{ secrets.DEPLOY_USER }} + remote_key: ${{ secrets.DEPLOY_KEY }} + + - name: Update Release symlinks + uses: appleboy/ssh-action@v0.1.4 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_KEY }} + envs: JELLYFIN_VERSION + script_stop: true + script: | + cd /srv/repository/releases/client/android; + rm -rf *.apk version.txt; + ln -s versions/v${JELLYFIN_VERSION}/jellyfin-android-v${JELLYFIN_VERSION}-*.apk .; + ln -s versions/v${JELLYFIN_VERSION}/version.txt .; diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d0c8292b28..82bb002b30 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,6 +29,15 @@ 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 + } + } + buildTypes { getByName("release") { isMinifyEnabled = true @@ -36,6 +45,7 @@ android { aaptOptions.cruncherEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + signingConfig = releaseSigningConfig } getByName("debug") { applicationIdSuffix = ".debug" diff --git a/buildSrc/src/main/kotlin/SigningHelper.kt b/buildSrc/src/main/kotlin/SigningHelper.kt new file mode 100644 index 0000000000..5881768efe --- /dev/null +++ b/buildSrc/src/main/kotlin/SigningHelper.kt @@ -0,0 +1,49 @@ +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 + ) +}