diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd5acf0..17953fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Build run: ./gradlew assemble - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-artifacts path: | diff --git a/docs/plugin.md b/docs/plugin.md index a3fa9ad..8a75523 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -54,10 +54,14 @@ appSizer { ``` ### Run the analysis - +If you need to analyze apk files generated from the aab file according to device specs: ```bash ./gradlew app:appSizeAnalysis[Release|Debug] --no-configure-on-demand --no-configuration-cache ``` +Or if you need to analyze the apk file that is the result of the assemble task, you can execute the following command: +```bash +./gradlew app:apkSizeAnalysis[Release|Debug] --no-configure-on-demand --no-configuration-cache +``` ## Configuration Use the registered `appSizer` extension block to the app module's `build.gradle` to configure App Sizer Plugin @@ -88,7 +92,7 @@ appSizer { variant.setIgnore(variant.flavors.contains("your-ignore-flavor")) } apk { - // APK Generation + // APK Generation from aab } } ... diff --git a/docs/task_graph.md b/docs/task_graph.md index eb8e12f..87410f8 100644 --- a/docs/task_graph.md +++ b/docs/task_graph.md @@ -3,8 +3,10 @@ flowchart TD A(generateApkDebug) B(generateArchiveDepDebug) C(appSizeAnalysisDebug) + D(apkSizeAnalysisDebug) C --> A C --> B + D --> B ``` diff --git a/sample/README.md b/sample/README.md index ad8774f..89b7c8d 100644 --- a/sample/README.md +++ b/sample/README.md @@ -34,7 +34,11 @@ appSizer { To run the App Sizer analysis using the Gradle plugin: 1. Open a terminal in the sample project directory. -2. Execute the following command: +2. If you need to analyze apk files generated from the aab file according to device specs: + ``` + ./gradlew app:appSizeAnalysisProRelease --no-configure-on-demand + ``` + Or if you need to analyze the apk file that is the result of the assemble task, you can execute the following command: ``` ./gradlew app:appSizeAnalysisProRelease --no-configure-on-demand ``` diff --git a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt index 677d9a3..af2c4bf 100644 --- a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt +++ b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/TaskManager.kt @@ -28,6 +28,7 @@ package com.grab.plugin.sizer import com.android.build.gradle.AppExtension +import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.api.BaseVariant import com.android.build.gradle.internal.dsl.BuildType import com.android.build.gradle.internal.dsl.ProductFlavor @@ -37,6 +38,7 @@ import com.grab.plugin.sizer.dependencies.* import com.grab.plugin.sizer.tasks.AppSizeAnalysisTask import com.grab.plugin.sizer.tasks.GenerateApkTask import com.grab.plugin.sizer.tasks.GenerateArchivesListTask +import com.grab.plugin.sizer.tasks.capitalize import com.grab.plugin.sizer.utils.isAndroidApplication import com.grab.plugin.sizer.utils.isAndroidLibrary import com.grab.plugin.sizer.utils.isJava @@ -44,7 +46,9 @@ import com.grab.plugin.sizer.utils.isKotlinJvm import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.file.Directory import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.listProperty import org.gradle.kotlin.dsl.the /* @@ -71,39 +75,75 @@ internal class TaskManager( val variantFilter = DefaultVariantFilter(variant) pluginExtension.input.variantFilter?.execute(variantFilter) if (!variantFilter.ignored) { - val generateApkTask = GenerateApkTask.registerTask( - project, - pluginExtension, - variant - ) val generateArchivesListTask = GenerateArchivesListTask.registerTask( - project, + project = project, variant = variant, flavorMatchingFallbacks = getProductFlavor(variant)?.matchingFallbacks ?: emptyList(), buildTypeMatchingFallbacks = getOriginalBuildType(variant).matchingFallbacks, enableMatchDebugVariant = pluginExtension.input.enableMatchDebugVariant ) - val appSizeAnalysisTask = AppSizeAnalysisTask.registerTask( - project, - variant, - pluginExtension, - generateApkTask, - generateArchivesListTask, - ) - registerAppSizeTaskDep(project, variant, this, appSizeAnalysisTask) + runCatching { + registerCollectDependenciesTask(project, variant, this) + }.onFailure { + project.logger.error("Can't create tasks for ${project.name} with variant ${variant.name}") + }.onSuccess { collectAppDependenciesTask -> + createAabAnalysisTask(project, variant, generateArchivesListTask).configure { + dependsOn(collectAppDependenciesTask) + } + createApkAnalysisTask(project, variant, generateArchivesListTask).configure { + dependsOn(collectAppDependenciesTask) + } + } } } } } - private fun registerAppSizeTaskDep( + private fun createApkAnalysisTask( + project: Project, + variant: ApplicationVariant, + generateArchivesListTask: TaskProvider + ) = AppSizeAnalysisTask.registerTask( + name = "apk", + project = project, + variant = variant, + pluginExtension = pluginExtension, + apkDirectories = variant.packageApplicationProvider.map { + project.objects.listProperty().value(listOf(it.outputDirectory.get())) + }, + generateArchivesListTask = generateArchivesListTask, + ) + + private fun createAabAnalysisTask( + project: Project, + variant: ApplicationVariant, + generateArchivesListTask: TaskProvider + ): TaskProvider { + val generateApkFromAabTask = GenerateApkTask.registerTask( + project, + pluginExtension, + variant + ) + + val appSizeAnalysisTask = AppSizeAnalysisTask.registerTask( + name = "app", + project = project, + variant = variant, + pluginExtension = pluginExtension, + apkDirectories = generateApkFromAabTask.map { it.outputDirectories }, + generateArchivesListTask = generateArchivesListTask, + ) + + return appSizeAnalysisTask + } + + private fun registerCollectDependenciesTask( project: Project, variant: BaseVariant, appExtension: AppExtension, - depTask: TaskProvider - ) { + ): TaskProvider { val dependenciesComponent = DaggerDependenciesComponent.factory().create( project = project, variantInput = variant.toVariantInput(), @@ -111,15 +151,19 @@ internal class TaskManager( buildTypeMatchingFallbacks = appExtension.getOriginalBuildType(variant).matchingFallbacks, enableMatchDebugVariant = pluginExtension.input.enableMatchDebugVariant ) + val collectDependenciesTask = project.tasks.register("collectAppDependencies${variant.name.capitalize()}") + val markAsChecked = mutableSetOf() - dfs(project, markAsChecked, dependenciesComponent, depTask) + dfs(project, markAsChecked, dependenciesComponent, collectDependenciesTask) + + return collectDependenciesTask } private fun dfs( project: Project, markAsChecked: MutableSet, dependenciesComponent: DependenciesComponent, - depTask: TaskProvider + depTask: TaskProvider ) { if (markAsChecked.contains(project.path)) return markAsChecked.add(project.path) @@ -135,7 +179,7 @@ internal class TaskManager( private fun handleSubProject( project: Project, - task: TaskProvider, + task: TaskProvider, variantExtractor: VariantExtractor ) { when { diff --git a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/ApkGeneratorExtension.kt b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/ApkGeneratorExtension.kt index 3b4454f..5912620 100644 --- a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/ApkGeneratorExtension.kt +++ b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/ApkGeneratorExtension.kt @@ -27,7 +27,6 @@ package com.grab.plugin.sizer.configuration -import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty diff --git a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/InputExtension.kt b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/InputExtension.kt index 7df0cc2..e908842 100644 --- a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/InputExtension.kt +++ b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/configuration/InputExtension.kt @@ -44,7 +44,6 @@ open class InputExtension @Inject constructor(objects: ObjectFactory) { var largeFileThreshold: Long = DEFAULT_LARGE_FILE var enableMatchDebugVariant = false - fun variantFilter(action: Action) { variantFilter = action } diff --git a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt index 351809c..7906f01 100644 --- a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt +++ b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/tasks/AppSizeAnalysisTask.kt @@ -48,10 +48,13 @@ import com.grab.sizer.report.db.InfluxDBConfig import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.ListProperty import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import java.io.File @@ -157,17 +160,18 @@ internal abstract class AppSizeAnalysisTask : DefaultTask() { companion object { fun registerTask( + name: String = "app", project: Project, variant: BaseVariant, pluginExtension: AppSizePluginExtension, - generateApkTask: TaskProvider, + apkDirectories: Provider>, generateArchivesListTask: TaskProvider, ): TaskProvider { return project.tasks.register( - "appSizeAnalysis${variant.name.capitalize()}", AppSizeAnalysisTask::class.java + "${name}SizeAnalysis${variant.name.capitalize()}", AppSizeAnalysisTask::class.java ) { this.variantInput.set(variant.toVariantInput()) - this.apkDirectories.setFrom(generateApkTask.map { it.outputDirectories }) + this.apkDirectories.setFrom(apkDirectories) this.archiveDepJsonFile.set(generateArchivesListTask.map { it.archiveDepFile.get() }) this.libName.set(project.params().libraryName()) this.option.set(project.params().option()) diff --git a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/utils/PluginInputProvider.kt b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/utils/PluginInputProvider.kt index 8f05bfa..9370103 100644 --- a/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/utils/PluginInputProvider.kt +++ b/sizer-gradle-plugin/src/main/kotlin/com/grab/plugin/sizer/utils/PluginInputProvider.kt @@ -34,6 +34,7 @@ import java.io.File private const val EXT_AAR = "aar" private const val EXT_JAR = "jar" +private const val EXT_APK = "apk" class PluginInputProvider( private val archiveDependencyStore: ArchiveDependencyStore, @@ -79,7 +80,8 @@ class PluginInputProvider( .filter { it.file.extension.equals(EXT_AAR, true) } override fun provideApkFiles(): Sequence { - return apksDirectory.listFiles()?.asSequence() ?: emptySequence() + return apksDirectory.listFiles()?.asSequence()?.filter { it.extension.equals(EXT_APK, true) } + ?: emptySequence() } override fun provideR8MappingFile(): File? = r8MappingFile