From a3a01477931cd104cae0b44ebc7e5c822a5f9330 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:38:00 -0400 Subject: [PATCH 01/36] Make BugsnagInstallJniLibsTask support configuration caching --- .../BugsnagInstallJniLibsTask.kt | 39 ++++++++++++++----- .../BugsnagPlugin.kt | 29 +++++++++----- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 598aba49..bb4ce371 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -3,20 +3,19 @@ package com.bugsnag.android.gradle import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.CopySpec import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.WorkResult import java.io.File import javax.inject.Inject -open class BugsnagInstallJniLibsTask @Inject constructor( - objects: ObjectFactory -) : DefaultTask() { - +abstract class BugsnagInstallJniLibsTask(objects: ObjectFactory) : DefaultTask() { init { description = "Copies shared object files from the bugsnag-android AAR to the required build directory" group = BugsnagPlugin.GROUP_NAME @@ -26,15 +25,17 @@ open class BugsnagInstallJniLibsTask @Inject constructor( val buildDirDestination: RegularFileProperty = objects.fileProperty() @get:InputFiles - val bugsnagArtefacts: Property = objects.property(FileCollection::class.java) + val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() + + abstract fun copy(action: (CopySpec) -> Unit): WorkResult /** * Looks at all the dependencies and their dependencies and finds the `com.bugsnag` artifacts with SO files. */ @TaskAction fun setupNdkProject() { - bugsnagArtefacts.get().forEach { file: File -> - project.copy { + bugsnagArtifacts.forEach { file: File -> + copy { it.from(project.zipTree(file)) it.into(project.file(buildDirDestination)) } @@ -45,7 +46,7 @@ open class BugsnagInstallJniLibsTask @Inject constructor( private val sharedObjectAarIds = listOf("bugsnag-android", "bugsnag-android-ndk", "bugsnag-plugin-android-anr", "bugsnag-plugin-android-ndk") - internal fun resolveBugsnagArtefacts(project: Project): FileCollection { + internal fun resolveBugsnagArtifacts(project: Project): FileCollection { val files = project.configurations .filter { it.toString().contains("CompileClasspath") } .map { it.resolvedConfiguration } @@ -62,3 +63,23 @@ open class BugsnagInstallJniLibsTask @Inject constructor( } } } + +/** Legacy [BugsnagInstallJniLibsTask] task that requires using [Project]. */ +internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( + objects: ObjectFactory +) : BugsnagInstallJniLibsTask(objects) { + override fun copy(action: (CopySpec) -> Unit): WorkResult { + return project.copy(action) + } +} + +/** + * A Gradle 6.0+ compatible [BugsnagInstallJniLibsTask], which uses [FileSystemOperations] + * and supports configuration caching. + */ +internal open class BugsnagInstallJniLibsTaskGradle6Plus @Inject constructor( + objects: ObjectFactory, + private val fsOperations: FileSystemOperations +) : BugsnagInstallJniLibsTask(objects) { + override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) +} diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 64e8514d..6c69dbf2 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -7,7 +7,8 @@ import com.android.build.gradle.api.ApkVariant import com.android.build.gradle.api.ApkVariantOutput import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.tasks.ExternalNativeBuildTask -import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBugsnagArtefacts +import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBugsnagArtifacts +import org.gradle.api.Action import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project @@ -90,21 +91,31 @@ class BugsnagPlugin : Plugin { } } - private fun registerNdkLibInstallTask(project: Project, - bugsnag: BugsnagPluginExtension, - android: AppExtension) { + private fun registerNdkLibInstallTask( + project: Project, + bugsnag: BugsnagPluginExtension, + android: AppExtension + ) { val ndkTasks = project.tasks.withType(ExternalNativeBuildTask::class.java) val cleanTasks = ndkTasks.filter { it.name.contains(CLEAN_TASK) }.toSet() val buildTasks = ndkTasks.filter { !it.name.contains(CLEAN_TASK) }.toSet() if (buildTasks.isNotEmpty()) { - val ndkSetupTask = project.tasks.create("bugsnagInstallJniLibsTask", BugsnagInstallJniLibsTask::class.java) - ndkSetupTask.buildDirDestination.set(File(project.buildDir, "/intermediates/bugsnag-libs")) - val files = resolveBugsnagArtefacts(project) - ndkSetupTask.bugsnagArtefacts.set(files) + val configuration: Action = Action { + it.buildDirDestination.set(File(project.buildDir, "/intermediates/bugsnag-libs")) + val files = resolveBugsnagArtifacts(project) + it.bugsnagArtifacts.from(files) + } + val ndkSetupTask = if (project.gradle.gradleVersion.startsWith("6")) { + project.tasks.register("bugsnagInstallJniLibsTask", BugsnagInstallJniLibsTaskGradle6Plus::class.java, configuration) + } else { + project.tasks.register("bugsnagInstallJniLibsTask", BugsnagInstallJniLibsTaskLegacy::class.java, configuration) + } if (isNdkUploadEnabled(bugsnag, android)) { - ndkSetupTask.mustRunAfter(cleanTasks) + ndkSetupTask.configure { + it.mustRunAfter(cleanTasks) + } buildTasks.forEach { it.dependsOn(ndkSetupTask) } } } From d9746ed70f8dc480dd05978894832be2e609b6b4 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:43:14 -0400 Subject: [PATCH 02/36] Use providerfactory --- .../BugsnagReleasesTask.kt | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 8071b119..e8ba4b3a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -10,6 +10,7 @@ import org.gradle.api.logging.LogLevel import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property +import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.Internal @@ -37,7 +38,8 @@ import java.time.Duration import javax.inject.Inject open class BugsnagReleasesTask @Inject constructor( - objects: ObjectFactory + objects: ObjectFactory, + private val providerFactory: ProviderFactory ) : DefaultTask(), AndroidManifestInfoReceiver { init { @@ -127,7 +129,7 @@ open class BugsnagReleasesTask @Inject constructor( val payload = generateJsonPayload(manifestInfo) val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, payload.toString()) { - project.logger.lifecycle("Bugsnag: Attempting upload to Releases API") + logger.lifecycle("Bugsnag: Attempting upload to Releases API") lateinit var response: String object : Call(retryCount, logger) { override fun makeApiCall(): Boolean { @@ -140,7 +142,7 @@ open class BugsnagReleasesTask @Inject constructor( response } requestOutputFile.asFile.get().writeText(response) - project.logger.lifecycle("Bugsnag: Releases request complete") + logger.lifecycle("Bugsnag: Releases request complete") } private fun deliverPayload( @@ -255,17 +257,17 @@ open class BugsnagReleasesTask @Inject constructor( val gradleVersionString = project.gradle.gradleVersion val gradleVersionNumber = VersionNumber.parse(gradleVersionString) gradleVersion.set(gradleVersionString) - gitVersion.set(project.provider { runCmd(VCS_COMMAND, "--version") } ) + gitVersion.set(providerFactory.provider { runCmd(VCS_COMMAND, "--version") } ) if (gradleVersionNumber >= SYS_PROPERTIES_VERSION) { - osArch.set(project.providers.systemProperty(MK_OS_ARCH) ) - osName.set(project.providers.systemProperty(MK_OS_NAME) ) - osVersion.set(project.providers.systemProperty(MK_OS_VERSION) ) - javaVersion.set(project.providers.systemProperty(MK_JAVA_VERSION)) + osArch.set(providerFactory.systemProperty(MK_OS_ARCH) ) + osName.set(providerFactory.systemProperty(MK_OS_NAME) ) + osVersion.set(providerFactory.systemProperty(MK_OS_VERSION) ) + javaVersion.set(providerFactory.systemProperty(MK_JAVA_VERSION)) } else { - osArch.set(project.provider { System.getProperty(MK_OS_ARCH) } ) - osName.set(project.provider { System.getProperty(MK_OS_NAME) } ) - osVersion.set(project.provider { System.getProperty(MK_OS_VERSION) } ) - javaVersion.set(project.provider { System.getProperty(MK_JAVA_VERSION) }) + osArch.set(providerFactory.provider { System.getProperty(MK_OS_ARCH) } ) + osName.set(providerFactory.provider { System.getProperty(MK_OS_NAME) } ) + osVersion.set(providerFactory.provider { System.getProperty(MK_OS_VERSION) } ) + javaVersion.set(providerFactory.provider { System.getProperty(MK_JAVA_VERSION) }) } } From 7873dec3a6d5e61b509947b02457d25a07af1900 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:45:12 -0400 Subject: [PATCH 03/36] Use injected gradle version --- .../com.bugsnag.android.gradle/BugsnagReleasesTask.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index e8ba4b3a..f05c6f38 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -253,12 +253,13 @@ open class BugsnagReleasesTask @Inject constructor( } } - internal fun configureMetadata(project: Project) { - val gradleVersionString = project.gradle.gradleVersion - val gradleVersionNumber = VersionNumber.parse(gradleVersionString) - gradleVersion.set(gradleVersionString) + internal fun configureMetadata() { + val gradleVersionNumber = gradleVersion.orNull?.let { + gradleVersion.set(it) + VersionNumber.parse(it) + } gitVersion.set(providerFactory.provider { runCmd(VCS_COMMAND, "--version") } ) - if (gradleVersionNumber >= SYS_PROPERTIES_VERSION) { + if (gradleVersionNumber != null && gradleVersionNumber >= SYS_PROPERTIES_VERSION) { osArch.set(providerFactory.systemProperty(MK_OS_ARCH) ) osName.set(providerFactory.systemProperty(MK_OS_NAME) ) osVersion.set(providerFactory.systemProperty(MK_OS_VERSION) ) From 8a0c008ae0d28c3988a51c1bd3a101dd6c539883 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:50:43 -0400 Subject: [PATCH 04/36] Fix doc --- .../com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index bb4ce371..f77a98b3 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -64,7 +64,7 @@ abstract class BugsnagInstallJniLibsTask(objects: ObjectFactory) : DefaultTask() } } -/** Legacy [BugsnagInstallJniLibsTask] task that requires using [Project]. */ +/** Legacy [BugsnagInstallJniLibsTask] task that requires using [getProject]. */ internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( objects: ObjectFactory ) : BugsnagInstallJniLibsTask(objects) { From a0af86aafa5f3243071be7e26ed59539d6d0d1b2 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:57:36 -0400 Subject: [PATCH 05/36] Make BugsnagReleasesTask compatible with configuration caching --- .../BugsnagPlugin.kt | 34 +++++++------ .../BugsnagReleasesTask.kt | 50 ++++++++++++++++++- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 6c69dbf2..6586888b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -243,26 +243,28 @@ class BugsnagPlugin : Plugin { } } - private fun registerReleasesUploadTask(project: Project, - variant: ApkVariant, - output: ApkVariantOutput, - bugsnag: BugsnagPluginExtension): TaskProvider { + private fun registerReleasesUploadTask( + project: Project, + variant: ApkVariant, + output: ApkVariantOutput, + bugsnag: BugsnagPluginExtension + ): TaskProvider { val outputName = taskNameForOutput(output) val taskName = "bugsnagRelease${outputName}Task" val path = "intermediates/bugsnag/requests/releasesFor${outputName}.json" val requestOutputFile = project.layout.buildDirectory.file(path) - return project.tasks.register(taskName, BugsnagReleasesTask::class.java) { - it.requestOutputFile.set(requestOutputFile) - it.retryCount.set(bugsnag.retryCount) - it.timeoutMillis.set(bugsnag.requestTimeoutMs) - it.releasesEndpoint.set(bugsnag.releasesEndpoint) - it.sourceControlProvider.set(bugsnag.sourceControl.provider) - it.sourceControlRepository.set(bugsnag.sourceControl.repository) - it.sourceControlRevision.set(bugsnag.sourceControl.revision) - it.metadata.set(bugsnag.metadata) - it.builderName.set(bugsnag.builderName) - addTaskToExecutionGraph(it, variant, output, project, bugsnag, bugsnag.reportBuilds.get()) - it.configureMetadata(project) + return BugsnagReleasesTask.register(project, taskName) { + this.requestOutputFile.set(requestOutputFile) + retryCount.set(bugsnag.retryCount) + timeoutMillis.set(bugsnag.requestTimeoutMs) + releasesEndpoint.set(bugsnag.releasesEndpoint) + sourceControlProvider.set(bugsnag.sourceControl.provider) + sourceControlRepository.set(bugsnag.sourceControl.repository) + sourceControlRevision.set(bugsnag.sourceControl.revision) + metadata.set(bugsnag.metadata) + builderName.set(bugsnag.builderName) + addTaskToExecutionGraph(this, variant, output, project, bugsnag, bugsnag.reportBuilds.get()) + configureMetadata() } } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index f05c6f38..e5037a62 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -20,6 +20,10 @@ import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity.NONE import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.TaskProvider +import org.gradle.process.ExecOperations +import org.gradle.process.ExecResult +import org.gradle.process.ExecSpec import org.gradle.process.internal.ExecException import org.gradle.util.VersionNumber import retrofit2.Response @@ -37,7 +41,7 @@ import java.nio.charset.Charset import java.time.Duration import javax.inject.Inject -open class BugsnagReleasesTask @Inject constructor( +abstract class BugsnagReleasesTask( objects: ObjectFactory, private val providerFactory: ProviderFactory ) : DefaultTask(), AndroidManifestInfoReceiver { @@ -123,6 +127,8 @@ open class BugsnagReleasesTask @Inject constructor( @get:Optional val gitVersion: Property = objects.property(String::class.java) + abstract fun exec(action: (ExecSpec) -> Unit): ExecResult + @TaskAction fun fetchReleaseInfo() { val manifestInfo = parseManifestInfo() @@ -242,7 +248,7 @@ open class BugsnagReleasesTask @Inject constructor( private fun runCmd(vararg cmd: String): String? { return try { val baos = ByteArrayOutputStream() - project.exec { execSpec -> + exec { execSpec -> execSpec.commandLine(*cmd) execSpec.standardOutput = baos logging.captureStandardError(LogLevel.INFO) @@ -321,6 +327,46 @@ open class BugsnagReleasesTask @Inject constructor( .build() .create() } + + /** + * Registers the appropriate subtype to this [project] with the given [name] and + * [configurationAction] + */ + internal fun register( + project: Project, + name: String, + configurationAction: BugsnagReleasesTask.() -> Unit + ): TaskProvider { + return if (project.gradle.gradleVersion.startsWith('6')) { + project.tasks.register(name, BugsnagReleasesTaskGradle6Plus::class.java, configurationAction) + } else { + project.tasks.register(name, BugsnagReleasesTaskLegacy::class.java, configurationAction) + } + } + } +} + +/** Legacy [BugsnagReleasesTask] task that requires using [getProject]. */ +internal open class BugsnagReleasesTaskLegacy @Inject constructor( + objects: ObjectFactory, + providerFactory: ProviderFactory +) : BugsnagReleasesTask(objects, providerFactory) { + override fun exec(action: (ExecSpec) -> Unit): ExecResult { + return project.exec(action) + } +} + +/** + * A Gradle 6.0+ compatible [BugsnagReleasesTask], which uses [ExecOperations] + * and supports configuration caching. + */ +internal open class BugsnagReleasesTaskGradle6Plus @Inject constructor( + objects: ObjectFactory, + providerFactory: ProviderFactory, + private val execOps: ExecOperations +) : BugsnagReleasesTask(objects, providerFactory) { + override fun exec(action: (ExecSpec) -> Unit): ExecResult { + return execOps.exec(action) } } From 7fc125df271d310c4b0007c65426fbf49b1a1603 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 19:59:13 -0400 Subject: [PATCH 06/36] Use register pattern --- .../BugsnagInstallJniLibsTask.kt | 17 +++++++++++++++++ .../com.bugsnag.android.gradle/BugsnagPlugin.kt | 12 +++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index f77a98b3..6ac23c93 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -11,6 +11,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.WorkResult import java.io.File import javax.inject.Inject @@ -61,6 +62,22 @@ abstract class BugsnagInstallJniLibsTask(objects: ObjectFactory) : DefaultTask() .toSet() return project.files(files) } + + /** + * Registers the appropriate subtype to this [project] with the given [name] and + * [configurationAction] + */ + internal fun register( + project: Project, + name: String, + configurationAction: BugsnagInstallJniLibsTask.() -> Unit + ): TaskProvider { + return if (project.gradle.gradleVersion.startsWith('6')) { + project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) + } else { + project.tasks.register(name, BugsnagInstallJniLibsTaskLegacy::class.java, configurationAction) + } + } } } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 6586888b..7f733b8f 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -8,7 +8,6 @@ import com.android.build.gradle.api.ApkVariantOutput import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.tasks.ExternalNativeBuildTask import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBugsnagArtifacts -import org.gradle.api.Action import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project @@ -101,15 +100,10 @@ class BugsnagPlugin : Plugin { val buildTasks = ndkTasks.filter { !it.name.contains(CLEAN_TASK) }.toSet() if (buildTasks.isNotEmpty()) { - val configuration: Action = Action { - it.buildDirDestination.set(File(project.buildDir, "/intermediates/bugsnag-libs")) + val ndkSetupTask = BugsnagInstallJniLibsTask.register(project, "bugsnagInstallJniLibsTask") { + buildDirDestination.set(File(project.buildDir, "/intermediates/bugsnag-libs")) val files = resolveBugsnagArtifacts(project) - it.bugsnagArtifacts.from(files) - } - val ndkSetupTask = if (project.gradle.gradleVersion.startsWith("6")) { - project.tasks.register("bugsnagInstallJniLibsTask", BugsnagInstallJniLibsTaskGradle6Plus::class.java, configuration) - } else { - project.tasks.register("bugsnagInstallJniLibsTask", BugsnagInstallJniLibsTaskLegacy::class.java, configuration) + bugsnagArtifacts.from(files) } if (isNdkUploadEnabled(bugsnag, android)) { From a85f901128778ff3ccda023bde4a0cfe665ac9de Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:02:45 -0400 Subject: [PATCH 07/36] Use ProjectLayout --- .../BugsnagInstallJniLibsTask.kt | 19 +++++++++++++------ .../BugsnagPlugin.kt | 2 -- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 6ac23c93..29760078 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -4,9 +4,10 @@ import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.CopySpec +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemOperations -import org.gradle.api.file.RegularFileProperty +import org.gradle.api.file.ProjectLayout import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory @@ -16,14 +17,18 @@ import org.gradle.api.tasks.WorkResult import java.io.File import javax.inject.Inject -abstract class BugsnagInstallJniLibsTask(objects: ObjectFactory) : DefaultTask() { +abstract class BugsnagInstallJniLibsTask( + objects: ObjectFactory, + projectLayout: ProjectLayout +) : DefaultTask() { init { description = "Copies shared object files from the bugsnag-android AAR to the required build directory" group = BugsnagPlugin.GROUP_NAME } @get:OutputDirectory - val buildDirDestination: RegularFileProperty = objects.fileProperty() + val buildDirDestination: DirectoryProperty = objects.directoryProperty() + .convention(projectLayout.buildDirectory.dir("intermediates/bugsnag-libs")) @get:InputFiles val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() @@ -83,8 +88,9 @@ abstract class BugsnagInstallJniLibsTask(objects: ObjectFactory) : DefaultTask() /** Legacy [BugsnagInstallJniLibsTask] task that requires using [getProject]. */ internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( - objects: ObjectFactory -) : BugsnagInstallJniLibsTask(objects) { + objects: ObjectFactory, + projectLayout: ProjectLayout +) : BugsnagInstallJniLibsTask(objects, projectLayout) { override fun copy(action: (CopySpec) -> Unit): WorkResult { return project.copy(action) } @@ -96,7 +102,8 @@ internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( */ internal open class BugsnagInstallJniLibsTaskGradle6Plus @Inject constructor( objects: ObjectFactory, + projectLayout: ProjectLayout, private val fsOperations: FileSystemOperations -) : BugsnagInstallJniLibsTask(objects) { +) : BugsnagInstallJniLibsTask(objects, projectLayout) { override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 7f733b8f..eed99ad0 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -15,7 +15,6 @@ import org.gradle.api.Task import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider -import java.io.File import java.util.UUID /** @@ -101,7 +100,6 @@ class BugsnagPlugin : Plugin { if (buildTasks.isNotEmpty()) { val ndkSetupTask = BugsnagInstallJniLibsTask.register(project, "bugsnagInstallJniLibsTask") { - buildDirDestination.set(File(project.buildDir, "/intermediates/bugsnag-libs")) val files = resolveBugsnagArtifacts(project) bugsnagArtifacts.from(files) } From 61e14df811f2cbafdd9a1a018a07ca484ea55d4b Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:03:12 -0400 Subject: [PATCH 08/36] Make classes sealed to prevent extra source extension --- .../com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt | 2 +- .../kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 29760078..7059085a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -17,7 +17,7 @@ import org.gradle.api.tasks.WorkResult import java.io.File import javax.inject.Inject -abstract class BugsnagInstallJniLibsTask( +sealed class BugsnagInstallJniLibsTask( objects: ObjectFactory, projectLayout: ProjectLayout ) : DefaultTask() { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index e5037a62..5f1c95c5 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -41,7 +41,7 @@ import java.nio.charset.Charset import java.time.Duration import javax.inject.Inject -abstract class BugsnagReleasesTask( +sealed class BugsnagReleasesTask( objects: ObjectFactory, private val providerFactory: ProviderFactory ) : DefaultTask(), AndroidManifestInfoReceiver { From cf428fcedf88da0f6cdcd94738c0a5df3dd8d06e Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:13:42 -0400 Subject: [PATCH 09/36] Make exec internal --- .../kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 5f1c95c5..5426d1cd 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -127,7 +127,7 @@ sealed class BugsnagReleasesTask( @get:Optional val gitVersion: Property = objects.property(String::class.java) - abstract fun exec(action: (ExecSpec) -> Unit): ExecResult + internal abstract fun exec(action: (ExecSpec) -> Unit): ExecResult @TaskAction fun fetchReleaseInfo() { From e0b9033c9ab55b171c9391c2eb54c8dfac58c514 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:16:25 -0400 Subject: [PATCH 10/36] Fully support configuration caching in BugsnagInstallJniLibsTask --- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- gradlew.bat | 21 ++------ .../BugsnagInstallJniLibsTask.kt | 47 ++++++++++++++---- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 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 Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8e9b6083..910c5a98 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Mon Jul 06 17:13:48 BST 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-rc-6-all.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index a9f778a7..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 7059085a..156d5193 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -2,11 +2,13 @@ package com.bugsnag.android.gradle import org.gradle.api.DefaultTask import org.gradle.api.Project +import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.CopySpec import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemOperations +import org.gradle.api.file.FileTree import org.gradle.api.file.ProjectLayout import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.InputFiles @@ -33,17 +35,19 @@ sealed class BugsnagInstallJniLibsTask( @get:InputFiles val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() - abstract fun copy(action: (CopySpec) -> Unit): WorkResult + internal abstract fun copy(action: (CopySpec) -> Unit): WorkResult + internal abstract fun zipTree(file: File): FileTree /** * Looks at all the dependencies and their dependencies and finds the `com.bugsnag` artifacts with SO files. */ @TaskAction fun setupNdkProject() { + val destination = buildDirDestination.asFile.get() bugsnagArtifacts.forEach { file: File -> copy { - it.from(project.zipTree(file)) - it.into(project.file(buildDirDestination)) + it.from(zipTree(file)) + it.into(destination) } } } @@ -77,8 +81,13 @@ sealed class BugsnagInstallJniLibsTask( name: String, configurationAction: BugsnagInstallJniLibsTask.() -> Unit ): TaskProvider { - return if (project.gradle.gradleVersion.startsWith('6')) { - project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) + val gradleVersion = project.gradle.gradleVersion + return if (gradleVersion.startsWith('6')) { + if (gradleVersion.startsWith("6.6")) { + project.tasks.register(name, BugsnagInstallJniLibsTaskGradle66Plus::class.java, configurationAction) + } else { + project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) + } } else { project.tasks.register(name, BugsnagInstallJniLibsTaskLegacy::class.java, configurationAction) } @@ -94,16 +103,36 @@ internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( override fun copy(action: (CopySpec) -> Unit): WorkResult { return project.copy(action) } + + override fun zipTree(file: File): FileTree { + return project.zipTree(file) + } } -/** - * A Gradle 6.0+ compatible [BugsnagInstallJniLibsTask], which uses [FileSystemOperations] - * and supports configuration caching. - */ +/** A Gradle 6+ compatible [BugsnagInstallJniLibsTask], which uses [FileSystemOperations]. */ internal open class BugsnagInstallJniLibsTaskGradle6Plus @Inject constructor( objects: ObjectFactory, projectLayout: ProjectLayout, private val fsOperations: FileSystemOperations ) : BugsnagInstallJniLibsTask(objects, projectLayout) { override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) + override fun zipTree(file: File): FileTree { + return project.zipTree(file) + } +} + +/** + * A Gradle 6.6+ compatible [BugsnagInstallJniLibsTask], which uses [FileSystemOperations] + * and [ArchiveOperations] to support configuration caching. + */ +internal open class BugsnagInstallJniLibsTaskGradle66Plus @Inject constructor( + objects: ObjectFactory, + projectLayout: ProjectLayout, + private val fsOperations: FileSystemOperations, + private val archiveOperations: ArchiveOperations +) : BugsnagInstallJniLibsTask(objects, projectLayout) { + override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) + override fun zipTree(file: File): FileTree { + return archiveOperations.zipTree(file) + } } From 757f36aed2e2a7abc86d6bd241fee8794abf9e3f Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:20:12 -0400 Subject: [PATCH 11/36] Use more flexible versioning checks Just checking the first char isn't enough! --- .../BugsnagInstallJniLibsTask.kt | 6 +++--- .../com.bugsnag.android.gradle/BugsnagReleasesTask.kt | 2 +- .../com.bugsnag.android.gradle/GradleVersions.kt | 11 +++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 156d5193..7cde4449 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -81,9 +81,9 @@ sealed class BugsnagInstallJniLibsTask( name: String, configurationAction: BugsnagInstallJniLibsTask.() -> Unit ): TaskProvider { - val gradleVersion = project.gradle.gradleVersion - return if (gradleVersion.startsWith('6')) { - if (gradleVersion.startsWith("6.6")) { + val gradleVersion = project.gradle.versionNumber() + return if (gradleVersion >= GradleVersions.VERSION_6) { + if (gradleVersion >= GradleVersions.VERSION_6_6) { project.tasks.register(name, BugsnagInstallJniLibsTaskGradle66Plus::class.java, configurationAction) } else { project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 5426d1cd..3dbe883c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -337,7 +337,7 @@ sealed class BugsnagReleasesTask( name: String, configurationAction: BugsnagReleasesTask.() -> Unit ): TaskProvider { - return if (project.gradle.gradleVersion.startsWith('6')) { + return if (project.gradle.versionNumber() >= GradleVersions.VERSION_6) { project.tasks.register(name, BugsnagReleasesTaskGradle6Plus::class.java, configurationAction) } else { project.tasks.register(name, BugsnagReleasesTaskLegacy::class.java, configurationAction) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt new file mode 100644 index 00000000..7f1813db --- /dev/null +++ b/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt @@ -0,0 +1,11 @@ +package com.bugsnag.android.gradle + +import org.gradle.api.invocation.Gradle +import org.gradle.util.VersionNumber + +internal object GradleVersions { + val VERSION_6 = VersionNumber.parse("6.0") + val VERSION_6_6 = VersionNumber.parse("6.6") +} + +internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleVersion) From 98d8c7a0881a3353088db44870c2b2ecb724100a Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:25:31 -0400 Subject: [PATCH 12/36] Make BugsnagUploadNdkTask compatible with configuration caching --- .../BugsnagPlugin.kt | 1 + .../BugsnagUploadNdkTask.kt | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index eed99ad0..bbd4a10b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -230,6 +230,7 @@ class BugsnagPlugin : Plugin { it.projectRoot.set(bugsnag.projectRoot.getOrElse(project.projectDir.toString())) it.searchDirectories.set(getSearchDirectories(project, variant)) it.variantOutput = output + it.objDumpPaths.set(bugsnag.objdumpPaths) addTaskToExecutionGraph(it, variant, output, project, bugsnag, true) it.configureWith(bugsnag) } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 8ec92288..af33f7b4 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -11,14 +11,18 @@ import okio.source import org.apache.tools.ant.taskdefs.condition.Os import org.gradle.api.DefaultTask import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection +import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity.NONE @@ -42,7 +46,8 @@ import javax.inject.Inject * a build. */ open class BugsnagUploadNdkTask @Inject constructor( - objects: ObjectFactory + objects: ObjectFactory, + projectLayout: ProjectLayout ) : DefaultTask(), AndroidManifestInfoReceiver, BugsnagFileUploadTask { init { @@ -69,6 +74,10 @@ open class BugsnagUploadNdkTask @Inject constructor( @get:OutputFile val requestOutputFile: RegularFileProperty = objects.fileProperty() + @get:OutputDirectory + val intermediateOutputDir: DirectoryProperty = objects.directoryProperty() + .convention(projectLayout.buildDirectory.dir("intermediates/bugsnag")) + @get:Input override val failOnUploadError: Property = objects.property(Boolean::class.javaObjectType) @@ -84,18 +93,21 @@ open class BugsnagUploadNdkTask @Inject constructor( @get:Input override val timeoutMillis: Property = objects.property(Long::class.javaObjectType) + @get:Input + val objDumpPaths: MapProperty = objects.mapProperty(String::class.java, String::class.java) + @TaskAction fun upload() { - project.logger.lifecycle("Starting ndk upload") + logger.lifecycle("Starting ndk upload") val searchDirs = searchDirectories.get().files.toList() val files = findSharedObjectMappingFiles(project, variantOutput, searchDirs) - project.logger.lifecycle("Processing shared object files") + logger.lifecycle("Processing shared object files") processFiles(files) requestOutputFile.asFile.get().writeText("OK") } private fun processFiles(files: Collection) { - project.logger.info("Bugsnag: Found shared object files for upload: $files") + logger.info("Bugsnag: Found shared object files for upload: $files") files.forEach { file -> processFile(file) @@ -119,14 +131,11 @@ open class BugsnagUploadNdkTask @Inject constructor( private fun generateSymbolsForSharedObject(sharedObject: File, arch: String): File? { // Get the path the version of objdump to use to get symbols val objDumpPath = getObjDumpExecutable(arch) - val logger = project.logger + val logger = logger if (objDumpPath != null) { val outReader: Reader? = null try { - val outputDir = File(project.buildDir, "bugsnag") - if (!outputDir.exists()) { - outputDir.mkdir() - } + val outputDir = intermediateOutputDir.asFile.get() val outputFile = File(outputDir, "$arch.gz") val errorOutputFile = File(outputDir, "$arch.error.txt") logger.info("Bugsnag: Creating symbol file for $arch at $outputFile") @@ -168,7 +177,7 @@ open class BugsnagUploadNdkTask @Inject constructor( // a SO file may not contain debug info. if that's the case then the mapping file should be very small, // so we try and reject it here as otherwise the event-worker will reject it with a 400 status code. if (!mappingFile.exists() || mappingFile.length() < VALID_SO_FILE_THRESHOLD) { - project.logger.warn("Bugsnag: Skipping upload of empty/invalid mapping file: $mappingFile") + logger.warn("Bugsnag: Skipping upload of empty/invalid mapping file: $mappingFile") return } val parts = mutableMapOf() @@ -181,13 +190,13 @@ open class BugsnagUploadNdkTask @Inject constructor( } parts["projectRoot"] = projectRoot.get().toTextRequestBody() val request = BugsnagMultiPartUploadRequest.from(this) - project.logger.lifecycle("Bugsnag: Attempting to upload shared object mapping " + + logger.lifecycle("Bugsnag: Attempting to upload shared object mapping " + "file for $sharedObjectName-$arch from $mappingFile") val manifestInfo = parseManifestInfo() val mappingFileContents = mappingFile.readText() val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, mappingFileContents) { - project.logger.lifecycle("Bugsnag: Attempting to upload shared object mapping " + + logger.lifecycle("Bugsnag: Attempting to upload shared object mapping " + "file for $sharedObjectName-$arch from $mappingFile") request.uploadMultipartEntity(parts, parseManifestInfo()) } @@ -210,15 +219,13 @@ open class BugsnagUploadNdkTask @Inject constructor( } return objDumpFile } catch (ex: Throwable) { - project.logger.error("Bugsnag: Error attempting to calculate objdump location: " + ex.message) + logger.error("Bugsnag: Error attempting to calculate objdump location: " + ex.message) } return null } private fun getObjDumpOverride(arch: String): String? { - val bugsnag = project.extensions.getByType(BugsnagPluginExtension::class.java) - val paths = bugsnag.objdumpPaths - return paths.get()[arch] + return objDumpPaths.get()[arch] } companion object { From 65d4f1a1929e3840a387dbf10df47d54a0e06b8a Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 20:26:20 -0400 Subject: [PATCH 13/36] Make BugsnagUploadProguardTask compatible with configuration caching --- .../com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt index 7838bad6..2361f68a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt @@ -69,13 +69,12 @@ open class BugsnagUploadProguardTask @Inject constructor( fun upload() { val mappingFile = mappingFileProperty.asFile.get() if (mappingFile.length() == 0L) { // proguard's -dontobfuscate generates an empty mapping file - project.logger.warn("Bugsnag: Ignoring empty proguard file") + logger.warn("Bugsnag: Ignoring empty proguard file") return } if (!mappingFile.exists()) { logger.warn("Bugsnag: Mapping file not found: $mappingFile") - val bugsnag = project.extensions.findByType(BugsnagPluginExtension::class.java)!! - if (bugsnag.failOnUploadError.get()) { + if (failOnUploadError.get()) { throw IllegalStateException("Mapping file not found: $mappingFile") } } From a9f26ceb75170221f30b33693fa550d422524654 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 21:56:59 -0400 Subject: [PATCH 14/36] Match naming pattern --- .../kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 3dbe883c..0bc73f0c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -363,10 +363,10 @@ internal open class BugsnagReleasesTaskLegacy @Inject constructor( internal open class BugsnagReleasesTaskGradle6Plus @Inject constructor( objects: ObjectFactory, providerFactory: ProviderFactory, - private val execOps: ExecOperations + private val execOperations: ExecOperations ) : BugsnagReleasesTask(objects, providerFactory) { override fun exec(action: (ExecSpec) -> Unit): ExecResult { - return execOps.exec(action) + return execOperations.exec(action) } } From 1c212fd560ca9c683192052757183794fefe9681 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 21:57:21 -0400 Subject: [PATCH 15/36] Add gradle version input --- src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index bbd4a10b..1d56778a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -256,6 +256,7 @@ class BugsnagPlugin : Plugin { sourceControlRevision.set(bugsnag.sourceControl.revision) metadata.set(bugsnag.metadata) builderName.set(bugsnag.builderName) + gradleVersion.set(project.gradle.gradleVersion) addTaskToExecutionGraph(this, variant, output, project, bugsnag, bugsnag.reportBuilds.get()) configureMetadata() } From a59825afaf4033213e5e2dfc5eb17cf9cc64446d Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:26:45 -0400 Subject: [PATCH 16/36] Fix fileCollection use on older versions --- .../BugsnagInstallJniLibsTask.kt | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 7cde4449..906f75c8 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -32,8 +32,7 @@ sealed class BugsnagInstallJniLibsTask( val buildDirDestination: DirectoryProperty = objects.directoryProperty() .convention(projectLayout.buildDirectory.dir("intermediates/bugsnag-libs")) - @get:InputFiles - val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() + abstract val bugsnagArtifacts: ConfigurableFileCollection internal abstract fun copy(action: (CopySpec) -> Unit): WorkResult internal abstract fun zipTree(file: File): FileTree @@ -88,6 +87,8 @@ sealed class BugsnagInstallJniLibsTask( } else { project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) } + } else if (gradleVersion >= GradleVersions.VERSION_5_3) { + project.tasks.register(name, BugsnagInstallJniLibsTask53Plus::class.java, configurationAction) } else { project.tasks.register(name, BugsnagInstallJniLibsTaskLegacy::class.java, configurationAction) } @@ -95,18 +96,32 @@ sealed class BugsnagInstallJniLibsTask( } } -/** Legacy [BugsnagInstallJniLibsTask] task that requires using [getProject]. */ +/** + * Legacy [BugsnagInstallJniLibsTask] task that requires using [getProject] and + * [ProjectLayout.configurableFiles]. + */ internal open class BugsnagInstallJniLibsTaskLegacy @Inject constructor( objects: ObjectFactory, projectLayout: ProjectLayout ) : BugsnagInstallJniLibsTask(objects, projectLayout) { - override fun copy(action: (CopySpec) -> Unit): WorkResult { - return project.copy(action) - } + @Suppress("DEPRECATION") // Here for backward compatibility + @get:InputFiles + override val bugsnagArtifacts: ConfigurableFileCollection = projectLayout.configurableFiles() - override fun zipTree(file: File): FileTree { - return project.zipTree(file) - } + override fun copy(action: (CopySpec) -> Unit): WorkResult = project.copy(action) + override fun zipTree(file: File): FileTree = project.zipTree(file) +} + +/** Legacy [BugsnagInstallJniLibsTask] task that requires using [getProject]. */ +internal open class BugsnagInstallJniLibsTask53Plus @Inject constructor( + objects: ObjectFactory, + projectLayout: ProjectLayout +) : BugsnagInstallJniLibsTask(objects, projectLayout) { + @get:InputFiles + override val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() + + override fun copy(action: (CopySpec) -> Unit): WorkResult = project.copy(action) + override fun zipTree(file: File): FileTree = project.zipTree(file) } /** A Gradle 6+ compatible [BugsnagInstallJniLibsTask], which uses [FileSystemOperations]. */ @@ -115,10 +130,11 @@ internal open class BugsnagInstallJniLibsTaskGradle6Plus @Inject constructor( projectLayout: ProjectLayout, private val fsOperations: FileSystemOperations ) : BugsnagInstallJniLibsTask(objects, projectLayout) { + @get:InputFiles + override val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() + override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) - override fun zipTree(file: File): FileTree { - return project.zipTree(file) - } + override fun zipTree(file: File): FileTree = project.zipTree(file) } /** @@ -131,8 +147,9 @@ internal open class BugsnagInstallJniLibsTaskGradle66Plus @Inject constructor( private val fsOperations: FileSystemOperations, private val archiveOperations: ArchiveOperations ) : BugsnagInstallJniLibsTask(objects, projectLayout) { + @get:InputFiles + override val bugsnagArtifacts: ConfigurableFileCollection = objects.fileCollection() + override fun copy(action: (CopySpec) -> Unit): WorkResult = fsOperations.copy(action) - override fun zipTree(file: File): FileTree { - return archiveOperations.zipTree(file) - } + override fun zipTree(file: File): FileTree = archiveOperations.zipTree(file) } From 023aafdcd3576ec9f8201ca48af3c569e18a31c9 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:37:23 -0400 Subject: [PATCH 17/36] Borrow some kotlin gradle util --- .../BugsnagInstallJniLibsTask.kt | 27 +++++--- .../com.bugsnag.android.gradle/GradleUtil.kt | 62 +++++++++++++++++++ .../GradleVersions.kt | 11 ---- 3 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt delete mode 100644 src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 906f75c8..5fed7cdd 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -81,16 +81,23 @@ sealed class BugsnagInstallJniLibsTask( configurationAction: BugsnagInstallJniLibsTask.() -> Unit ): TaskProvider { val gradleVersion = project.gradle.versionNumber() - return if (gradleVersion >= GradleVersions.VERSION_6) { - if (gradleVersion >= GradleVersions.VERSION_6_6) { - project.tasks.register(name, BugsnagInstallJniLibsTaskGradle66Plus::class.java, configurationAction) - } else { - project.tasks.register(name, BugsnagInstallJniLibsTaskGradle6Plus::class.java, configurationAction) - } - } else if (gradleVersion >= GradleVersions.VERSION_5_3) { - project.tasks.register(name, BugsnagInstallJniLibsTask53Plus::class.java, configurationAction) - } else { - project.tasks.register(name, BugsnagInstallJniLibsTaskLegacy::class.java, configurationAction) + return when { + gradleVersion >= GradleVersions.VERSION_6 -> { + when { + gradleVersion >= GradleVersions.VERSION_6_6 -> { + project.tasks.register(name, configurationAction) + } + else -> { + project.tasks.register(name, configurationAction) + } + } + } + gradleVersion >= GradleVersions.VERSION_5_3 -> { + project.tasks.register(name, configurationAction) + } + else -> { + project.tasks.register(name, configurationAction) + } } } } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt new file mode 100644 index 00000000..912d85e2 --- /dev/null +++ b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt @@ -0,0 +1,62 @@ +package com.bugsnag.android.gradle + +import org.gradle.api.Task +import org.gradle.api.invocation.Gradle +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.TaskProvider +import org.gradle.util.VersionNumber + +internal object GradleVersions { + val VERSION_5_3: VersionNumber = VersionNumber.parse("5.3") + val VERSION_6: VersionNumber = VersionNumber.parse("6.0") + val VERSION_6_6: VersionNumber = VersionNumber.parse("6.6") +} + +internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleVersion) + +/* Borrowed helper functions from the Gradle Kotlin DSL. */ + +/** + * Creates a [Property] that holds values of the given type [T]. + * + * @see [ObjectFactory.property] + */ +internal inline fun ObjectFactory.property(): Property = + property(T::class.javaObjectType) + +/** + * Creates a [SetProperty] that holds values of the given type [T]. + * + * @see [ObjectFactory.setProperty] + */ +internal inline fun ObjectFactory.setProperty(): SetProperty = + setProperty(T::class.javaObjectType) + +/** + * Creates a [ListProperty] that holds values of the given type [T]. + * + * @see [ObjectFactory.listProperty] + */ +internal inline fun ObjectFactory.listProperty(): ListProperty = + listProperty(T::class.javaObjectType) + +/** + * Creates a [MapProperty] that holds values of the given key type [K] and value type [V]. + * + * @see [ObjectFactory.mapProperty] + */ +internal inline fun ObjectFactory.mapProperty(): MapProperty = + mapProperty(K::class.javaObjectType, V::class.javaObjectType) + +/** + * Defines and configure a new task, which will be created when it is required. + * + * @see [TaskContainer.register] + */ +internal inline fun TaskContainer.register(name: String, noinline configuration: T.() -> Unit): TaskProvider = + register(name, T::class.javaObjectType, configuration) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt deleted file mode 100644 index 7f1813db..00000000 --- a/src/main/kotlin/com.bugsnag.android.gradle/GradleVersions.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.bugsnag.android.gradle - -import org.gradle.api.invocation.Gradle -import org.gradle.util.VersionNumber - -internal object GradleVersions { - val VERSION_6 = VersionNumber.parse("6.0") - val VERSION_6_6 = VersionNumber.parse("6.6") -} - -internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleVersion) From 1c0f048ae4e2aa1a5d0ccd882285419412674f12 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:37:43 -0400 Subject: [PATCH 18/36] Use direct task logger in BugsnagManifestUuidTask --- .../BugsnagManifestUuidTask.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt index fe85d28a..a0657619 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt @@ -59,10 +59,10 @@ open class BugsnagManifestUuidTask @Inject constructor(objects: ObjectFactory) : fun updateManifest() { val manifestPath = getManifestPaths(project, variant, variantOutput) if (manifestPath == null) { - project.logger.warn("Bugsnag: Failed to find manifest at $manifestPath for $variantOutput") + logger.warn("Bugsnag: Failed to find manifest at $manifestPath for $variantOutput") } - project.logger.info("Bugsnag: Updating manifest with build UUID: $manifestPath") + logger.info("Bugsnag: Updating manifest with build UUID: $manifestPath") // read the manifest information and store it for subsequent tasks val manifestParser = AndroidManifestParser() @@ -98,16 +98,16 @@ open class BugsnagManifestUuidTask @Inject constructor(objects: ObjectFactory) : } val processManifest = variantOutput.processManifestProvider.get() if (getMergedManifest) { - directoryMerged = getManifestOutputDir(processManifest, project) + directoryMerged = getManifestOutputDir(processManifest) if (directoryMerged != null) { - addManifestPath(manifestPaths, directoryMerged, project.logger, variantOutput) + addManifestPath(manifestPaths, directoryMerged, logger, variantOutput) } } // Attempt to get the bundle manifest directory if required if (getBundleManifest) { directoryBundle = resolveBundleManifestOutputDirectory(processManifest) - addManifestPath(manifestPaths, directoryBundle, project.logger, variantOutput) + addManifestPath(manifestPaths, directoryBundle, logger, variantOutput) } require(manifestPaths.size == 1) { "Unexpected number of manifest paths.$manifestPaths" } return manifestPaths[0] @@ -116,14 +116,14 @@ open class BugsnagManifestUuidTask @Inject constructor(objects: ObjectFactory) : private fun addManifestPath(manifestPaths: MutableList, directory: File, logger: Logger, variantOutput: ApkVariantOutput) { val manifestFile = Paths.get(directory.toString(), variantOutput.dirName, "AndroidManifest.xml").toFile() if (manifestFile.exists()) { - logger.info("Bugsnag: Found manifest at ${manifestFile}") + logger.info("Bugsnag: Found manifest at $manifestFile") manifestPaths.add(manifestFile) } else { - logger.info("Bugsnag: Failed to find manifest at ${manifestFile}") + logger.info("Bugsnag: Failed to find manifest at $manifestFile") } } - private fun getManifestOutputDir(processManifest: ManifestProcessorTask, project: Project): File? { + private fun getManifestOutputDir(processManifest: ManifestProcessorTask): File? { try { val outputDir = processManifest.javaClass.getMethod("getManifestOutputDirectory").invoke(processManifest) if (outputDir is File) { @@ -138,7 +138,7 @@ open class BugsnagManifestUuidTask @Inject constructor(objects: ObjectFactory) : } } } catch (exc: Throwable) { - project.logger.warn("Bugsnag: failed to find manifestOutputDir", exc) + logger.warn("Bugsnag: failed to find manifestOutputDir", exc) } return null } From 26e3cdde0862366452dc05433066ae7fbe0fe216 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:43:38 -0400 Subject: [PATCH 19/36] Fix nullability check --- .../SharedObjectMappingFileProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/SharedObjectMappingFileProvider.kt b/src/main/kotlin/com.bugsnag.android.gradle/SharedObjectMappingFileProvider.kt index 5e284ebb..16288098 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/SharedObjectMappingFileProvider.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/SharedObjectMappingFileProvider.kt @@ -35,7 +35,7 @@ fun findSharedObjectMappingFiles(project: Project, private fun findSymbolPath(variantOutput: ApkVariantOutput?): File { val resources = variantOutput!!.processResourcesProvider.get() - return resources.property("textSymbolOutputFile") as File + return resources.property("textSymbolOutputFile") as? File ?: throw IllegalStateException("Could not find symbol path") } From bbc4d8dba1d657abdbec0b74359ac80af0e57bbd Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:44:00 -0400 Subject: [PATCH 20/36] Use kotlin extensions! --- .../AndroidManifestParser.kt | 5 +-- .../BugsnagManifestUuidTask.kt | 2 +- .../BugsnagPlugin.kt | 2 +- .../BugsnagPluginExtension.kt | 36 +++++++++---------- .../BugsnagReleasesTask.kt | 32 ++++++++--------- .../BugsnagUploadNdkTask.kt | 16 ++++----- .../BugsnagUploadProguardTask.kt | 12 +++---- .../com.bugsnag.android.gradle/GradleUtil.kt | 12 +++++++ 8 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt index 8306ba6b..868cf08c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt @@ -13,11 +13,10 @@ import java.io.IOException import java.io.PrintWriter import javax.xml.parsers.ParserConfigurationException -class AndroidManifestParser { +internal class AndroidManifestParser { private val namespace = Namespace("http://schemas.android.com/apk/res/android", "android") - @Throws(ParserConfigurationException::class, SAXException::class, IOException::class) fun readManifest(manifestPath: File, logger: Logger): AndroidManifestInfo { logger.debug("Bugsnag: Reading manifest at: $manifestPath") val root = XmlParser().parse(manifestPath) @@ -63,6 +62,8 @@ class AndroidManifestParser { |versionCode=$versionCode |versionName=$versionName |applicationId=$applicationId + |Manifest file = $manifestPath + |Manifest content=${manifestPath.readText()} """.trimMargin()) } return AndroidManifestInfo(apiKey, versionCode, buildUUID, versionName, applicationId) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt index a0657619..7afd87a9 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt @@ -27,7 +27,7 @@ abstract class BaseBugsnagManifestUuidTask(objects: ObjectFactory) : DefaultTask } @get:Input - val buildUuid: Property = objects.property(String::class.java) + val buildUuid: Property = objects.property() @get:OutputFile val manifestInfoProvider: RegularFileProperty = objects.fileProperty() diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 1d56778a..3eee9c68 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -324,7 +324,7 @@ class BugsnagPlugin : Plugin { output: ApkVariantOutput, prefix: String): Set { val variantName = output.name.split("-")[0].capitalize() - val assembleTask = variant.assembleProvider.getOrNull() + val assembleTask = variant.assembleProvider.orNull val taskNames = HashSet() taskNames.add(prefix) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt index 5011f806..cd518e4e 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt @@ -19,56 +19,56 @@ private val NULL_BOOLEAN: Boolean? = null // After Gradle 5.2, this can use service injection for injecting ObjectFactory open class BugsnagPluginExtension(objects: ObjectFactory) { - val sourceControl: SourceControl = objects.newInstance(SourceControl::class.java) + val sourceControl: SourceControl = objects.newInstance() - val enabled: Property = objects.property(Boolean::class.javaObjectType) + val enabled: Property = objects.property() .convention(true) - val uploadJvmMappings: Property = objects.property(Boolean::class.javaObjectType) + val uploadJvmMappings: Property = objects.property() .convention(true) - val uploadNdkMappings: Property = objects.property(Boolean::class.javaObjectType) + val uploadNdkMappings: Property = objects.property() .convention(NULL_BOOLEAN) - val reportBuilds: Property = objects.property(Boolean::class.javaObjectType) + val reportBuilds: Property = objects.property() .convention(true) - val uploadDebugBuildMappings: Property = objects.property(Boolean::class.javaObjectType) + val uploadDebugBuildMappings: Property = objects.property() .convention(false) - val autoUpdateBuildUuid: Property = objects.property(Boolean::class.javaObjectType) + val autoUpdateBuildUuid: Property = objects.property() .convention(true) - val endpoint: Property = objects.property(String::class.javaObjectType) + val endpoint: Property = objects.property() .convention("https://upload.bugsnag.com") - val releasesEndpoint = objects.property(String::class.javaObjectType) + val releasesEndpoint = objects.property() .convention("https://build.bugsnag.com") - val overwrite: Property = objects.property(Boolean::class.javaObjectType) + val overwrite: Property = objects.property() .convention(false) - val retryCount: Property = objects.property(Int::class.javaObjectType) + val retryCount: Property = objects.property() .convention(0) - val sharedObjectPaths: ListProperty = objects.listProperty(File::class.java) + val sharedObjectPaths: ListProperty = objects.listProperty() .convention(emptyList()) - val projectRoot: Property = objects.property(String::class.java).convention(NULL_STRING) + val projectRoot: Property = objects.property().convention(NULL_STRING) - val failOnUploadError: Property = objects.property(Boolean::class.javaObjectType) + val failOnUploadError: Property = objects.property() .convention(true) - val requestTimeoutMs: Property = objects.property(Long::class.javaObjectType) + val requestTimeoutMs: Property = objects.property() .convention(60000) // release API values - val builderName: Property = objects.property(String::class.java).convention(NULL_STRING) + val builderName: Property = objects.property().convention(NULL_STRING) - val metadata: MapProperty = objects.mapProperty(String::class.java, String::class.java) + val metadata: MapProperty = objects.mapProperty() .convention(emptyMap()) - val objdumpPaths: MapProperty = objects.mapProperty(String::class.java, String::class.java) + val objdumpPaths: MapProperty = objects.mapProperty() .convention(emptyMap()) // exposes sourceControl as a nested object on the extension, diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 0bc73f0c..bae41e8a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -52,7 +52,7 @@ sealed class BugsnagReleasesTask( } @get:Internal - internal val uploadRequestClient: Property = objects.property(UploadRequestClient::class.java) + internal val uploadRequestClient: Property = objects.property() @get:PathSensitive(NONE) @get:InputFile @@ -72,60 +72,60 @@ sealed class BugsnagReleasesTask( @get:PathSensitive(NONE) @get:InputFiles @get:Optional - val ndkMappingFileProperty: Property = objects.property(FileCollection::class.java) + val ndkMappingFileProperty: Property = objects.property() @get:Input - val retryCount: Property = objects.property(Int::class.javaObjectType) + val retryCount: Property = objects.property() @get:Input - val timeoutMillis: Property = objects.property(Long::class.javaObjectType) + val timeoutMillis: Property = objects.property() @get:Input - val releasesEndpoint: Property = objects.property(String::class.java) + val releasesEndpoint: Property = objects.property() @get:Optional @get:Input - val builderName: Property = objects.property(String::class.java) + val builderName: Property = objects.property() @get:Optional @get:Input - val metadata: MapProperty = objects.mapProperty(String::class.java, String::class.java) + val metadata: MapProperty = objects.mapProperty() @get:Optional @get:Input - val sourceControlProvider: Property = objects.property(String::class.java) + val sourceControlProvider: Property = objects.property() @get:Optional @get:Input - val sourceControlRepository: Property = objects.property(String::class.java) + val sourceControlRepository: Property = objects.property() @get:Optional @get:Input - val sourceControlRevision: Property = objects.property(String::class.java) + val sourceControlRevision: Property = objects.property() @get:Input @get:Optional - val osArch: Property = objects.property(String::class.java) + val osArch: Property = objects.property() @get:Input @get:Optional - val osName: Property = objects.property(String::class.java) + val osName: Property = objects.property() @get:Input @get:Optional - val osVersion: Property = objects.property(String::class.java) + val osVersion: Property = objects.property() @get:Input @get:Optional - val javaVersion: Property = objects.property(String::class.java) + val javaVersion: Property = objects.property() @get:Input @get:Optional - val gradleVersion: Property = objects.property(String::class.java) + val gradleVersion: Property = objects.property() @get:Input @get:Optional - val gitVersion: Property = objects.property(String::class.java) + val gitVersion: Property = objects.property() internal abstract fun exec(action: (ExecSpec) -> Unit): ExecResult diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index af33f7b4..51662350 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -56,10 +56,10 @@ open class BugsnagUploadNdkTask @Inject constructor( } @get:Internal - internal val uploadRequestClient: Property = objects.property(UploadRequestClient::class.java) + internal val uploadRequestClient: Property = objects.property() @Input - val projectRoot: Property = objects.property(String::class.javaObjectType) + val projectRoot: Property = objects.property() @get:InputFiles val searchDirectories: Property = objects.property(FileCollection::class.java) @@ -79,22 +79,22 @@ open class BugsnagUploadNdkTask @Inject constructor( .convention(projectLayout.buildDirectory.dir("intermediates/bugsnag")) @get:Input - override val failOnUploadError: Property = objects.property(Boolean::class.javaObjectType) + override val failOnUploadError: Property = objects.property() @get:Input - override val overwrite: Property = objects.property(Boolean::class.javaObjectType) + override val overwrite: Property = objects.property() @get:Input - override val endpoint: Property = objects.property(String::class.javaObjectType) + override val endpoint: Property = objects.property() @get:Input - override val retryCount: Property = objects.property(Int::class.javaObjectType) + override val retryCount: Property = objects.property() @get:Input - override val timeoutMillis: Property = objects.property(Long::class.javaObjectType) + override val timeoutMillis: Property = objects.property() @get:Input - val objDumpPaths: MapProperty = objects.mapProperty(String::class.java, String::class.java) + val objDumpPaths: MapProperty = objects.mapProperty() @TaskAction fun upload() { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt index 2361f68a..0268158a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt @@ -37,7 +37,7 @@ open class BugsnagUploadProguardTask @Inject constructor( } @get:Internal - internal val uploadRequestClient: Property = objects.property(UploadRequestClient::class.java) + internal val uploadRequestClient: Property = objects.property() @get:PathSensitive(NONE) @get:InputFile @@ -51,19 +51,19 @@ open class BugsnagUploadProguardTask @Inject constructor( val requestOutputFile: RegularFileProperty = objects.fileProperty() @get:Input - override val failOnUploadError: Property = objects.property(Boolean::class.javaObjectType) + override val failOnUploadError: Property = objects.property() @get:Input - override val overwrite: Property = objects.property(Boolean::class.javaObjectType) + override val overwrite: Property = objects.property() @get:Input - override val endpoint: Property = objects.property(String::class.javaObjectType) + override val endpoint: Property = objects.property() @get:Input - override val retryCount: Property = objects.property(Int::class.javaObjectType) + override val retryCount: Property = objects.property() @get:Input - override val timeoutMillis: Property = objects.property(Long::class.javaObjectType) + override val timeoutMillis: Property = objects.property() @TaskAction fun upload() { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt index 912d85e2..c9bbc41a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt @@ -21,6 +21,18 @@ internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleV /* Borrowed helper functions from the Gradle Kotlin DSL. */ +/** + * Create a new instance of [T], using [parameters] as the construction parameters. + * + * @param T The type of object to create + * @param parameters The construction parameters + * @return the created named object + * + * @see [ObjectFactory.newInstance] + */ +inline fun ObjectFactory.newInstance(vararg parameters: Any): T = + newInstance(T::class.javaObjectType, *parameters) + /** * Creates a [Property] that holds values of the given type [T]. * From 9e606ef35d0176fe898225a2a3b553fb97e1667d Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 8 Aug 2020 23:53:55 -0400 Subject: [PATCH 21/36] Backport configurablefilecollection use in BugsnagUploadNdkTask --- .../BugsnagPlugin.kt | 26 ++++++----- .../BugsnagUploadNdkTask.kt | 45 ++++++++++++++++--- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 3eee9c68..bf29bd94 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -216,23 +216,25 @@ class BugsnagPlugin : Plugin { } } - private fun registerSharedObjectUploadTask(project: Project, - variant: ApkVariant, - output: ApkVariantOutput, - bugsnag: BugsnagPluginExtension): TaskProvider { + private fun registerSharedObjectUploadTask( + project: Project, + variant: ApkVariant, + output: ApkVariantOutput, + bugsnag: BugsnagPluginExtension + ): TaskProvider { // Create a Bugsnag task to upload NDK mapping file(s) val outputName = taskNameForOutput(output) val taskName = "uploadBugsnagNdk${outputName}Mapping" val path = "intermediates/bugsnag/requests/ndkFor${outputName}.json" val requestOutputFile = project.layout.buildDirectory.file(path) - return project.tasks.register(taskName, BugsnagUploadNdkTask::class.java) { - it.requestOutputFile.set(requestOutputFile) - it.projectRoot.set(bugsnag.projectRoot.getOrElse(project.projectDir.toString())) - it.searchDirectories.set(getSearchDirectories(project, variant)) - it.variantOutput = output - it.objDumpPaths.set(bugsnag.objdumpPaths) - addTaskToExecutionGraph(it, variant, output, project, bugsnag, true) - it.configureWith(bugsnag) + return BugsnagUploadNdkTask.register(project, taskName) { + this.requestOutputFile.set(requestOutputFile) + projectRoot.set(bugsnag.projectRoot.getOrElse(project.projectDir.toString())) + searchDirectories.from(getSearchDirectories(project, variant)) + variantOutput = output + objDumpPaths.set(bugsnag.objdumpPaths) + addTaskToExecutionGraph(this, variant, output, project, bugsnag, true) + configureWith(bugsnag) } } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 51662350..52828fba 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -11,6 +11,7 @@ import okio.source import org.apache.tools.ant.taskdefs.condition.Os import org.gradle.api.DefaultTask import org.gradle.api.Project +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.file.ProjectLayout @@ -27,6 +28,7 @@ import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity.NONE import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.TaskProvider import java.io.File import java.io.InputStream import java.io.Reader @@ -45,7 +47,7 @@ import javax.inject.Inject * it is usually safe to have this be the absolute last task executed during * a build. */ -open class BugsnagUploadNdkTask @Inject constructor( +sealed class BugsnagUploadNdkTask( objects: ObjectFactory, projectLayout: ProjectLayout ) : DefaultTask(), AndroidManifestInfoReceiver, BugsnagFileUploadTask { @@ -61,9 +63,6 @@ open class BugsnagUploadNdkTask @Inject constructor( @Input val projectRoot: Property = objects.property() - @get:InputFiles - val searchDirectories: Property = objects.property(FileCollection::class.java) - @get:PathSensitive(NONE) @get:InputFile override val manifestInfoFile: RegularFileProperty = objects.fileProperty() @@ -96,10 +95,12 @@ open class BugsnagUploadNdkTask @Inject constructor( @get:Input val objDumpPaths: MapProperty = objects.mapProperty() + abstract val searchDirectories: ConfigurableFileCollection + @TaskAction fun upload() { logger.lifecycle("Starting ndk upload") - val searchDirs = searchDirectories.get().files.toList() + val searchDirs = searchDirectories.files.toList() val files = findSharedObjectMappingFiles(project, variantOutput, searchDirs) logger.lifecycle("Processing shared object files") processFiles(files) @@ -271,5 +272,39 @@ open class BugsnagUploadNdkTask @Inject constructor( else -> null } } + + internal fun register( + project: Project, + name: String, + configurationAction: BugsnagUploadNdkTask.() -> Unit + ): TaskProvider { + val gradleVersion = project.gradle.versionNumber() + return when { + gradleVersion >= GradleVersions.VERSION_5_3 -> { + project.tasks.register(name, configurationAction) + } + else -> { + project.tasks.register(name, configurationAction) + } + } + } } } + +/** A legacy [BugsnagUploadNdkTask] that uses [ProjectLayout.configurableFiles]. */ +internal open class BugsnagUploadNdkTaskLegacy @Inject constructor( + objects: ObjectFactory, + projectLayout: ProjectLayout +) : BugsnagUploadNdkTask(objects, projectLayout) { + @Suppress("DEPRECATION") // Here for backward compat + @get:InputFiles + override val searchDirectories: ConfigurableFileCollection = projectLayout.configurableFiles() +} + +internal open class BugsnagUploadNdkTask53Plus @Inject constructor( + objects: ObjectFactory, + projectLayout: ProjectLayout +) : BugsnagUploadNdkTask(objects, projectLayout) { + @get:InputFiles + override val searchDirectories: ConfigurableFileCollection = objects.fileCollection() +} From ba7eed8d1d08ae75aac5db383a3fd608a63cd7f4 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 00:03:02 -0400 Subject: [PATCH 22/36] Fix missing inputs --- .../com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt | 1 + .../kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index 5fed7cdd..f57500fa 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -32,6 +32,7 @@ sealed class BugsnagInstallJniLibsTask( val buildDirDestination: DirectoryProperty = objects.directoryProperty() .convention(projectLayout.buildDirectory.dir("intermediates/bugsnag-libs")) + @get:InputFiles abstract val bugsnagArtifacts: ConfigurableFileCollection internal abstract fun copy(action: (CopySpec) -> Unit): WorkResult diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 52828fba..2a06b18c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -95,6 +95,7 @@ sealed class BugsnagUploadNdkTask( @get:Input val objDumpPaths: MapProperty = objects.mapProperty() + @get:InputFiles abstract val searchDirectories: ConfigurableFileCollection @TaskAction From a42ea8db1340a26adb0af9c44d76724b67167d8b Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 00:27:52 -0400 Subject: [PATCH 23/36] Backport ConfigurableFileCollection in BugsnagReleasesTask --- .../BugsnagPlugin.kt | 2 +- .../BugsnagReleasesTask.kt | 52 ++++++++++++++++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index bf29bd94..7c75c683 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -157,7 +157,7 @@ class BugsnagPlugin : Plugin { symbolFileTask?.get()?.let { task -> val ndkSearchDirs = symbolFileTask.get().searchDirectories - releasesTask.get().ndkMappingFileProperty.set(ndkSearchDirs) + releasesTask.get().ndkMappingFileProperty.from(ndkSearchDirs) task.uploadRequestClient.set(ndkUploadClient) } releasesTask.get().uploadRequestClient.set(releasesUploadClient) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index bae41e8a..321711eb 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -4,7 +4,8 @@ import com.squareup.moshi.JsonClass import okhttp3.OkHttpClient import org.gradle.api.DefaultTask import org.gradle.api.Project -import org.gradle.api.file.FileCollection +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty import org.gradle.api.logging.LogLevel import org.gradle.api.model.ObjectFactory @@ -13,8 +14,8 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Internal import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive @@ -72,7 +73,7 @@ sealed class BugsnagReleasesTask( @get:PathSensitive(NONE) @get:InputFiles @get:Optional - val ndkMappingFileProperty: Property = objects.property() + abstract val ndkMappingFileProperty: ConfigurableFileCollection @get:Input val retryCount: Property = objects.property() @@ -337,20 +338,50 @@ sealed class BugsnagReleasesTask( name: String, configurationAction: BugsnagReleasesTask.() -> Unit ): TaskProvider { - return if (project.gradle.versionNumber() >= GradleVersions.VERSION_6) { - project.tasks.register(name, BugsnagReleasesTaskGradle6Plus::class.java, configurationAction) - } else { - project.tasks.register(name, BugsnagReleasesTaskLegacy::class.java, configurationAction) + return when { + project.gradle.versionNumber() >= GradleVersions.VERSION_6 -> { + project.tasks.register(name, configurationAction) + } + project.gradle.versionNumber() >= GradleVersions.VERSION_5_3 -> { + project.tasks.register(name, configurationAction) + } + else -> { + project.tasks.register(name, configurationAction) + } } } } } -/** Legacy [BugsnagReleasesTask] task that requires using [getProject]. */ +/** + * Legacy [BugsnagReleasesTask] task that requires using [getProject] and + * [ProjectLayout.configurableFiles]. + */ internal open class BugsnagReleasesTaskLegacy @Inject constructor( + objects: ObjectFactory, + providerFactory: ProviderFactory, + projectLayout: ProjectLayout +) : BugsnagReleasesTask(objects, providerFactory) { + + @Suppress("DEPRECATION") // Here for backward compat + @get:PathSensitive(NONE) + @get:InputFiles + @get:Optional + override val ndkMappingFileProperty: ConfigurableFileCollection = projectLayout.configurableFiles() + + override fun exec(action: (ExecSpec) -> Unit): ExecResult = project.exec(action) +} + +/** Legacy [BugsnagReleasesTask] task that requires using [getProject]. */ +internal open class BugsnagReleasesTaskGradle53Plus @Inject constructor( objects: ObjectFactory, providerFactory: ProviderFactory ) : BugsnagReleasesTask(objects, providerFactory) { + @get:PathSensitive(NONE) + @get:InputFiles + @get:Optional + override val ndkMappingFileProperty: ConfigurableFileCollection = objects.fileCollection() + override fun exec(action: (ExecSpec) -> Unit): ExecResult { return project.exec(action) } @@ -365,6 +396,11 @@ internal open class BugsnagReleasesTaskGradle6Plus @Inject constructor( providerFactory: ProviderFactory, private val execOperations: ExecOperations ) : BugsnagReleasesTask(objects, providerFactory) { + @get:PathSensitive(NONE) + @get:InputFiles + @get:Optional + override val ndkMappingFileProperty: ConfigurableFileCollection = objects.fileCollection() + override fun exec(action: (ExecSpec) -> Unit): ExecResult { return execOperations.exec(action) } From 714a6e91f9fbdefefe9494fb3b3d19e492e95a8e Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 00:59:13 -0400 Subject: [PATCH 24/36] Detekt fixes --- .../BugsnagManifestUuidTask.kt | 10 ++++------ .../kotlin/com.bugsnag.android.gradle/GradleUtil.kt | 8 ++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt index 7afd87a9..64389746 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt @@ -124,23 +124,21 @@ open class BugsnagManifestUuidTask @Inject constructor(objects: ObjectFactory) : } private fun getManifestOutputDir(processManifest: ManifestProcessorTask): File? { - try { + return try { val outputDir = processManifest.javaClass.getMethod("getManifestOutputDirectory").invoke(processManifest) if (outputDir is File) { - return outputDir + outputDir } else { // gradle 4.7 introduced a provider API for lazy evaluation of properties, // AGP subsequently changed the API from File to Provider // see https://docs.gradle.org/4.7/userguide/lazy_configuration.html @Suppress("UNCHECKED_CAST") val dir = (outputDir as Provider).orNull - if (dir != null) { - return dir.asFile - } + dir?.asFile } } catch (exc: Throwable) { logger.warn("Bugsnag: failed to find manifestOutputDir", exc) + null } - return null } private fun resolveBundleManifestOutputDirectory(processManifest: ManifestProcessorTask): File { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt index c9bbc41a..bca73d9c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt @@ -1,3 +1,4 @@ +@file:Suppress("MatchingDeclarationName") // This file contains multiple top-level members package com.bugsnag.android.gradle import org.gradle.api.Task @@ -30,6 +31,7 @@ internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleV * * @see [ObjectFactory.newInstance] */ +@Suppress("SpreadOperator") inline fun ObjectFactory.newInstance(vararg parameters: Any): T = newInstance(T::class.javaObjectType, *parameters) @@ -70,5 +72,7 @@ internal inline fun ObjectFactory.mapProperty * * @see [TaskContainer.register] */ -internal inline fun TaskContainer.register(name: String, noinline configuration: T.() -> Unit): TaskProvider = - register(name, T::class.javaObjectType, configuration) +internal inline fun TaskContainer.register( + name: String, + noinline configuration: T.() -> Unit +): TaskProvider = register(name, T::class.javaObjectType, configuration) From 5046dd7d789435fc0caa93ed3593770c596f0fbf Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 02:07:58 -0400 Subject: [PATCH 25/36] Use a BuildService for OkHttpClient reuse --- .../BugsnagFileUploadTask.kt | 2 + .../BugsnagMultiPartUploadRequest.kt | 14 +---- .../BugsnagPlugin.kt | 61 ++++++++++++++----- .../BugsnagUploadNdkTask.kt | 4 ++ .../BugsnagUploadProguardTask.kt | 4 ++ .../com.bugsnag.android.gradle/GradleUtil.kt | 1 + .../internal/BugsnagHttpClientHelper.kt | 45 ++++++++++++++ 7 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 src/main/kotlin/com/bugsnag/android/gradle/internal/BugsnagHttpClientHelper.kt diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagFileUploadTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagFileUploadTask.kt index 8b9aa63c..04baf550 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagFileUploadTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagFileUploadTask.kt @@ -1,5 +1,6 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import org.gradle.api.provider.Property interface BugsnagFileUploadTask { @@ -8,6 +9,7 @@ interface BugsnagFileUploadTask { val endpoint: Property val retryCount: Property val timeoutMillis: Property + val httpClientHelper: Property fun configureWith(bugsnag: BugsnagPluginExtension) { failOnUploadError.set(bugsnag.failOnUploadError) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagMultiPartUploadRequest.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagMultiPartUploadRequest.kt index e314dbe0..a7091c2a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagMultiPartUploadRequest.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagMultiPartUploadRequest.kt @@ -16,7 +16,6 @@ import retrofit2.http.POST import retrofit2.http.PartMap import retrofit2.http.Url import java.io.File -import java.time.Duration /** * Task to upload ProGuard mapping files to Bugsnag. @@ -37,10 +36,10 @@ class BugsnagMultiPartUploadRequest( private val overwrite: Boolean, private val endpoint: String, private val retryCount: Int, - timeoutDuration: Duration + okHttpClient: OkHttpClient ) { - private val bugsnagService = createService(timeoutDuration) + private val bugsnagService = createService(okHttpClient) fun uploadMultipartEntity( parts: MutableMap, @@ -126,17 +125,10 @@ class BugsnagMultiPartUploadRequest( overwrite = task.overwrite.get(), endpoint = task.endpoint.get(), retryCount = task.retryCount.get(), - timeoutDuration = Duration.ofMillis(task.timeoutMillis.get()) + okHttpClient = task.httpClientHelper.get().okHttpClient ) } - private fun createService(timeoutDuration: Duration): BugsnagService { - return createService(OkHttpClient.Builder() - .connectTimeout(timeoutDuration) - .callTimeout(timeoutDuration) - .build()) - } - internal fun createService(client: OkHttpClient): BugsnagService { return Retrofit.Builder() .baseUrl("https://upload.bugsnag.com") // Not actually used diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 7c75c683..a67b7062 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -8,6 +8,9 @@ import com.android.build.gradle.api.ApkVariantOutput import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.tasks.ExternalNativeBuildTask import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBugsnagArtifacts +import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.BuildServiceBugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.LegacyBugsnagHttpClientHelper import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project @@ -56,6 +59,17 @@ class BugsnagPlugin : Plugin { return@withPlugin } + val httpClientHelperProvider: Provider = if (project.gradle.versionNumber() >= GradleVersions.VERSION_6_1) { + project.gradle.sharedServices.registerIfAbsent("bugsnagHttpClientHelper", + BuildServiceBugsnagHttpClientHelper::class.java + ) { spec -> + // Provide some parameters + spec.parameters.timeoutMillis.set(bugsnag.requestTimeoutMs) + } + } else { + project.provider { LegacyBugsnagHttpClientHelper(bugsnag.requestTimeoutMs) } + } + val android = project.extensions.getByType(AppExtension::class.java) if (BugsnagManifestUuidTaskV2.isApplicable()) { check(android is CommonExtension<*, *, *, *, *, *, *, *>) @@ -82,7 +96,7 @@ class BugsnagPlugin : Plugin { project.afterEvaluate { android.applicationVariants.configureEach { variant -> - registerBugsnagTasksForVariant(project, variant, bugsnag) + registerBugsnagTasksForVariant(project, variant, bugsnag, httpClientHelperProvider) } registerNdkLibInstallTask(project, bugsnag, android) } @@ -121,7 +135,8 @@ class BugsnagPlugin : Plugin { private fun registerBugsnagTasksForVariant( project: Project, variant: ApkVariant, - bugsnag: BugsnagPluginExtension + bugsnag: BugsnagPluginExtension, + httpClientHelperProvider: Provider ) { variant.outputs.configureEach { val output = it as ApkVariantOutput @@ -136,11 +151,23 @@ class BugsnagPlugin : Plugin { // register bugsnag tasks val manifestInfoFile = registerManifestUuidTask(project, variant, output) val proguardTask = when { - jvmMinificationEnabled -> registerProguardUploadTask(project, variant, output, bugsnag) + jvmMinificationEnabled -> registerProguardUploadTask( + project, + variant, + output, + bugsnag, + httpClientHelperProvider + ) else -> null } val symbolFileTask = when { - ndkEnabled -> registerSharedObjectUploadTask(project, variant, output, bugsnag) + ndkEnabled -> registerSharedObjectUploadTask( + project, + variant, + output, + bugsnag, + httpClientHelperProvider + ) else -> null } val releasesTask = registerReleasesUploadTask(project, variant, output, bugsnag) @@ -201,18 +228,22 @@ class BugsnagPlugin : Plugin { /** * Creates a bugsnag task to upload proguard mapping file */ - private fun registerProguardUploadTask(project: Project, - variant: ApkVariant, - output: ApkVariantOutput, - bugsnag: BugsnagPluginExtension): TaskProvider { + private fun registerProguardUploadTask( + project: Project, + variant: ApkVariant, + output: ApkVariantOutput, + bugsnag: BugsnagPluginExtension, + httpClientHelperProvider: Provider + ): TaskProvider { val outputName = taskNameForOutput(output) val taskName = "uploadBugsnag${outputName}Mapping" val path = "intermediates/bugsnag/requests/proguardFor${outputName}.json" - val requestOutputFile = project.layout.buildDirectory.file(path) - return project.tasks.register(taskName, BugsnagUploadProguardTask::class.java) { - it.requestOutputFile.set(requestOutputFile) - addTaskToExecutionGraph(it, variant, output, project, bugsnag, bugsnag.uploadJvmMappings.get()) - it.configureWith(bugsnag) + val requestOutputFileProvider = project.layout.buildDirectory.file(path) + return project.tasks.register(taskName) { + requestOutputFile.set(requestOutputFileProvider) + httpClientHelper.set(httpClientHelperProvider) + addTaskToExecutionGraph(this, variant, output, project, bugsnag, bugsnag.uploadJvmMappings.get()) + configureWith(bugsnag) } } @@ -220,7 +251,8 @@ class BugsnagPlugin : Plugin { project: Project, variant: ApkVariant, output: ApkVariantOutput, - bugsnag: BugsnagPluginExtension + bugsnag: BugsnagPluginExtension, + httpClientHelperProvider: Provider ): TaskProvider { // Create a Bugsnag task to upload NDK mapping file(s) val outputName = taskNameForOutput(output) @@ -233,6 +265,7 @@ class BugsnagPlugin : Plugin { searchDirectories.from(getSearchDirectories(project, variant)) variantOutput = output objDumpPaths.set(bugsnag.objdumpPaths) + httpClientHelper.set(httpClientHelperProvider) addTaskToExecutionGraph(this, variant, output, project, bugsnag, true) configureWith(bugsnag) } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 2a06b18c..16d23f43 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -3,6 +3,7 @@ package com.bugsnag.android.gradle import com.android.build.gradle.AppExtension import com.android.build.gradle.api.ApkVariantOutput import com.bugsnag.android.gradle.Abi.Companion.findByName +import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import okhttp3.RequestBody import okio.buffer import okio.gzip @@ -60,6 +61,9 @@ sealed class BugsnagUploadNdkTask( @get:Internal internal val uploadRequestClient: Property = objects.property() + @get:Internal + override val httpClientHelper: Property = objects.property() + @Input val projectRoot: Property = objects.property() diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt index 0268158a..c950abb4 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt @@ -1,5 +1,6 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import okhttp3.RequestBody import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty @@ -39,6 +40,9 @@ open class BugsnagUploadProguardTask @Inject constructor( @get:Internal internal val uploadRequestClient: Property = objects.property() + @get:Internal + override val httpClientHelper: Property = objects.property() + @get:PathSensitive(NONE) @get:InputFile val mappingFileProperty: RegularFileProperty = objects.fileProperty() diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt index bca73d9c..7bf7d995 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt @@ -15,6 +15,7 @@ import org.gradle.util.VersionNumber internal object GradleVersions { val VERSION_5_3: VersionNumber = VersionNumber.parse("5.3") val VERSION_6: VersionNumber = VersionNumber.parse("6.0") + val VERSION_6_1: VersionNumber = VersionNumber.parse("6.1") val VERSION_6_6: VersionNumber = VersionNumber.parse("6.6") } diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/BugsnagHttpClientHelper.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/BugsnagHttpClientHelper.kt new file mode 100644 index 00000000..323ad3f9 --- /dev/null +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/BugsnagHttpClientHelper.kt @@ -0,0 +1,45 @@ +package com.bugsnag.android.gradle.internal + +import com.bugsnag.android.gradle.internal.BuildServiceBugsnagHttpClientHelper.Params +import okhttp3.OkHttpClient +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters +import java.time.Duration + +/** A simple API for providing a shared [OkHttpClient] instance for shared use in upload tasks. */ +interface BugsnagHttpClientHelper : AutoCloseable { + val okHttpClient: OkHttpClient + + override fun close() { + okHttpClient.dispatcher.executorService.shutdown() + okHttpClient.connectionPool.evictAll() + okHttpClient.cache?.close() + } +} + +/** A [BuildService] implementation of [BugsnagHttpClientHelper]. */ +abstract class BuildServiceBugsnagHttpClientHelper + : BuildService, BugsnagHttpClientHelper { + + interface Params : BuildServiceParameters { + val timeoutMillis: Property + } + + override val okHttpClient: OkHttpClient by lazy { newClient(parameters.timeoutMillis.get()) } +} + +/** A simple instance-based [BugsnagHttpClientHelper] for use on Gradle <6.1. */ +class LegacyBugsnagHttpClientHelper(timeoutMillis: Provider) : BugsnagHttpClientHelper { + override val okHttpClient: OkHttpClient by lazy { newClient(timeoutMillis.get()) } +} + +private fun newClient(timeoutMillis: Long): OkHttpClient { + val timeoutDuration = Duration.ofMillis(timeoutMillis) + return OkHttpClient.Builder() + .connectTimeout(timeoutDuration) + .callTimeout(timeoutDuration) + .build() +} + From 4eec71c93152b9530fef4ec7a843e6032e8379eb Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 02:23:04 -0400 Subject: [PATCH 26/36] Make UploadRequestClient use a build service on gradle 6.1+ --- .../BugsnagPlugin.kt | 31 ++++++--- .../BugsnagReleasesTask.kt | 1 + .../BugsnagUploadNdkTask.kt | 2 +- .../BugsnagUploadProguardTask.kt | 1 + .../UploadRequestClient.kt | 33 --------- .../gradle/internal/UploadRequestClient.kt | 67 +++++++++++++++++++ .../android/gradle/UploadRequestClientTest.kt | 7 +- 7 files changed, 96 insertions(+), 46 deletions(-) delete mode 100644 src/main/kotlin/com.bugsnag.android.gradle/UploadRequestClient.kt create mode 100644 src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index a67b7062..3ada40ca 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -11,6 +11,8 @@ import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBug import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import com.bugsnag.android.gradle.internal.BuildServiceBugsnagHttpClientHelper import com.bugsnag.android.gradle.internal.LegacyBugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.UploadRequestClient +import com.bugsnag.android.gradle.internal.newUploadRequestClientProvider import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project @@ -43,10 +45,6 @@ class BugsnagPlugin : Plugin { const val BUNDLE_TASK = "bundle" } - private val releasesUploadClient = UploadRequestClient() - private val proguardUploadClient = UploadRequestClient() - private val ndkUploadClient = UploadRequestClient() - override fun apply(project: Project) { // After Gradle 5.2, this can use service injection for injecting ObjectFactory val bugsnag = project.extensions.create( @@ -70,6 +68,10 @@ class BugsnagPlugin : Plugin { project.provider { LegacyBugsnagHttpClientHelper(bugsnag.requestTimeoutMs) } } + val releasesUploadClientProvider = newUploadRequestClientProvider(project, "releases") + val proguardUploadClientProvider = newUploadRequestClientProvider(project, "proguard") + val ndkUploadClientProvider = newUploadRequestClientProvider(project, "ndk") + val android = project.extensions.getByType(AppExtension::class.java) if (BugsnagManifestUuidTaskV2.isApplicable()) { check(android is CommonExtension<*, *, *, *, *, *, *, *>) @@ -96,7 +98,15 @@ class BugsnagPlugin : Plugin { project.afterEvaluate { android.applicationVariants.configureEach { variant -> - registerBugsnagTasksForVariant(project, variant, bugsnag, httpClientHelperProvider) + registerBugsnagTasksForVariant( + project, + variant, + bugsnag, + httpClientHelperProvider, + releasesUploadClientProvider, + proguardUploadClientProvider, + ndkUploadClientProvider + ) } registerNdkLibInstallTask(project, bugsnag, android) } @@ -136,7 +146,10 @@ class BugsnagPlugin : Plugin { project: Project, variant: ApkVariant, bugsnag: BugsnagPluginExtension, - httpClientHelperProvider: Provider + httpClientHelperProvider: Provider, + releasesUploadClientProvider: Provider, + proguardUploadClientProvider: Provider, + ndkUploadClientProvider: Provider ) { variant.outputs.configureEach { val output = it as ApkVariantOutput @@ -179,15 +192,15 @@ class BugsnagPlugin : Plugin { val mappingFileProvider = createMappingFileProvider(project, variant, output) task.mappingFileProperty.set(mappingFileProvider) releasesTask.get().jvmMappingFileProperty.set(mappingFileProvider) - task.uploadRequestClient.set(proguardUploadClient) + task.uploadRequestClient.set(proguardUploadClientProvider) } symbolFileTask?.get()?.let { task -> val ndkSearchDirs = symbolFileTask.get().searchDirectories releasesTask.get().ndkMappingFileProperty.from(ndkSearchDirs) - task.uploadRequestClient.set(ndkUploadClient) + task.uploadRequestClient.set(ndkUploadClientProvider) } - releasesTask.get().uploadRequestClient.set(releasesUploadClient) + releasesTask.get().uploadRequestClient.set(releasesUploadClientProvider) releasesTask.get().manifestInfoFile.set(manifestInfoFile) symbolFileTask?.get()?.manifestInfoFile?.set(manifestInfoFile) releasesTask.get().manifestInfoFile.set(manifestInfoFile) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 321711eb..72f167eb 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -1,5 +1,6 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.UploadRequestClient import com.squareup.moshi.JsonClass import okhttp3.OkHttpClient import org.gradle.api.DefaultTask diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 16d23f43..4d4928e5 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -4,6 +4,7 @@ import com.android.build.gradle.AppExtension import com.android.build.gradle.api.ApkVariantOutput import com.bugsnag.android.gradle.Abi.Companion.findByName import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.UploadRequestClient import okhttp3.RequestBody import okio.buffer import okio.gzip @@ -14,7 +15,6 @@ import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.FileCollection import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt index c950abb4..7c4438a5 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt @@ -1,6 +1,7 @@ package com.bugsnag.android.gradle import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.UploadRequestClient import okhttp3.RequestBody import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty diff --git a/src/main/kotlin/com.bugsnag.android.gradle/UploadRequestClient.kt b/src/main/kotlin/com.bugsnag.android.gradle/UploadRequestClient.kt deleted file mode 100644 index 342e9091..00000000 --- a/src/main/kotlin/com.bugsnag.android.gradle/UploadRequestClient.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.bugsnag.android.gradle - -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.FutureTask - -class UploadRequestClient { - - private val requestMap = ConcurrentHashMap>() - - /** - * Executes request with automatic de-duplication of similar requests. - * - * If the version information and payload match another request that - * has already been enqueued, the response value of the existing request - * will be returned. If no existing requests match, a new request will - * be enqueued and executed. - * - * Equality is measured by the [AndroidManifestInfo] (excluding buildUuid) - * and the request payload. - */ - fun makeRequestIfNeeded(manifestInfo: AndroidManifestInfo, - payload: String, - request: () -> String): String { - val versionInfoHash = manifestInfo.hashCode() - val requestIdHash = versionInfoHash + payload.hashCode() - - val future = requestMap.getOrPut(requestIdHash.toString()) { - FutureTask { request() } - } - future.run() - return future.get() - } -} diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt new file mode 100644 index 00000000..e5f6b0ee --- /dev/null +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -0,0 +1,67 @@ +package com.bugsnag.android.gradle.internal + +import com.bugsnag.android.gradle.AndroidManifestInfo +import com.bugsnag.android.gradle.GradleVersions +import com.bugsnag.android.gradle.versionNumber +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters +import org.gradle.tooling.internal.protocol.BuildParameters +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.FutureTask + +sealed class UploadRequestClient : AutoCloseable { + + private val requestMap = ConcurrentHashMap>() + + /** + * Executes request with automatic de-duplication of similar requests. + * + * If the version information and payload match another request that + * has already been enqueued, the response value of the existing request + * will be returned. If no existing requests match, a new request will + * be enqueued and executed. + * + * Equality is measured by the [AndroidManifestInfo] (excluding buildUuid) + * and the request payload. + */ + fun makeRequestIfNeeded( + manifestInfo: AndroidManifestInfo, + payload: String, + request: () -> String + ): String { + val versionInfoHash = manifestInfo.hashCode() + val requestIdHash = versionInfoHash + payload.hashCode() + + val future = requestMap.getOrPut(requestIdHash.toString()) { + FutureTask { request() } + } + future.run() + return future.get() + } + + override fun close() { + requestMap.forEach { (_, future) -> + future.cancel(true) + } + } +} + +/** A [BuildService]-based implementation of [UploadRequestClient]. */ +abstract class BuildServiceUploadRequestClient : UploadRequestClient(), BuildService + +/** A simple [UploadRequestClient] for use on Gradle <6.1 */ +class LegacyUploadRequestClient : UploadRequestClient() + +internal fun newUploadRequestClientProvider(project: Project, prefix: String): Provider { + return if (project.gradle.versionNumber() >= GradleVersions.VERSION_6_1) { + project.gradle.sharedServices.registerIfAbsent("bugsnag${prefix.capitalize()}UploadRequestClient", + BuildServiceUploadRequestClient::class.java + ) { + // No parameters! + } + } else { + project.provider(::LegacyUploadRequestClient) + } +} diff --git a/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt b/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt index b7a3ad73..bc892fee 100644 --- a/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt +++ b/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt @@ -1,5 +1,6 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.LegacyUploadRequestClient import org.junit.Assert.assertEquals import org.junit.Test @@ -15,7 +16,7 @@ class UploadRequestClientTest { @Test fun testRequestDiffVersionInfo() { - val client = UploadRequestClient() + val client = LegacyUploadRequestClient() var requestCount = 0 val request = { requestCount += 1 @@ -28,7 +29,7 @@ class UploadRequestClientTest { @Test fun testRequestDiffPayload() { - val client = UploadRequestClient() + val client = LegacyUploadRequestClient() var requestCount = 0 val request = { requestCount += 1 @@ -41,7 +42,7 @@ class UploadRequestClientTest { @Test fun testRequestSameInfo() { - val client = UploadRequestClient() + val client = LegacyUploadRequestClient() var requestCount = 0 val request = { requestCount += 1 From 68f3bc1aa0a3fa8852642634875b02a4a45c14ca Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 03:36:23 -0400 Subject: [PATCH 27/36] Detekt issues --- src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index 3ada40ca..e933912b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -45,6 +45,7 @@ class BugsnagPlugin : Plugin { const val BUNDLE_TASK = "bundle" } + @Suppress("LongMethod") override fun apply(project: Project) { // After Gradle 5.2, this can use service injection for injecting ObjectFactory val bugsnag = project.extensions.create( @@ -57,7 +58,8 @@ class BugsnagPlugin : Plugin { return@withPlugin } - val httpClientHelperProvider: Provider = if (project.gradle.versionNumber() >= GradleVersions.VERSION_6_1) { + val canUseBuildService = project.gradle.versionNumber() >= GradleVersions.VERSION_6_1 + val httpClientHelperProvider = if (canUseBuildService) { project.gradle.sharedServices.registerIfAbsent("bugsnagHttpClientHelper", BuildServiceBugsnagHttpClientHelper::class.java ) { spec -> @@ -142,6 +144,7 @@ class BugsnagPlugin : Plugin { * * See https://sites.google.com/a/android.com/tools/tech-docs/new-build-system/user-guide#TOC-Build-Variants */ + @Suppress("LongParameterList") private fun registerBugsnagTasksForVariant( project: Project, variant: ApkVariant, From a91949bdd01033717dbf367e9a9b43efcb019e8b Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 03:46:02 -0400 Subject: [PATCH 28/36] Remove import --- .../com/bugsnag/android/gradle/internal/UploadRequestClient.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt index e5f6b0ee..ca27ebd1 100644 --- a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -7,7 +7,6 @@ import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters -import org.gradle.tooling.internal.protocol.BuildParameters import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.FutureTask From f1c443b8b2793375f988632edb01437acbe0639d Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 04:16:35 -0400 Subject: [PATCH 29/36] Use fast file hashing + de-dupe buildUuid from hashcode generation --- .../AndroidManifestInfo.kt | 10 +++++----- .../BugsnagInstallJniLibsTask.kt | 3 +++ .../BugsnagManifestUuidTask.kt | 1 + .../BugsnagPlugin.kt | 3 +++ .../BugsnagPluginExtension.kt | 4 ++++ .../BugsnagReleasesTask.kt | 7 ++++++- .../BugsnagUploadNdkTask.kt | 12 ++++++++++-- .../BugsnagUploadProguardTask.kt | 10 ++++++++-- .../android/gradle/internal}/GradleUtil.kt | 15 ++++++++++++++- .../gradle/internal/UploadRequestClient.kt | 19 ++++++++++++++----- 10 files changed, 68 insertions(+), 16 deletions(-) rename src/main/kotlin/{com.bugsnag.android.gradle => com/bugsnag/android/gradle/internal}/GradleUtil.kt (85%) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestInfo.kt b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestInfo.kt index 7e833822..1d73741c 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestInfo.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestInfo.kt @@ -9,11 +9,11 @@ import java.io.File @JsonClass(generateAdapter = true) data class AndroidManifestInfo( - var apiKey: String, - var versionCode: String, - var buildUUID: String?, - var versionName: String, - var applicationId: String + val apiKey: String, + val versionCode: String, + val buildUUID: String?, + val versionName: String, + val applicationId: String ) { internal fun write(file: File) { file.sink().buffer().use { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index f57500fa..b234186b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -1,5 +1,8 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.GradleVersions +import com.bugsnag.android.gradle.internal.register +import com.bugsnag.android.gradle.internal.versionNumber import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.ArchiveOperations diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt index 64389746..2471f8e2 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagManifestUuidTask.kt @@ -3,6 +3,7 @@ package com.bugsnag.android.gradle import com.android.build.gradle.api.ApkVariant import com.android.build.gradle.api.ApkVariantOutput import com.android.build.gradle.tasks.ManifestProcessorTask +import com.bugsnag.android.gradle.internal.property import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.Directory diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index e933912b..c24062fe 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -10,9 +10,12 @@ import com.android.build.gradle.tasks.ExternalNativeBuildTask import com.bugsnag.android.gradle.BugsnagInstallJniLibsTask.Companion.resolveBugsnagArtifacts import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import com.bugsnag.android.gradle.internal.BuildServiceBugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.GradleVersions import com.bugsnag.android.gradle.internal.LegacyBugsnagHttpClientHelper import com.bugsnag.android.gradle.internal.UploadRequestClient import com.bugsnag.android.gradle.internal.newUploadRequestClientProvider +import com.bugsnag.android.gradle.internal.register +import com.bugsnag.android.gradle.internal.versionNumber import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt index cd518e4e..36b8771e 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPluginExtension.kt @@ -1,5 +1,9 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.listProperty +import com.bugsnag.android.gradle.internal.mapProperty +import com.bugsnag.android.gradle.internal.newInstance +import com.bugsnag.android.gradle.internal.property import groovy.lang.Closure import org.gradle.api.Action import org.gradle.api.model.ObjectFactory diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 72f167eb..5bda2bf4 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -1,6 +1,11 @@ package com.bugsnag.android.gradle +import com.bugsnag.android.gradle.internal.GradleVersions import com.bugsnag.android.gradle.internal.UploadRequestClient +import com.bugsnag.android.gradle.internal.mapProperty +import com.bugsnag.android.gradle.internal.property +import com.bugsnag.android.gradle.internal.register +import com.bugsnag.android.gradle.internal.versionNumber import com.squareup.moshi.JsonClass import okhttp3.OkHttpClient import org.gradle.api.DefaultTask @@ -136,7 +141,7 @@ sealed class BugsnagReleasesTask( val manifestInfo = parseManifestInfo() val payload = generateJsonPayload(manifestInfo) - val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, payload.toString()) { + val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, payload.hashCode()) { logger.lifecycle("Bugsnag: Attempting upload to Releases API") lateinit var response: String object : Call(retryCount, logger) { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt index 4d4928e5..9286607b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadNdkTask.kt @@ -4,8 +4,16 @@ import com.android.build.gradle.AppExtension import com.android.build.gradle.api.ApkVariantOutput import com.bugsnag.android.gradle.Abi.Companion.findByName import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper +import com.bugsnag.android.gradle.internal.GradleVersions import com.bugsnag.android.gradle.internal.UploadRequestClient +import com.bugsnag.android.gradle.internal.mapProperty +import com.bugsnag.android.gradle.internal.md5HashCode +import com.bugsnag.android.gradle.internal.property +import com.bugsnag.android.gradle.internal.register +import com.bugsnag.android.gradle.internal.versionNumber import okhttp3.RequestBody +import okio.HashingSource +import okio.blackholeSink import okio.buffer import okio.gzip import okio.sink @@ -200,8 +208,8 @@ sealed class BugsnagUploadNdkTask( "file for $sharedObjectName-$arch from $mappingFile") val manifestInfo = parseManifestInfo() - val mappingFileContents = mappingFile.readText() - val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, mappingFileContents) { + val mappingFileHash = mappingFile.md5HashCode() + val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, mappingFileHash) { logger.lifecycle("Bugsnag: Attempting to upload shared object mapping " + "file for $sharedObjectName-$arch from $mappingFile") request.uploadMultipartEntity(parts, parseManifestInfo()) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt index 7c4438a5..02c6d780 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagUploadProguardTask.kt @@ -2,7 +2,13 @@ package com.bugsnag.android.gradle import com.bugsnag.android.gradle.internal.BugsnagHttpClientHelper import com.bugsnag.android.gradle.internal.UploadRequestClient +import com.bugsnag.android.gradle.internal.md5HashCode +import com.bugsnag.android.gradle.internal.property import okhttp3.RequestBody +import okio.HashingSource +import okio.blackholeSink +import okio.buffer +import okio.source import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory @@ -93,8 +99,8 @@ open class BugsnagUploadProguardTask @Inject constructor( // Send the request val request = BugsnagMultiPartUploadRequest.from(this) val manifestInfo = parseManifestInfo() - val mappingFileContents = mappingFile.readText() - val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, mappingFileContents) { + val mappingFileHash = mappingFile.md5HashCode() + val response = uploadRequestClient.get().makeRequestIfNeeded(manifestInfo, mappingFileHash) { logger.lifecycle("Bugsnag: Attempting to upload JVM mapping file: $mappingFile") request.uploadMultipartEntity(parts, manifestInfo) } diff --git a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/GradleUtil.kt similarity index 85% rename from src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt rename to src/main/kotlin/com/bugsnag/android/gradle/internal/GradleUtil.kt index 7bf7d995..d0d59136 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/GradleUtil.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/GradleUtil.kt @@ -1,6 +1,10 @@ @file:Suppress("MatchingDeclarationName") // This file contains multiple top-level members -package com.bugsnag.android.gradle +package com.bugsnag.android.gradle.internal +import okio.HashingSource +import okio.blackholeSink +import okio.buffer +import okio.source import org.gradle.api.Task import org.gradle.api.invocation.Gradle import org.gradle.api.model.ObjectFactory @@ -11,6 +15,7 @@ import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.TaskContainer import org.gradle.api.tasks.TaskProvider import org.gradle.util.VersionNumber +import java.io.File internal object GradleVersions { val VERSION_5_3: VersionNumber = VersionNumber.parse("5.3") @@ -21,6 +26,14 @@ internal object GradleVersions { internal fun Gradle.versionNumber(): VersionNumber = VersionNumber.parse(gradleVersion) +/** A fast file hash that don't load the entire file contents into memory at once. */ +internal fun File.md5HashCode(): Int { + return HashingSource.md5(source()).use { hashingSource -> + hashingSource.buffer().readAll(blackholeSink()) + hashingSource.hash.hashCode() + } +} + /* Borrowed helper functions from the Gradle Kotlin DSL. */ /** diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt index ca27ebd1..b8f34ad2 100644 --- a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -1,12 +1,11 @@ package com.bugsnag.android.gradle.internal import com.bugsnag.android.gradle.AndroidManifestInfo -import com.bugsnag.android.gradle.GradleVersions -import com.bugsnag.android.gradle.versionNumber import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters +import java.util.Objects import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.FutureTask @@ -27,11 +26,11 @@ sealed class UploadRequestClient : AutoCloseable { */ fun makeRequestIfNeeded( manifestInfo: AndroidManifestInfo, - payload: String, + payloadHash: Int, request: () -> String ): String { - val versionInfoHash = manifestInfo.hashCode() - val requestIdHash = versionInfoHash + payload.hashCode() + val versionInfoHash = manifestInfo.requestHash() + val requestIdHash = Objects.hash(versionInfoHash, payloadHash) val future = requestMap.getOrPut(requestIdHash.toString()) { FutureTask { request() } @@ -47,6 +46,16 @@ sealed class UploadRequestClient : AutoCloseable { } } +// Hashcode without buildUuid +private fun AndroidManifestInfo.requestHash(): Int { + return Objects.hash( + apiKey, + versionCode, + versionName, + applicationId + ) +} + /** A [BuildService]-based implementation of [UploadRequestClient]. */ abstract class BuildServiceUploadRequestClient : UploadRequestClient(), BuildService From 2f136e3a6d5edab880d2c0c4774fa1ad6d8ff220 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 04:17:55 -0400 Subject: [PATCH 30/36] Update test --- .../android/gradle/UploadRequestClientTest.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt b/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt index bc892fee..2bbc504f 100644 --- a/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt +++ b/src/test/kotlin/com/bugsnag/android/gradle/UploadRequestClientTest.kt @@ -22,8 +22,8 @@ class UploadRequestClientTest { requestCount += 1 "" } - client.makeRequestIfNeeded(info, "{}", request) - client.makeRequestIfNeeded(info.copy(apiKey = "40fadb0123094f"), "{}", request) + client.makeRequestIfNeeded(info, "{}".hashCode(), request) + client.makeRequestIfNeeded(info.copy(apiKey = "40fadb0123094f"), "{}".hashCode(), request) assertEquals(2, requestCount) } @@ -35,8 +35,8 @@ class UploadRequestClientTest { requestCount += 1 "" } - client.makeRequestIfNeeded(info, "{}", request) - client.makeRequestIfNeeded(info, "[]", request) + client.makeRequestIfNeeded(info, "{}".hashCode(), request) + client.makeRequestIfNeeded(info, "[]".hashCode(), request) assertEquals(2, requestCount) } @@ -48,8 +48,8 @@ class UploadRequestClientTest { requestCount += 1 "" } - client.makeRequestIfNeeded(info, "{}", request) - client.makeRequestIfNeeded(info, "{}", request) + client.makeRequestIfNeeded(info, "{}".hashCode(), request) + client.makeRequestIfNeeded(info, "{}".hashCode(), request) assertEquals(1, requestCount) } } From 55eb3f1a653e02db76e4b204469e61af55db11d2 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 04:20:34 -0400 Subject: [PATCH 31/36] Use single provider instance --- .../bugsnag/android/gradle/internal/UploadRequestClient.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt index b8f34ad2..7f6da05c 100644 --- a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -70,6 +70,8 @@ internal fun newUploadRequestClientProvider(project: Project, prefix: String): P // No parameters! } } else { - project.provider(::LegacyUploadRequestClient) + // Reuse this single instance every time it's provided + val provider = LegacyUploadRequestClient() + project.provider { provider } } } From 8a6e5db71c564ddd08075b5fb2797bc0a9521367 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 04:23:33 -0400 Subject: [PATCH 32/36] Use single provider instance --- src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt index c24062fe..6ef80d0b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagPlugin.kt @@ -70,7 +70,9 @@ class BugsnagPlugin : Plugin { spec.parameters.timeoutMillis.set(bugsnag.requestTimeoutMs) } } else { - project.provider { LegacyBugsnagHttpClientHelper(bugsnag.requestTimeoutMs) } + // Reuse instance + val client = LegacyBugsnagHttpClientHelper(bugsnag.requestTimeoutMs) + project.provider { client } } val releasesUploadClientProvider = newUploadRequestClientProvider(project, "releases") From dcf8007abc85ec15622627a25274b2c9ee553704 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 9 Aug 2020 23:08:02 -0400 Subject: [PATCH 33/36] Revert custom hashcode --- .../android/gradle/internal/UploadRequestClient.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt index 7f6da05c..8bb9876b 100644 --- a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -29,7 +29,7 @@ sealed class UploadRequestClient : AutoCloseable { payloadHash: Int, request: () -> String ): String { - val versionInfoHash = manifestInfo.requestHash() + val versionInfoHash = manifestInfo.hashCode() val requestIdHash = Objects.hash(versionInfoHash, payloadHash) val future = requestMap.getOrPut(requestIdHash.toString()) { @@ -46,16 +46,6 @@ sealed class UploadRequestClient : AutoCloseable { } } -// Hashcode without buildUuid -private fun AndroidManifestInfo.requestHash(): Int { - return Objects.hash( - apiKey, - versionCode, - versionName, - applicationId - ) -} - /** A [BuildService]-based implementation of [UploadRequestClient]. */ abstract class BuildServiceUploadRequestClient : UploadRequestClient(), BuildService From d8ed6ff9598af9106367b631ab3e86a8df4dd6da Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 10 Aug 2020 02:38:36 -0400 Subject: [PATCH 34/36] Remove content --- .../kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt index 868cf08c..88acb5da 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/AndroidManifestParser.kt @@ -63,7 +63,6 @@ internal class AndroidManifestParser { |versionName=$versionName |applicationId=$applicationId |Manifest file = $manifestPath - |Manifest content=${manifestPath.readText()} """.trimMargin()) } return AndroidManifestInfo(apiKey, versionCode, buildUUID, versionName, applicationId) From d7bada8214d547b97a1bef46a17de69c876b440d Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Mon, 10 Aug 2020 12:01:09 +0100 Subject: [PATCH 35/36] address review feedback --- .../BugsnagInstallJniLibsTask.kt | 12 ++++++------ .../BugsnagReleasesTask.kt | 3 +-- .../android/gradle/internal/UploadRequestClient.kt | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt index b234186b..64c2a02b 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagInstallJniLibsTask.kt @@ -88,12 +88,12 @@ sealed class BugsnagInstallJniLibsTask( return when { gradleVersion >= GradleVersions.VERSION_6 -> { when { - gradleVersion >= GradleVersions.VERSION_6_6 -> { - project.tasks.register(name, configurationAction) - } - else -> { - project.tasks.register(name, configurationAction) - } + gradleVersion >= GradleVersions.VERSION_6_6 -> { + project.tasks.register(name, configurationAction) + } + else -> { + project.tasks.register(name, configurationAction) + } } } gradleVersion >= GradleVersions.VERSION_5_3 -> { diff --git a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt index 5bda2bf4..79c5a55a 100644 --- a/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt +++ b/src/main/kotlin/com.bugsnag.android.gradle/BugsnagReleasesTask.kt @@ -272,7 +272,7 @@ sealed class BugsnagReleasesTask( VersionNumber.parse(it) } gitVersion.set(providerFactory.provider { runCmd(VCS_COMMAND, "--version") } ) - if (gradleVersionNumber != null && gradleVersionNumber >= SYS_PROPERTIES_VERSION) { + if (gradleVersionNumber != null && gradleVersionNumber >= GradleVersions.VERSION_6_1) { osArch.set(providerFactory.systemProperty(MK_OS_ARCH) ) osName.set(providerFactory.systemProperty(MK_OS_NAME) ) osVersion.set(providerFactory.systemProperty(MK_OS_VERSION) ) @@ -294,7 +294,6 @@ sealed class BugsnagReleasesTask( private const val MK_JAVA_VERSION = "java.version" private const val VCS_COMMAND = "git" private const val CHARSET_UTF8 = "UTF-8" - private val SYS_PROPERTIES_VERSION = VersionNumber.parse("6.1") @JvmStatic fun isValidVcsProvider(provider: String?): Boolean { diff --git a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt index 8bb9876b..96d1c1c8 100644 --- a/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt +++ b/src/main/kotlin/com/bugsnag/android/gradle/internal/UploadRequestClient.kt @@ -21,7 +21,7 @@ sealed class UploadRequestClient : AutoCloseable { * will be returned. If no existing requests match, a new request will * be enqueued and executed. * - * Equality is measured by the [AndroidManifestInfo] (excluding buildUuid) + * Equality is measured by the [AndroidManifestInfo] * and the request payload. */ fun makeRequestIfNeeded( From 11f3e2bdedc0e6b79eb857f61a2045c2383acf9d Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Mon, 10 Aug 2020 14:05:13 +0100 Subject: [PATCH 36/36] docs: add changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50b7ae4a..afcfa10c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,16 @@ improvements compared to previous versions of the plugin, such as: - Supporting [up-to-date checks](https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:up_to_date_checks) - Supporting [task configuration avoidance](https://docs.gradle.org/current/userguide/task_configuration_avoidance.html) +- Supporting the [configuration cache](https://docs.gradle.org/current/userguide/configuration_cache.html) - Avoidance of unnecessary work See the [Upgrade Guide](./UPGRADING.md) for migration instructions. ### Changes +Support configuration caching +[#257](https://github.com/bugsnag/bugsnag-android-gradle-plugin/pull/257) + Convert plugin extension to use property syntax [#251](https://github.com/bugsnag/bugsnag-android-gradle-plugin/pull/251)