mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-16 19:26:12 -04:00
Refactor: Convert build configuration to Gradle plugin pattern
- Migrate ProjectConfig from static object to proper Gradle plugin - Add version type support (beta/rc) to version.properties - Clean up legacy fastlane changelogs - Update release script to support version types - Remove automatic fastlane changelog generation from release script - Add BuildConfig field injection for version info
This commit is contained in:
+14
-9
@@ -1,4 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
|
id("projectConfig")
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
id("com.google.devtools.ksp")
|
id("com.google.devtools.ksp")
|
||||||
@@ -9,28 +10,32 @@ apply(plugin = "dagger.hilt.android.plugin")
|
|||||||
apply(plugin = "androidx.navigation.safeargs.kotlin")
|
apply(plugin = "androidx.navigation.safeargs.kotlin")
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = ProjectConfig.compileSdk
|
compileSdk = projectConfig.compileSdk
|
||||||
namespace = ProjectConfig.packageName
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = ProjectConfig.packageName
|
namespace = projectConfig.packageName
|
||||||
|
|
||||||
minSdk = ProjectConfig.minSdk
|
minSdk = projectConfig.minSdk
|
||||||
targetSdk = ProjectConfig.targetSdk
|
targetSdk = projectConfig.targetSdk
|
||||||
|
|
||||||
versionCode = ProjectConfig.Version.code + 0 // Base app
|
versionCode = projectConfig.version.code.toInt()
|
||||||
versionName = ProjectConfig.Version.name
|
versionName = projectConfig.version.name
|
||||||
|
|
||||||
testInstrumentationRunner = "eu.darken.capod.HiltTestRunner"
|
testInstrumentationRunner = "eu.darken.capod.HiltTestRunner"
|
||||||
|
|
||||||
|
buildConfigField("String", "PACKAGENAME", "\"${projectConfig.packageName}\"")
|
||||||
|
buildConfigField("String", "VERSION_CODE", "\"${projectConfig.version.code}\"")
|
||||||
|
buildConfigField("String", "VERSION_NAME", "\"${projectConfig.version.name}\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable automatic per-app language preferences generation
|
// Enable automatic per-app language preferences generation
|
||||||
androidResources {
|
androidResources {
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
generateLocaleConfig = true
|
generateLocaleConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
val basePath = File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}")
|
val basePath = File(System.getProperty("user.home"), ".appconfig/${projectConfig.packageName}")
|
||||||
create("releaseFoss") {
|
create("releaseFoss") {
|
||||||
setupCredentials(File(basePath, "signing-foss.properties"))
|
setupCredentials(File(basePath, "signing-foss.properties"))
|
||||||
}
|
}
|
||||||
@@ -94,7 +99,7 @@ android {
|
|||||||
val variantName: String = variantOutputImpl.name
|
val variantName: String = variantOutputImpl.name
|
||||||
|
|
||||||
if (listOf("release", "beta").any { variantName.lowercase().contains(it) }) {
|
if (listOf("release", "beta").any { variantName.lowercase().contains(it) }) {
|
||||||
val outputFileName = ProjectConfig.packageName +
|
val outputFileName = projectConfig.packageName +
|
||||||
"-v${defaultConfig.versionName}-${defaultConfig.versionCode}" +
|
"-v${defaultConfig.versionName}-${defaultConfig.versionCode}" +
|
||||||
"-${variantName.uppercase()}.apk"
|
"-${variantName.uppercase()}.apk"
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
package eu.darken.capod.common
|
package eu.darken.capod.common
|
||||||
|
|
||||||
import eu.darken.capod.BuildConfig
|
import android.util.Log
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
|
||||||
// Can't be const because that prevents them from being mocked in tests
|
@Keep
|
||||||
@Suppress("MayBeConstant")
|
|
||||||
object BuildConfigWrap {
|
object BuildConfigWrap {
|
||||||
val DEBUG: Boolean = BuildConfig.DEBUG
|
val APPLICATION_ID = getBuildConfigValue("PACKAGENAME") as String
|
||||||
|
val DEBUG: Boolean = getBuildConfigValue("DEBUG") as Boolean
|
||||||
val BUILD_TYPE: BuildType = when (val typ = BuildConfig.BUILD_TYPE) {
|
val BUILD_TYPE: BuildType = when (val typ = getBuildConfigValue("BUILD_TYPE") as String) {
|
||||||
"debug" -> BuildType.DEV
|
"debug" -> BuildType.DEV
|
||||||
"beta" -> BuildType.BETA
|
"beta" -> BuildType.BETA
|
||||||
"release" -> BuildType.RELEASE
|
"release" -> BuildType.RELEASE
|
||||||
else -> throw IllegalArgumentException("Unknown buildtype: $typ")
|
else -> throw IllegalArgumentException("Unknown buildtype: $typ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
enum class BuildType {
|
enum class BuildType {
|
||||||
DEV,
|
DEV,
|
||||||
BETA,
|
BETA,
|
||||||
@@ -22,24 +24,36 @@ object BuildConfigWrap {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
val FLAVOR: Flavor = when (val flav = BuildConfig.FLAVOR) {
|
val FLAVOR: Flavor = when (val flav = getBuildConfigValue("FLAVOR") as String?) {
|
||||||
"gplay" -> Flavor.GPLAY
|
"gplay" -> Flavor.GPLAY
|
||||||
"foss" -> Flavor.FOSS
|
"foss" -> Flavor.FOSS
|
||||||
|
null -> Flavor.NONE
|
||||||
else -> throw IllegalStateException("Unknown flavor: $flav")
|
else -> throw IllegalStateException("Unknown flavor: $flav")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Flavor {
|
enum class Flavor {
|
||||||
GPLAY,
|
GPLAY,
|
||||||
FOSS,
|
FOSS,
|
||||||
|
NONE,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
val APPLICATION_ID: String = BuildConfig.APPLICATION_ID
|
val VERSION_CODE: Long = (getBuildConfigValue("VERSION_CODE") as String).toLong()
|
||||||
|
val VERSION_NAME: String = getBuildConfigValue("VERSION_NAME") as String
|
||||||
|
|
||||||
val VERSION_CODE: Long = BuildConfig.VERSION_CODE.toLong()
|
val VERSION_DESCRIPTION: String = "v$VERSION_NAME ($VERSION_CODE) ~ $FLAVOR/$BUILD_TYPE"
|
||||||
val VERSION_NAME: String = BuildConfig.VERSION_NAME
|
val VERSION_DESCRIPTION_SHORT: String = "v$VERSION_NAME ~ $FLAVOR"
|
||||||
|
|
||||||
val VERSION_DESCRIPTION_LONG: String = "v$VERSION_NAME ($VERSION_CODE) ${FLAVOR}_$BUILD_TYPE"
|
|
||||||
val VERSION_DESCRIPTION_SHORT: String = "v$VERSION_NAME $FLAVOR"
|
|
||||||
val VERSION_DESCRIPTION_TINY: String = "v$VERSION_NAME"
|
val VERSION_DESCRIPTION_TINY: String = "v$VERSION_NAME"
|
||||||
|
|
||||||
|
private fun getBuildConfigValue(fieldName: String): Any? = try {
|
||||||
|
val c = Class.forName("eu.darken.capod.BuildConfig")
|
||||||
|
val f: Field = c.getField(fieldName).apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
f.get(null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Log.e("getBuildConfigValue", "fieldName: $fieldName")
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class RecorderModule @Inject constructor(
|
|||||||
triggerFile.createNewFile()
|
triggerFile.createNewFile()
|
||||||
|
|
||||||
log(TAG, INFO) { "Build.Fingerprint: ${Build.FINGERPRINT}" }
|
log(TAG, INFO) { "Build.Fingerprint: ${Build.FINGERPRINT}" }
|
||||||
log(TAG, INFO) { "BuildConfig.Versions: ${BuildConfigWrap.VERSION_DESCRIPTION_LONG}" }
|
log(TAG, INFO) { "BuildConfig.Versions: ${BuildConfigWrap.VERSION_DESCRIPTION}" }
|
||||||
|
|
||||||
copy(
|
copy(
|
||||||
recorder = newRecorder
|
recorder = newRecorder
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class RecorderActivityVM @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun share() = launch {
|
fun share() = launch {
|
||||||
val (path, size) = resultCacheCompressedObs.first()
|
val (path, _) = resultCacheCompressedObs.first()
|
||||||
|
|
||||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||||
val uri = FileProvider.getUriForFile(
|
val uri = FileProvider.getUriForFile(
|
||||||
@@ -89,7 +89,7 @@ class RecorderActivityVM @Inject constructor(
|
|||||||
type = "application/zip"
|
type = "application/zip"
|
||||||
|
|
||||||
addCategory(Intent.CATEGORY_DEFAULT)
|
addCategory(Intent.CATEGORY_DEFAULT)
|
||||||
putExtra(Intent.EXTRA_SUBJECT, "CAPod DebugLog - ${BuildConfigWrap.VERSION_DESCRIPTION_LONG})")
|
putExtra(Intent.EXTRA_SUBJECT, "CAPod DebugLog - ${BuildConfigWrap.VERSION_DESCRIPTION})")
|
||||||
putExtra(Intent.EXTRA_TEXT, "Your text here.")
|
putExtra(Intent.EXTRA_TEXT, "Your text here.")
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class SettingsIndexFragment : PreferenceFragment2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreferencesCreated() {
|
override fun onPreferencesCreated() {
|
||||||
findPreference<Preference>("core.changelog")!!.summary = BuildConfigWrap.VERSION_DESCRIPTION_LONG
|
findPreference<Preference>("core.changelog")!!.summary = BuildConfigWrap.VERSION_DESCRIPTION
|
||||||
findPreference<Preference>("core.privacy")!!.setOnPreferenceClickListener {
|
findPreference<Preference>("core.privacy")!!.setOnPreferenceClickListener {
|
||||||
webpageTool.open(PrivacyPolicy.URL)
|
webpageTool.open(PrivacyPolicy.URL)
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -3,10 +3,20 @@ plugins {
|
|||||||
`java-library`
|
`java-library`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
plugins {
|
||||||
|
create("projectConfigPlugin") {
|
||||||
|
id = "projectConfig"
|
||||||
|
implementationClass = "ProjectConfigPlugin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.android.tools.build:gradle:8.13.0")
|
implementation("com.android.tools.build:gradle:8.13.0")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.10")
|
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.10")
|
||||||
|
|||||||
@@ -1,64 +1,56 @@
|
|||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
object ProjectConfig {
|
open class ProjectConfig {
|
||||||
const val packageName = "eu.darken.capod"
|
val packageName = "eu.darken.capod"
|
||||||
|
val minSdk = 26
|
||||||
|
|
||||||
const val minSdk = 26
|
val compileSdk = 36
|
||||||
const val compileSdk = 36
|
val targetSdk = 36
|
||||||
const val targetSdk = 36
|
|
||||||
|
|
||||||
object Version {
|
lateinit var version: Version
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "ProjectConfig($packageName, min=$minSdk, compile=$compileSdk, target=$targetSdk, version=$version)"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init(project: Project) {
|
||||||
val versionProperties = Properties().apply {
|
val versionProperties = Properties().apply {
|
||||||
load(FileInputStream(File("version.properties")))
|
val propsPath = File(project.rootDir, "version.properties")
|
||||||
|
println("Version: From $propsPath:")
|
||||||
|
load(FileInputStream(propsPath))
|
||||||
|
println("$this")
|
||||||
}
|
}
|
||||||
val major = versionProperties.getProperty("project.versioning.major").toInt()
|
version = Version(
|
||||||
val minor = versionProperties.getProperty("project.versioning.minor").toInt()
|
major = versionProperties.getProperty("project.versioning.major").toInt(),
|
||||||
val patch = versionProperties.getProperty("project.versioning.patch").toInt()
|
minor = versionProperties.getProperty("project.versioning.minor").toInt(),
|
||||||
val build = versionProperties.getProperty("project.versioning.build").toInt()
|
patch = versionProperties.getProperty("project.versioning.patch").toInt(),
|
||||||
|
build = versionProperties.getProperty("project.versioning.build").toInt(),
|
||||||
|
type = versionProperties.getProperty("project.versioning.type"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val name = "${major}.${minor}.${patch}-rc${build}"
|
data class Version(
|
||||||
val code = major * 10000000 + minor * 100000 + patch * 1000 + build * 10
|
val major: Int,
|
||||||
|
val minor: Int,
|
||||||
|
val patch: Int,
|
||||||
|
val build: Int,
|
||||||
|
val type: String,
|
||||||
|
) {
|
||||||
|
val name: String
|
||||||
|
get() = "${major}.${minor}.${patch}-$type${build}"
|
||||||
|
val code: Long
|
||||||
|
get() = major * 10000000 + minor * 100000 + patch * 1000 + build * 10L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun lastCommitHash(): String = Runtime.getRuntime().exec("git rev-parse --short HEAD").let { process ->
|
class ProjectConfigPlugin : Plugin<Project> {
|
||||||
process.waitFor()
|
override fun apply(project: Project) {
|
||||||
val output = process.inputStream.use { input ->
|
val extension = project.extensions.create("projectConfig", ProjectConfig::class.java)
|
||||||
input.bufferedReader().use {
|
extension.init(project)
|
||||||
it.readText()
|
project.afterEvaluate { println("ProjectConfigPlugin loaded: $extension") }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
process.destroy()
|
}
|
||||||
output.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun com.android.build.api.dsl.SigningConfig.setupCredentials(
|
|
||||||
signingPropsPath: File? = null
|
|
||||||
) {
|
|
||||||
|
|
||||||
val keyStoreFromEnv = System.getenv("STORE_PATH")?.let { File(it) }
|
|
||||||
|
|
||||||
if (keyStoreFromEnv?.exists() == true) {
|
|
||||||
println("Using signing data from environment variables.")
|
|
||||||
storeFile = keyStoreFromEnv
|
|
||||||
storePassword = System.getenv("STORE_PASSWORD")
|
|
||||||
keyAlias = System.getenv("KEY_ALIAS")
|
|
||||||
keyPassword = System.getenv("KEY_PASSWORD")
|
|
||||||
} else {
|
|
||||||
println("Using signing data from properties file.")
|
|
||||||
val props = Properties().apply {
|
|
||||||
signingPropsPath?.takeIf { it.canRead() }?.let { load(FileInputStream(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val keyStorePath = props.getProperty("release.storePath")?.let { File(it) }
|
|
||||||
|
|
||||||
if (keyStorePath?.exists() == true) {
|
|
||||||
storeFile = keyStorePath
|
|
||||||
storePassword = props.getProperty("release.storePassword")
|
|
||||||
keyAlias = props.getProperty("release.keyAlias")
|
|
||||||
keyPassword = props.getProperty("release.keyPassword")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import com.android.build.api.dsl.SigningConfig
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.testing.Test
|
||||||
|
import org.gradle.api.tasks.testing.TestDescriptor
|
||||||
|
import org.gradle.api.tasks.testing.TestListener
|
||||||
|
import org.gradle.api.tasks.testing.TestResult
|
||||||
|
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||||
|
import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.util.Properties
|
||||||
|
|
||||||
|
val Project.projectConfig: ProjectConfig
|
||||||
|
get() = extensions.findByType(ProjectConfig::class.java)!!
|
||||||
|
|
||||||
|
fun SigningConfig.setupCredentials(
|
||||||
|
signingPropsPath: File? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
val keyStoreFromEnv = System.getenv("STORE_PATH")?.let { File(it) }
|
||||||
|
|
||||||
|
if (keyStoreFromEnv?.exists() == true) {
|
||||||
|
println("Using signing data from environment variables.")
|
||||||
|
storeFile = keyStoreFromEnv
|
||||||
|
storePassword = System.getenv("STORE_PASSWORD")
|
||||||
|
keyAlias = System.getenv("KEY_ALIAS")
|
||||||
|
keyPassword = System.getenv("KEY_PASSWORD")
|
||||||
|
} else {
|
||||||
|
println("Using signing data from properties file.")
|
||||||
|
val props = Properties().apply {
|
||||||
|
signingPropsPath?.takeIf { it.canRead() }?.let { load(FileInputStream(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val keyStorePath = props.getProperty("release.storePath")?.let { File(it) }
|
||||||
|
|
||||||
|
if (keyStorePath?.exists() == true) {
|
||||||
|
storeFile = keyStorePath
|
||||||
|
storePassword = props.getProperty("release.storePassword")
|
||||||
|
keyAlias = props.getProperty("release.keyAlias")
|
||||||
|
keyPassword = props.getProperty("release.keyPassword")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Test.setupTestLogging() {
|
||||||
|
testLogging {
|
||||||
|
events(
|
||||||
|
TestLogEvent.FAILED,
|
||||||
|
TestLogEvent.PASSED,
|
||||||
|
TestLogEvent.SKIPPED,
|
||||||
|
// TestLogEvent.STANDARD_OUT,
|
||||||
|
)
|
||||||
|
exceptionFormat = TestExceptionFormat.FULL
|
||||||
|
showExceptions = true
|
||||||
|
showCauses = true
|
||||||
|
showStackTraces = true
|
||||||
|
|
||||||
|
addTestListener(object : TestListener {
|
||||||
|
override fun beforeSuite(suite: TestDescriptor) {}
|
||||||
|
override fun beforeTest(testDescriptor: TestDescriptor) {}
|
||||||
|
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {}
|
||||||
|
override fun afterSuite(suite: TestDescriptor, result: TestResult) {
|
||||||
|
if (suite.parent != null) {
|
||||||
|
val messages = """
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
| ${result.resultType} ${result.testCount} tests: ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
println(messages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
v1.0.0:
|
|
||||||
- Initial release.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031300)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031301)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031302)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031303)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031304)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031305)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031306)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
v1.3.13(1031307)
|
|
||||||
• Updated translations
|
|
||||||
• Updated internal dependencies
|
|
||||||
• Tweaked placement of UI elements
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes and performance improvements.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
|
|
||||||
A detailed changelog is available on GitHub:
|
|
||||||
https://github.com/d4rken-org/capod/releases/latest
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
|
|
||||||
A detailed changelog is available on GitHub:
|
|
||||||
https://github.com/d4rken-org/capod/releases/latest
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
|
|
||||||
A detailed changelog is available on GitHub:
|
|
||||||
https://github.com/d4rken-org/capod/releases/latest
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
|
|
||||||
A detailed changelog is available on GitHub:
|
|
||||||
https://github.com/d4rken-org/capod/releases/latest
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Support for AirPods Pro 2 with USB-C
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Bugfixes, performance improvements and maybe new features.
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Updates contain bugfixes, performance improvements and maybe new features.
|
|
||||||
A detailed changelog is always available on GitHub.
|
|
||||||
|
|
||||||
FYI: It’s just me here, sometimes replies might take a bit. Sorry for that!
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Updates contain bugfixes, performance improvements and maybe new features.
|
|
||||||
A detailed changelog is always available on GitHub.
|
|
||||||
|
|
||||||
FYI: It’s just me here, sometimes replies might take a bit. Sorry for that!
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Updates contain bugfixes, performance improvements and maybe new features.
|
|
||||||
A detailed changelog is always available on GitHub.
|
|
||||||
|
|
||||||
FYI: It’s just me here, sometimes replies might take a bit. Sorry for that!
|
|
||||||
¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
🐛 Bug fixes, 🚀 performance boosts, maybe even ✨ new features.
|
|
||||||
|
|
||||||
Changelog: https://capod.darken.eu/changelog
|
|
||||||
|
|
||||||
FYI: It’s just me here — thanks for understanding if replies take a bit. ¯\_(ツ)_/¯
|
|
||||||
+5
-20
@@ -308,6 +308,7 @@ do-version-properties() {
|
|||||||
V_MINOR_REGEX='^([a-zA-Z\.]+minor)=([0-9]+)$'
|
V_MINOR_REGEX='^([a-zA-Z\.]+minor)=([0-9]+)$'
|
||||||
V_PATCH_REGEX='^([a-zA-Z\.]+patch)=([0-9]+)$'
|
V_PATCH_REGEX='^([a-zA-Z\.]+patch)=([0-9]+)$'
|
||||||
V_BUILD_REGEX='^([a-zA-Z\.]+build)=([0-9]+)$'
|
V_BUILD_REGEX='^([a-zA-Z\.]+build)=([0-9]+)$'
|
||||||
|
V_TYPE_REGEX='^([a-zA-Z\.]+type)=(rc|beta)$'
|
||||||
|
|
||||||
PROPS_FILE_NEW=""
|
PROPS_FILE_NEW=""
|
||||||
|
|
||||||
@@ -333,6 +334,10 @@ do-version-properties() {
|
|||||||
updated="${BASH_REMATCH[1]}=${V_BUILD_COUNTER}"
|
updated="${BASH_REMATCH[1]}=${V_BUILD_COUNTER}"
|
||||||
echo "Found build, replacing: $line -> $updated"
|
echo "Found build, replacing: $line -> $updated"
|
||||||
PROPS_FILE_NEW+=$updated
|
PROPS_FILE_NEW+=$updated
|
||||||
|
elif [[ $line =~ $V_TYPE_REGEX ]]; then
|
||||||
|
updated="${BASH_REMATCH[1]}=${V_BUILD_TYPE}"
|
||||||
|
echo "Found type, replacing: $line -> $updated"
|
||||||
|
PROPS_FILE_NEW+=$updated
|
||||||
else
|
else
|
||||||
PROPS_FILE_NEW+="$line"
|
PROPS_FILE_NEW+="$line"
|
||||||
fi
|
fi
|
||||||
@@ -360,25 +365,6 @@ do-versionfile() {
|
|||||||
git add VERSION
|
git add VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update a version file that can be parsed by third-parties, e.g. F-Droid
|
|
||||||
do-fastlane-changelog() {
|
|
||||||
CHANGELOGS_DIR="fastlane/metadata/android/en-US/changelogs"
|
|
||||||
NEW_CHANGELOG="$CHANGELOGS_DIR/$V_CODE.txt"
|
|
||||||
|
|
||||||
[ -f "$NEW_CHANGELOG" ] && return
|
|
||||||
|
|
||||||
echo -e "\n${S_NOTICE}Creating new default fastlane changelog file for $V_CODE...\n"
|
|
||||||
|
|
||||||
cp "$CHANGELOGS_DIR/default.txt" "$NEW_CHANGELOG"
|
|
||||||
|
|
||||||
cat "$NEW_CHANGELOG"
|
|
||||||
|
|
||||||
echo -e "\n\n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM}$NEW_CHANGELOG${S_NOTICE}] file"
|
|
||||||
|
|
||||||
# Stage file for commit
|
|
||||||
git add "$CHANGELOGS_DIR/$V_CODE.txt"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Does the release branch already exist?
|
# Does the release branch already exist?
|
||||||
check-branch-exist() {
|
check-branch-exist() {
|
||||||
[ "$FLAG_NOBRANCH" = true ] && return
|
[ "$FLAG_NOBRANCH" = true ] && return
|
||||||
@@ -467,7 +453,6 @@ echo -e "\n${S_LIGHT}––––––"
|
|||||||
# Update steps
|
# Update steps
|
||||||
do-version-properties
|
do-version-properties
|
||||||
do-versionfile
|
do-versionfile
|
||||||
do-fastlane-changelog
|
|
||||||
do-branch
|
do-branch
|
||||||
do-commit
|
do-commit
|
||||||
create-tag "${V_NAME}" "${REL_NOTE}"
|
create-tag "${V_NAME}" "${REL_NOTE}"
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ project.versioning.major=3
|
|||||||
project.versioning.minor=0
|
project.versioning.minor=0
|
||||||
project.versioning.patch=0
|
project.versioning.patch=0
|
||||||
project.versioning.build=1
|
project.versioning.build=1
|
||||||
|
project.versioning.type=beta
|
||||||
#############################
|
#############################
|
||||||
|
|||||||
Reference in New Issue
Block a user