diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index a9d480c0272..561e0a0d924 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -14,6 +14,9 @@ jobs:
distribution: temurin
java-version: 17
+ - name: Set up Android SDK
+ uses: android-actions/setup-android@v3
+
- name: Grant execute permission for gradlew
run: chmod +x gradlew
@@ -23,11 +26,76 @@ jobs:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
cache-read-only: false
+ - name: Build dokka
+ run: ./gradlew docs:dokkaGeneratePublicationHtml
+
- name: Run Gradle
- run: ./gradlew assemblePrereleaseDebug lint
+ run: ./gradlew assemblePrereleaseRelease androidSourcesJar makeJar
- name: Upload Artifact
uses: actions/upload-artifact@v6
with:
name: pull-request-build
- path: "app/build/outputs/apk/prerelease/debug/*.apk"
+ path: |
+ app/build/outputs/apk/prerelease/debug/*.apk
+ app/build/outputs/apk/prerelease/release/*.apk
+ app/build/libs/app-sources.jar
+ app/build/classes.jar
+ library/build/libs/library-*-sources.jar
+
+ - name: Stage Reports + Dokka for GitHub Pages
+ run: |
+ BRANCH_NAME=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
+ TARGET_DIR=gh-pages/$BRANCH_NAME
+
+ mkdir -p "$TARGET_DIR"
+
+ if [ -d "build/reports" ]; then
+ mkdir -p "$TARGET_DIR/reports"
+ cp -r build/reports/. "$TARGET_DIR/reports/"
+ fi
+
+ for REPORT_DIR in */build/reports; do
+ if [ -d "$REPORT_DIR" ]; then
+ mkdir -p "$TARGET_DIR/reports/$REPORT_DIR"
+ cp -r "$REPORT_DIR/." "$TARGET_DIR/reports/$REPORT_DIR/"
+ fi
+ done
+
+ if [ -d "docs/build/dokka/html" ]; then
+ mkdir -p "$TARGET_DIR/dokka"
+ cp -r docs/build/dokka/html/. "$TARGET_DIR/dokka/"
+ fi
+
+ INDEX_FILE="$TARGET_DIR/index.html"
+ echo "
+
+
+
+ Artifacts for $BRANCH_NAME
+
+
+ Artifacts for branch $BRANCH_NAME
+ " > "$INDEX_FILE"
+
+ if [ -d "$TARGET_DIR/reports" ]; then
+ echo " - reports/
" >> "$INDEX_FILE"
+ fi
+
+ if [ -d "$TARGET_DIR/dokka" ]; then
+ echo " - dokka/
" >> "$INDEX_FILE"
+ fi
+
+ echo "
+
+ " >> "$INDEX_FILE"
+ shell: bash
+
+ - name: Push to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./gh-pages
+ user_name: "github-actions"
+ user_email: "github-actions@github.com"
+ commit_message: "Update reports + dokka for ${{ github.head_ref }} [ci skip]"
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 41e8fc0a01a..85c0ff5c469 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,4 +1,5 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
+import com.android.build.gradle.tasks.MergeSourceSetFolders
import org.jetbrains.dokka.gradle.engine.parameters.KotlinPlatform
import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
@@ -8,30 +9,48 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.dokka)
- alias(libs.plugins.kotlin.android)
}
val javaTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get())
-val tmpFilePath = System.getProperty("user.home") + "/work/_temp/keystore/"
-val prereleaseStoreFile: File? = File(tmpFilePath).listFiles()?.first()
-
-fun getGitCommitHash(): String {
- return try {
- val headFile = file("${project.rootDir}/.git/HEAD")
-
- // Read the commit hash from .git/HEAD
- if (headFile.exists()) {
- val headContent = headFile.readText().trim()
- if (headContent.startsWith("ref:")) {
- val refPath = headContent.substring(5) // e.g., refs/heads/main
- val commitFile = file("${project.rootDir}/.git/$refPath")
- if (commitFile.exists()) commitFile.readText().trim() else ""
- } else headContent // If it's a detached HEAD (commit hash directly)
- } else {
- "" // If .git/HEAD doesn't exist
- }.take(7) // Return the short commit hash
- } catch (_: Throwable) {
- "" // Just return an empty string if any exception occurs
+
+tasks.register("generateGitHash") {
+ val gitHashDir = layout.buildDirectory.dir("generated/git")
+ val rootDir = project.rootDir
+ outputs.dir(gitHashDir)
+
+ doLast {
+ val hash = try {
+ // Read the commit hash from .git/HEAD
+ val headFile = File(rootDir, ".git/HEAD")
+ if (headFile.exists()) {
+ val headContent = headFile.readText().trim()
+ if (headContent.startsWith("ref:")) {
+ val refPath = headContent.substring(5) // e.g., refs/heads/main
+ val commitFile = File(rootDir, ".git/$refPath")
+ if (commitFile.exists()) commitFile.readText().trim() else ""
+ } else headContent // If it's a detached HEAD (commit hash directly)
+ } else "" // If .git/HEAD doesn't exist
+ } catch (_: Throwable) {
+ "" // Just set to an empty string if any exception occurs
+ }.take(7) // Get the short commit hash
+
+ val outFile = gitHashDir.get().file("git-hash.txt").asFile
+ outFile.parentFile.mkdirs()
+ outFile.writeText(hash)
+ }
+}
+
+tasks.withType {
+ if (name.contains("Assets", ignoreCase = true)) {
+ dependsOn("generateGitHash")
+ val gitHashDir = layout.buildDirectory.dir("generated/git")
+
+ doLast {
+ val assetsDir = outputs.files.singleFile
+ val gitHashFile = gitHashDir.get().file("git-hash.txt").asFile
+ val outFile = File(assetsDir, "git-hash.txt")
+ gitHashFile.copyTo(outFile, overwrite = true)
+ }
}
}
@@ -46,9 +65,14 @@ android {
}
signingConfigs {
- if (prereleaseStoreFile != null) {
+ // We just use SIGNING_KEY_ALIAS here since it won't change
+ // so won't kill the configuration cache.
+ if (System.getenv("SIGNING_KEY_ALIAS") != null) {
create("prerelease") {
- storeFile = file(prereleaseStoreFile)
+ val tmpFilePath = System.getProperty("user.home") + "/work/_temp/keystore/"
+ val prereleaseStoreFile: File? = File(tmpFilePath).listFiles()?.first()
+
+ storeFile = prereleaseStoreFile?.let { file(it) }
storePassword = System.getenv("SIGNING_STORE_PASSWORD")
keyAlias = System.getenv("SIGNING_KEY_ALIAS")
keyPassword = System.getenv("SIGNING_KEY_PASSWORD")
@@ -65,8 +89,6 @@ android {
versionCode = 67
versionName = "4.6.2"
- resValue("string", "commit_hash", getGitCommitHash())
-
manifestPlaceholders["target_sdk_version"] = libs.versions.targetSdk.get()
// Reads local.properties
@@ -135,21 +157,19 @@ android {
}
java {
- // Use Java 17 toolchain even if a higher JDK runs the build.
+ // Use Java 17 toolchain even if a higher JDK runs the build.
// We still use Java 8 for now which higher JDKs have deprecated.
- toolchain {
- languageVersion.set(JavaLanguageVersion.of(libs.versions.jdkToolchain.get()))
- }
+ toolchain {
+ languageVersion.set(JavaLanguageVersion.of(libs.versions.jdkToolchain.get()))
+ }
}
lint {
- abortOnError = false
checkReleaseBuilds = false
}
buildFeatures {
buildConfig = true
- resValues = true
}
namespace = "com.lagradost.cloudstream3"
@@ -272,8 +292,10 @@ tasks.withType {
dokka {
moduleName = "App"
dokkaSourceSets {
- main {
+ configureEach {
+ suppress = name != "prereleaseDebug"
analysisPlatform = KotlinPlatform.JVM
+ displayName = "JVM"
documentedVisibilities(
VisibilityModifier.Public,
VisibilityModifier.Protected
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt
index 097eb2c600b..e41109b5982 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt
@@ -27,6 +27,7 @@ import com.lagradost.cloudstream3.ui.settings.Globals.TV
import com.lagradost.cloudstream3.ui.settings.Globals.isLandscape
import com.lagradost.cloudstream3.ui.settings.Globals.isLayout
import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.utils.GitInfo.currentCommitHash
import com.lagradost.cloudstream3.utils.ImageLoader.loadImage
import com.lagradost.cloudstream3.utils.UIHelper.clipboardHelper
import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding
@@ -247,7 +248,7 @@ class SettingsFragment : BaseFragment(
}
val appVersion = BuildConfig.VERSION_NAME
- val commitInfo = getString(R.string.commit_hash)
+ val commitHash = activity?.currentCommitHash() ?: ""
val buildTimestamp = SimpleDateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG,
Locale.getDefault()
).apply { timeZone = TimeZone.getTimeZone("UTC")
@@ -255,8 +256,9 @@ class SettingsFragment : BaseFragment(
binding.appVersion.text = appVersion
binding.buildDate.text = buildTimestamp
+ binding.commitHash.text = commitHash
binding.appVersionInfo.setOnLongClickListener {
- clipboardHelper(txt(R.string.extension_version), "$appVersion $commitInfo $buildTimestamp")
+ clipboardHelper(txt(R.string.extension_version), "$appVersion $commitHash $buildTimestamp")
true
}
}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt
new file mode 100644
index 00000000000..58ff44bb257
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt
@@ -0,0 +1,20 @@
+package com.lagradost.cloudstream3.utils
+
+import android.content.Context
+
+/**
+ * Simple helper to get the short commit hash from assets.
+ * The hash is generated at build and stored as an asset
+ * that can be accessed at runtime for Gradle
+ * configuration cache support.
+ */
+object GitInfo {
+ fun Context.currentCommitHash(): String = try {
+ assets.open("git-hash.txt")
+ .bufferedReader()
+ .readText()
+ .trim()
+ } catch (_: Exception) {
+ ""
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt
index 057923eb05a..9380285ca44 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt
@@ -24,6 +24,7 @@ import com.lagradost.cloudstream3.services.PackageInstallerService
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
+import com.lagradost.cloudstream3.utils.GitInfo.currentCommitHash
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import okio.BufferedSink
@@ -170,7 +171,7 @@ object InAppUpdater {
Log.d(LOG_TAG, "Fetched GitHub tag: $updateCommitHash")
return Update(
- getString(R.string.commit_hash) != updateCommitHash,
+ currentCommitHash() != updateCommitHash,
foundAsset.browserDownloadUrl,
updateCommitHash,
found.body,
diff --git a/app/src/main/res/layout/main_settings.xml b/app/src/main/res/layout/main_settings.xml
index ba377455440..5c05599e828 100644
--- a/app/src/main/res/layout/main_settings.xml
+++ b/app/src/main/res/layout/main_settings.xml
@@ -134,8 +134,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
- android:text="@string/commit_hash"
- android:textColor="?attr/textColor" />
+ android:textColor="?attr/textColor"
+ tools:text="1234567" />
-
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index cca263dd422..e35c1f61148 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,7 +4,6 @@ plugins {
alias(libs.plugins.android.multiplatform.library) apply false
alias(libs.plugins.buildkonfig) apply false // Universal build config
alias(libs.plugins.dokka) apply false
- alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlin.multiplatform) apply false
}
diff --git a/gradle.properties b/gradle.properties
index 0168ae437bd..85ed7146560 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -26,3 +26,5 @@ org.gradle.configuration-cache=true
# Compiling with Java 8 is deprecated but we still use it for now
android.javaCompile.suppressSourceTargetDeprecationWarning=true
+
+org.jetbrains.dokka.analysis.enableExperimentalKDocResolution=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index afceb26dde0..5a1f309e315 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,7 +2,7 @@
# https://docs.gradle.org/current/userguide/dependency_versions.html#sec:strict-version
[versions]
activityKtx = "1.11.0"
-androidGradlePlugin = "8.13.2"
+androidGradlePlugin = "9.0.0"
appcompat = "1.7.1"
biometric = "1.4.0-alpha04"
buildkonfigGradlePlugin = "0.17.1"
@@ -12,7 +12,7 @@ conscryptAndroid = { strictly = "2.5.2" } # 2.5.3 crashes everything
constraintlayout = "2.2.1"
coreKtx = "1.17.0"
desugar_jdk_libs_nio = "2.1.5"
-dokkaGradlePlugin = "2.1.0"
+dokkaGradlePlugin = "2.2.0-Beta"
espressoCore = "3.7.0"
fragmentKtx = "1.8.9"
fuzzywuzzy = "1.4.0"
@@ -23,7 +23,7 @@ junit = "4.13.2"
junitKtx = "1.3.0"
junitVersion = "1.3.0"
juniversalchardet = "2.5.0"
-kotlinGradlePlugin = "2.3.0"
+kotlinGradlePlugin = "2.3.20-Beta1"
kotlinxCoroutinesCore = "1.10.2"
lifecycleKtx = "2.9.4"
material = "1.14.0-alpha08"
@@ -117,7 +117,6 @@ android-lint = { id = "com.android.lint", version.ref = "androidGradlePlugin" }
android-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
buildkonfig = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfigGradlePlugin" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokkaGradlePlugin" }
-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinGradlePlugin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm" , version.ref = "kotlinGradlePlugin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlinGradlePlugin" }