From 7cf1864361bb79389dafe13f12ff69f1618d2fd8 Mon Sep 17 00:00:00 2001 From: Nguyen Van Minh Date: Sat, 23 Nov 2024 00:37:19 +0800 Subject: [PATCH] Improve tasks implementation --- docs/index.md | 8 +-- .../plugin/sizer/AppSizePluginExtension.kt | 5 -- .../com/grab/plugin/sizer/TaskManager.kt | 3 +- .../plugin/sizer/tasks/AppSizeAnalysisTask.kt | 18 ++++- .../plugin/sizer/tasks/GenerateApkTask.kt | 15 ++-- .../sizer/tasks/GenerateArchivesListTask.kt | 69 +++++++++---------- 6 files changed, 66 insertions(+), 52 deletions(-) diff --git a/docs/index.md b/docs/index.md index 6bd6260..4795330 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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 diff --git a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/AppSizePluginExtension.kt b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/AppSizePluginExtension.kt index cc6eb10..63c7e6c 100644 --- a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/AppSizePluginExtension.kt +++ b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/AppSizePluginExtension.kt @@ -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) diff --git a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt index ccecaf7..677d9a3 100644 --- a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt +++ b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt @@ -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( diff --git a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt index 58de94b..351809c 100644 --- a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt +++ b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt @@ -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 @@ -65,6 +65,7 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() { abstract val customProperties: MapProperty @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) abstract val archiveDepJsonFile: RegularFileProperty @get:InputFiles @@ -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 @@ -97,9 +100,17 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() { @get:Optional abstract val influxDBConfig: Property + 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, @@ -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, diff --git a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateApkTask.kt b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateApkTask.kt index 8699a7a..16b8dce 100644 --- a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateApkTask.kt +++ b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateApkTask.kt @@ -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.* @@ -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 @@ -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 @get:OutputDirectories abstract val outputDirectories: ListProperty 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 { @@ -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") } } } @@ -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) { @@ -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() { diff --git a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateArchivesListTask.kt b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateArchivesListTask.kt index 3f1aa5d..8ca88f9 100644 --- a/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateArchivesListTask.kt +++ b/gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/GenerateArchivesListTask.kt @@ -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 @@ -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 @@ -59,32 +59,30 @@ internal abstract class GenerateArchivesListTask : DefaultTask() { @get:Input abstract val enableMatchDebugVariant: Property - /** - * 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 - @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. * @@ -115,7 +113,8 @@ internal abstract class GenerateArchivesListTask : DefaultTask() { (modules + libraries).toHashSet(), archiveDepFile.get().asFile ) - }else{ + + } else { createDependenciesComponent(false).run { ArchiveDependencyManager().writeToJsonFile( dependencyExtractor().extract(), @@ -123,16 +122,17 @@ internal abstract class GenerateArchivesListTask : DefaultTask() { ) } } - + 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( @@ -141,17 +141,14 @@ internal abstract class GenerateArchivesListTask : DefaultTask() { flavorMatchingFallbacks: List, buildTypeMatchingFallbacks: List, enableMatchDebugVariant: Boolean, - archiveDepTaskCacheable : Boolean - ): TaskProvider { - 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) } } } \ No newline at end of file