Skip to content

Commit

Permalink
Merge branch 'improve-tasks' into 'master'
Browse files Browse the repository at this point in the history
Improve tasks implementation

See merge request mobile/pax-app-core/app-sizer!45
  • Loading branch information
vanminh-grabtaxi committed Nov 22, 2024
2 parents 41ec60c + 7cf1864 commit 2df1e50
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 52 deletions.
8 changes: 4 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ To run analysis, execute

For plugin configuration options, see [Plugin Configuration][plugin_doc].


### Cli Tool Integration
To generate the command line binary file, execute
```text
./gradlew clt:shadowJar
```

1. Download the latest `clt-all.jar` from [Releases](link-to-releases)
2. Ensure Java 11+ is installed

To run analysis using the command line tool, execute
```text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ import org.gradle.api.Project
open class AppSizePluginExtension(val project: Project) {
var enabled = true

/**
* This is a workaround, by default, the ArchiveDep task haven't supported catching yet
* This flag to force the task become cacheable by default. It's not recommend to enable this flag
*/
var archiveDepTaskCacheable = false
var input = project.objects.newInstance(InputExtension::class.java, project.objects)
var metrics = project.objects.newInstance(MetricExtension::class.java, project)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ internal class TaskManager(
variant = variant,
flavorMatchingFallbacks = getProductFlavor(variant)?.matchingFallbacks ?: emptyList(),
buildTypeMatchingFallbacks = getOriginalBuildType(variant).matchingFallbacks,
enableMatchDebugVariant = pluginExtension.input.enableMatchDebugVariant,
archiveDepTaskCacheable = pluginExtension.archiveDepTaskCacheable
enableMatchDebugVariant = pluginExtension.input.enableMatchDebugVariant
)

val appSizeAnalysisTask = AppSizeAnalysisTask.registerTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import java.io.File


@CacheableTask
internal abstract class AppSizeAnalysisTask : DefaultTask() {

@get:Input
Expand All @@ -65,6 +65,7 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() {
abstract val customProperties: MapProperty<String, String>

@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val archiveDepJsonFile: RegularFileProperty

@get:InputFiles
Expand All @@ -79,10 +80,12 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() {

@get:InputFile
@get:Optional
@get:PathSensitive(PathSensitivity.NONE)
abstract val teamMappingFile: RegularFileProperty

@get:InputFile
@get:Optional
@get:PathSensitive(PathSensitivity.NONE)
abstract val r8MappingFile: RegularFileProperty

@get:Input
Expand All @@ -97,9 +100,17 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() {
@get:Optional
abstract val influxDBConfig: Property<InfluxDBConfig>

init {
group = "verification"
description = "Analyzes APK size and generates reports"

customProperties.convention(mapOf())
largeFileThreshold.convention(10L)
}

@TaskAction
fun run() {
validateInputs()
apkDirectories.forEach { apkDirectory ->
val projectInfo = ProjectInfo(
projectName = project.rootProject.name,
Expand All @@ -118,6 +129,11 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() {

}

private fun validateInputs() {
require(apkDirectories.files.isNotEmpty()) { "No APK directories found" }
require(archiveDepJsonFile.get().asFile.exists()) { "Archive dependency file not found" }
}

private fun createInputProvider(
archiveDependencyStore: ArchiveDependencyStore,
apksDirectory: File,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.LogLevel
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.api.tasks.Optional
import java.io.File
import java.util.*

Expand All @@ -54,8 +54,10 @@ private const val DEFAULT_DEVICE_SPEC = """

internal const val DEFAULT_DEVICE_NAME = "default_device"

@CacheableTask
internal abstract class GenerateApkTask : DefaultTask() {
@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val bundleToolFile: RegularFileProperty

@get:Input
Expand All @@ -66,15 +68,20 @@ internal abstract class GenerateApkTask : DefaultTask() {
abstract val deviceSpecFiles: ConfigurableFileCollection

@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val appBundleFile: RegularFileProperty

@get:Input
@get:Optional
abstract val signingConfig: Property<InternalSigningConfig>

@get:OutputDirectories
abstract val outputDirectories: ListProperty<Directory>

init {
group = "build"
description = "Generates APKs from App Bundle for different device specifications"

outputDirectories.convention(
// Add the provider to ensure the deviceSpecFiles values has set
project.provider {
Expand Down Expand Up @@ -106,7 +113,7 @@ internal abstract class GenerateApkTask : DefaultTask() {
extractApksToDirectory(tempFile, deviceSpecFile.path, outputDir)
} finally {
tempFile.delete()
project.logger.log(LogLevel.INFO, "Temp files were deleted")
logger.info("Temp files were deleted")
}
}
}
Expand Down Expand Up @@ -138,7 +145,7 @@ internal abstract class GenerateApkTask : DefaultTask() {
"--device-spec=${deviceSpec}",
)
}
project.logger.log(LogLevel.QUIET, "The Apks for $deviceSpec were extracted successfully")
logger.quiet("The Apks for $deviceSpec were extracted successfully")
}

private fun generateApksFile(apksTempFile: File, deviceSpec: String) {
Expand All @@ -160,7 +167,7 @@ internal abstract class GenerateApkTask : DefaultTask() {
"--overwrite"
)
}
project.logger.log(LogLevel.QUIET, "The app.apks generated successfully")
logger.quiet("The app.apks generated successfully")
}

private fun File.clearDirectory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ package com.grab.plugin.sizer.tasks

import com.android.build.gradle.api.BaseVariant
import com.grab.plugin.sizer.dependencies.*
import com.grab.sizer.utils.log
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.RegularFileProperty
Expand All @@ -39,13 +38,14 @@ import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.UntrackedTask

/**
* This task is used to generate the list of the [com.grab.plugin.sizer.dependencies.ArchiveDependency] to a json file
* The file will be consumed by the [AppSizeAnalysisTask] as the input for the list of aar/jar files
* This task is currently non-cacheable
*/
@UntrackedTask(because = "If there is any dependencies updated, the task cache should be invalidated")
internal abstract class GenerateArchivesListTask : DefaultTask() {
@get:Input
abstract val variantInput: Property<VariantInput>
Expand All @@ -59,32 +59,30 @@ internal abstract class GenerateArchivesListTask : DefaultTask() {
@get:Input
abstract val enableMatchDebugVariant: Property<Boolean>

/**
* This is a workaround, by default, this task haven't support catching yet
* This flag to force the task become cacheable by default. It's not recommend to enable this flag
*/
@get:Input
abstract val archiveDepTaskCacheable: Property<Boolean>


@get:OutputFile
abstract val archiveDepFile: RegularFileProperty

init {
/**
* Todo: Update this task to make it cacheable
* If there is any dependencies updated, the task cache should be invalidated
*/
outputs.upToDateWhen { archiveDepTaskCacheable.get() } // Mark this task as non-cacheable task
group = "build"
description = "Generates list of archive dependencies for app size analysis"

// Set property conventions
flavorMatchingFallbacks.convention(emptyList())
buildTypeMatchingFallbacks.convention(emptyList())
enableMatchDebugVariant.convention(false)
archiveDepFile.convention {
project.layout.buildDirectory.file("sizer/dep/${variantInput.get().name}/dependencies.json").get().asFile
project.layout.buildDirectory
.file("sizer/dep/${variantInput.get().name}/dependencies.json")
.get().asFile
}

}

@TaskAction
fun run() {
if(enableMatchDebugVariant.get()){
logger.info("Starting archive dependency generation for ${variantInput.get().name}")
if (enableMatchDebugVariant.get()) {
/**
* Extracts and manages project dependencies, separating modules from external libraries.
*
Expand Down Expand Up @@ -115,24 +113,26 @@ internal abstract class GenerateArchivesListTask : DefaultTask() {
(modules + libraries).toHashSet(),
archiveDepFile.get().asFile
)
}else{

} else {
createDependenciesComponent(false).run {
ArchiveDependencyManager().writeToJsonFile(
dependencyExtractor().extract(),
archiveDepFile.get().asFile
)
}
}

logger.info("Successfully generated archive dependencies")
}

private fun createDependenciesComponent(enableMatchDebugVariant : Boolean): DependenciesComponent = DaggerDependenciesComponent.factory().create(
project,
variantInput.get(),
flavorMatchingFallbacks.get(),
buildTypeMatchingFallbacks.get(),
enableMatchDebugVariant
)
private fun createDependenciesComponent(enableMatchDebugVariant: Boolean): DependenciesComponent =
DaggerDependenciesComponent.factory().create(
project,
variantInput.get(),
flavorMatchingFallbacks.get(),
buildTypeMatchingFallbacks.get(),
enableMatchDebugVariant
)

companion object {
fun registerTask(
Expand All @@ -141,17 +141,14 @@ internal abstract class GenerateArchivesListTask : DefaultTask() {
flavorMatchingFallbacks: List<String>,
buildTypeMatchingFallbacks: List<String>,
enableMatchDebugVariant: Boolean,
archiveDepTaskCacheable : Boolean
): TaskProvider<GenerateArchivesListTask> {
return project.tasks.register(
"generateArchiveDep${variant.name.capitalize()}", GenerateArchivesListTask::class.java
) {
this.variantInput.set(variant.toVariantInput())
this.buildTypeMatchingFallbacks.set(buildTypeMatchingFallbacks)
this.flavorMatchingFallbacks.set(flavorMatchingFallbacks)
this.enableMatchDebugVariant.set(enableMatchDebugVariant)
this.archiveDepTaskCacheable.set(archiveDepTaskCacheable)
}
) = project.tasks.register(
"generateArchiveDep${variant.name.capitalize()}",
GenerateArchivesListTask::class.java
) {
this.variantInput.set(variant.toVariantInput())
this.buildTypeMatchingFallbacks.set(buildTypeMatchingFallbacks)
this.flavorMatchingFallbacks.set(flavorMatchingFallbacks)
this.enableMatchDebugVariant.set(enableMatchDebugVariant)
}
}
}

0 comments on commit 2df1e50

Please sign in to comment.