Skip to content

Commit

Permalink
Merge pull request #3 from UbiqueInnovation/bugfix/generated-icon-out…
Browse files Browse the repository at this point in the history
…puts

fixed conflicting icon task outputs
  • Loading branch information
fbzli authored Oct 2, 2024
2 parents 5331fb9 + 9c7954c commit 5f826a5
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 76 deletions.
110 changes: 55 additions & 55 deletions alpaka/plugin/src/main/java/ch/ubique/gradle/alpaka/AlpakaPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
package ch.ubique.gradle.alpaka

import ch.ubique.gradle.alpaka.config.AlpakaPluginConfig
import ch.ubique.gradle.alpaka.extensions.applicationvariant.launcherIconLabel
import ch.ubique.gradle.alpaka.extensions.capitalize
import ch.ubique.gradle.alpaka.extensions.getMergedManifestFile
import ch.ubique.gradle.alpaka.extensions.productflavor.launcherIconLabel as flavorLauncherIconLabel
import ch.ubique.gradle.alpaka.extensions.productflavor.alpakaUploadKey
import ch.ubique.gradle.alpaka.extensions.productflavor.launcherIconLabel
import ch.ubique.gradle.alpaka.model.UploadRequest
import ch.ubique.gradle.alpaka.task.IconTask
import ch.ubique.gradle.alpaka.task.InjectMetadataIntoManifestTask
Expand All @@ -17,12 +19,16 @@ import com.android.build.gradle.internal.tasks.factory.dependsOn
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import java.io.File

abstract class AlpakaPlugin : Plugin<Project> {

@Suppress("DefaultLocale")
override fun apply(project: Project) {
val pluginExtension = project.extensions.create("alpaka", AlpakaPluginConfig::class.java, project)
val androidExtension = getAndroidExtension(project)
Expand Down Expand Up @@ -98,32 +104,28 @@ abstract class AlpakaPlugin : Plugin<Project> {
}
}

androidExtension.productFlavors.configureEach { flavor ->
// Add the property 'launcherIconLabel' to each flavor and set the default value to its name
val flavorName = flavor.name
flavor.launcherIconLabel = if (flavorName == "prod") null else flavorName
}

// Hook iconTask into android build process
project.afterEvaluate {
val buildDir = project.getBuildDirectory()
val labelAppIcons = pluginExtension.labelAppIcons.getOrElse(true)

androidExtension.buildTypes.configureEach { buildType ->
androidExtension.productFlavors.configureEach { flavor ->
val flavorName = flavor.name

// Add the property 'launcherIconLabel' to each flavor and set the default value to its name
flavor.launcherIconLabel = if (flavorName == "prod") null else flavorName

if (labelAppIcons) {
// make sure generated sources are used by build process
// Add generated icon path to res-SourceSet. This must be here otherwise it is too late!
val sourceSet = androidExtension.sourceSets.maybeCreate("$flavorName${buildType.name.capitalize()}")
sourceSet.res.srcDir("$buildDir/generated/res/launcher-icon/${flavorName}/")
}
}
}

androidExtension.applicationVariants.configureEach { variant ->
val variantName = variant.name
val flavor = variant.flavorName
val buildType = variant.buildType.name
val labelValue = launcherIconLabel(variant, androidExtension)
val labelValue = getLauncherIconLabel(variant, androidExtension)

if (labelAppIcons) {
// make sure generated sources are used by build process
// Add generated icon path to res-SourceSet. This must be here otherwise it is too late!
val sourceSet = androidExtension.sourceSets.maybeCreate(variantName)
sourceSet.res.srcDir(getGeneratedIconDir(project.layout.buildDirectory, flavor, buildType))
}

val iconTask = project.tasks.register(
"generateAppIcon${variantName.capitalize()}",
Expand All @@ -133,9 +135,9 @@ abstract class AlpakaPlugin : Plugin<Project> {
iconTask.flavor = flavor
iconTask.buildType = buildType
iconTask.labelValue = if (labelAppIcons) labelValue else null
iconTask.targetWebIconPath = getWebIconPath(buildDir, flavor)

iconTask.outputs.upToDateWhen { false } //always run the task
iconTask.targetWebIconFile = getGeneratedWebIconFile(project.layout.buildDirectory, flavor, buildType)
iconTask.generatedIconDir = getGeneratedIconDir(project.layout.buildDirectory, flavor, buildType)
iconTask.outputs.upToDateWhen { false } // always run the task
}

project.tasks.named("map${variantName.capitalize()}SourceSetPaths") { it.dependsOn(iconTask) }
Expand All @@ -148,53 +150,52 @@ abstract class AlpakaPlugin : Plugin<Project> {

// Hook uploadTask into android build process
project.afterEvaluate {
val buildDir = project.getBuildDirectory()

androidExtension.applicationVariants.configureEach { variant ->
val variantName = variant.name
val flavor = variant.flavorName
val buildType = variant.buildType.name
val uploadKey = uploadKey(variant, androidExtension)
val uploadKey = getUploadKey(variant, androidExtension)
if (buildType != "release") return@configureEach

val packageName = variant.applicationId
val minSdk = requireNotNull(androidExtension.defaultConfig.minSdk)
val targetSdk = requireNotNull(androidExtension.defaultConfig.targetSdk)
val versionName = requireNotNull(androidExtension.defaultConfig.versionName)

val uploadRequest = variant.outputs.first().let {
UploadRequest(
apk = it.outputFile,
appIcon = File(getWebIconPath(buildDir, flavor)),
appName = "", // Will be set from manifest inside the task
packageName = packageName,
flavor = flavor,
branch = buildBranch,
minSdk = minSdk,
targetSdk = targetSdk,
usesFeature = emptyList(), // Will be set from manifest inside the task
buildId = buildId,
buildNumber = buildNumber,
buildTime = buildTimestamp,
buildBatch = buildBatch,
changelog = "", // Will be set inside the task
signature = "", // Will be set inside the task
version = versionName,
)
}

project.tasks.register(
"uploadToAlpaka${variantName.capitalize()}",
UploadToAlpakaBackendTask::class.java
) { uploadTask ->
uploadTask.dependsOn("assemble${variantName.capitalize()}")
val uploadRequest = variant.outputs.first().let {
UploadRequest(
apk = it.outputFile,
appIcon = getGeneratedWebIconFile(project.layout.buildDirectory, flavor, buildType),
appName = "", // Will be set from manifest inside the task
packageName = packageName,
flavor = flavor,
branch = buildBranch,
minSdk = minSdk,
targetSdk = targetSdk,
usesFeature = emptyList(), // Will be set from manifest inside the task
buildId = buildId,
buildNumber = buildNumber,
buildTime = buildTimestamp,
buildBatch = buildBatch,
changelog = "", // Will be set inside the task
signature = "", // Will be set inside the task
version = versionName,
)
}

uploadTask.variant = variant
uploadTask.flavor = flavor
uploadTask.buildType = buildType
uploadTask.uploadKey = uploadKey ?: throw GradleException("No alpakaUploadKey specified")
uploadTask.proxy = pluginExtension.proxy.orNull
uploadTask.commitCount = pluginExtension.changelogCommitCount.orNull
uploadTask.uploadRequest = uploadRequest

uploadTask.dependsOn("assemble${variantName.capitalize()}")
}
}
}
Expand All @@ -206,23 +207,22 @@ abstract class AlpakaPlugin : Plugin<Project> {
return ext
}

private fun Project.getBuildDirectory(): File {
return project.layout.buildDirectory.asFile.get()
private fun getGeneratedWebIconFile(buildDir: DirectoryProperty, flavor: String, buildType: String): Provider<File> {
return getGeneratedIconDir(buildDir, flavor, buildType).map { it.file("web-icon.png").asFile }
}

private fun getWebIconPath(buildDir: File, flavor: String): String {
return "$buildDir/generated/res/launcher-icon/$flavor/web-icon.png"
private fun getGeneratedIconDir(buildDir: DirectoryProperty, flavor: String, buildType: String): Provider<Directory> {
return buildDir.dir("generated/res/launcher-icon/$flavor/$buildType/res")
}

private fun uploadKey(applicationVariant: ApplicationVariant, androidExtension: AppExtension): String? {
private fun getUploadKey(applicationVariant: ApplicationVariant, androidExtension: AppExtension): String? {
val productFlavor = applicationVariant.productFlavors.firstOrNull()
return productFlavor?.alpakaUploadKey ?: androidExtension.defaultConfig.alpakaUploadKey

}

private fun launcherIconLabel(applicationVariant: ApplicationVariant, androidExtension: AppExtension): String? {
private fun getLauncherIconLabel(applicationVariant: ApplicationVariant, androidExtension: AppExtension): String? {
val productFlavor = applicationVariant.productFlavors.firstOrNull()
return productFlavor?.launcherIconLabel ?: androidExtension.defaultConfig.launcherIconLabel
return productFlavor?.flavorLauncherIconLabel ?: androidExtension.defaultConfig.launcherIconLabel
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ private fun <T> ApplicationVariantDimension.setProperty(key: String, value: T) {
extensionAware.extraProperties[key] = value
}

private fun <T> ApplicationVariantDimension.getProperty(key: String): T {
val extensionAware = this as ExtensionAware
return extensionAware.extraProperties[key] as T
}

var ApplicationVariantDimension.launcherIconLabel: String?
get() = error("only setter")
get() = getProperty("launcherIconLabel")
set(value) = setProperty("launcherIconLabel", value)

var ApplicationVariantDimension.alpakaUploadKey: String?
get() = error("only setter")
set(value) = setProperty("alpakaUploadKey", value)
get() = getProperty("alpakaUploadKey")
set(value) = setProperty("alpakaUploadKey", value)
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package ch.ubique.gradle.alpaka.model

import ch.ubique.gradle.alpaka.network.dto.UploadDataDto
import org.gradle.api.provider.Provider
import java.io.File

data class UploadRequest(
val apk: File,
val appIcon: File,
val appIcon: Provider<File>,
val appName: String,
val packageName: String,
val flavor: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BackendRepository {

val response = service.appsUpload(
apk = uploadRequest.apk.toPartMap("apk", "application/octet-stream"),
icon = uploadRequest.appIcon.toPartMap("icon", "image/png"),
icon = uploadRequest.appIcon.get().toPartMap("icon", "image/png"),
data = data
).execute()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import ch.ubique.gradle.alpaka.extensions.olderThan
import ch.ubique.gradle.alpaka.utils.IconUtils
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.file.Directory
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import java.io.File

Expand All @@ -31,30 +33,27 @@ abstract class IconTask : DefaultTask() {
abstract var labelValue: String?

@get:Input
abstract var targetWebIconPath: String
abstract var targetWebIconFile: Provider<File>

@get:OutputDirectory
abstract var generatedIconDir: File

init {
val buildDir = project.layout.buildDirectory.asFile.get()
generatedIconDir = File("$buildDir/generated/res/launcher-icon/")
}
abstract var generatedIconDir: Provider<Directory>

@TaskAction
fun iconAction() {
val moduleDir = File(project.rootDir, project.name)
val targetWebIcon = File(targetWebIconPath).also {
val targetWebIcon = targetWebIconFile.get().also {
it.parentFile.mkdirs()
it.createNewFile()
}


val gradleLastModified = listOf(
File(moduleDir, "build.gradle").lastModified(),
File(moduleDir, "build.gradle.kts").lastModified(),
File(project.rootDir, "build.gradle").lastModified(),
File(project.rootDir, "build.gradle.kts").lastModified()
File(project.rootDir, "build.gradle.kts").lastModified(),
File(project.rootDir, "settings.gradle").lastModified(),
File(project.rootDir, "settings.gradle.kts").lastModified(),
File(project.rootDir, "gradle/libs.versions.toml").lastModified(),
).max()

val manifestFile = project.getMergedManifestFile(variantName)
Expand Down Expand Up @@ -85,7 +84,7 @@ abstract class IconTask : DefaultTask() {
allIcons.forEach iconsForEach@{ original ->
val resTypeName = original.parentFile.name
val originalBaseName = original.name.substringBefore(".")
val targetDir = File("${generatedIconDir}/$flavor/$resTypeName")
val targetDir = File(generatedIconDir.get().asFile, resTypeName)

val modified = targetDir.listFiles { file ->
file.name.matches(Regex("$originalBaseName\\.[^.]+"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object StringUtils {
val xmlParser = XmlParser(file)
xmlParser.findTagValue("string", mapOf("name" to labelName))
.takeIf { it.isNullOrEmpty().not() }
?.trim('"') // Strip PoEditor double quotes
?.trim('"') // Strip double quotes
}
}

Expand Down
21 changes: 19 additions & 2 deletions examplegroovy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,40 @@ android {
}

flavorDimensions = ["default"]

productFlavors {
dev {
dimension "default"
applicationIdSuffix ".dev"

alpakaUploadKey = "dev flavor upload key"
launcherIconLabel = "develop"
if (launcherIconLabel != "dev") {
throw new GradleException("Expected launcherIconLabel 'dev' but was $launcherIconLabel")
}
}
tescht {
dimension "default"
applicationIdSuffix ".test"
alpakaUploadKey = "test flavor upload key"
launcherIconLabel = "test"

if (launcherIconLabel != "test") {
throw new GradleException("Expected launcherIconLabel 'test' but was $launcherIconLabel")
}
}
prod {
dimension "default"

if (launcherIconLabel != null) {
throw new GradleException("Expected launcherIconLabel null but was $launcherIconLabel")
}
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
Expand Down
21 changes: 19 additions & 2 deletions examplekts/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,40 @@ android {
}

flavorDimensions += "default"

productFlavors {
create("dev") {
dimension = "default"
applicationIdSuffix = ".dev"

alpakaUploadKey = "dev flavor upload key"
launcherIconLabel = "develop"
if (launcherIconLabel != "dev") {
error("Expected launcherIconLabel 'dev' but was $launcherIconLabel")
}
}
create("tescht") {
dimension = "default"
applicationIdSuffix = ".test"
alpakaUploadKey = "test flavor upload key"
launcherIconLabel = "test"

if (launcherIconLabel != "test") {
error("Expected launcherIconLabel 'test' but was $launcherIconLabel")
}
}
create("prod") {
dimension = "default"

if (launcherIconLabel != null) {
error("Expected launcherIconLabel null but was $launcherIconLabel")
}
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
Expand Down

0 comments on commit 5f826a5

Please sign in to comment.