Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.triplet.gradle.play.PlayPublisherPlugin.kt Maven / Gradle / Ivy
package com.github.triplet.gradle.play
import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.github.triplet.gradle.androidpublisher.ResolutionStrategy
import com.github.triplet.gradle.common.validation.validateRuntime
import com.github.triplet.gradle.play.internal.PLAY_CONFIGS_PATH
import com.github.triplet.gradle.play.internal.PLAY_PATH
import com.github.triplet.gradle.play.internal.PRODUCTS_PATH
import com.github.triplet.gradle.play.internal.PlayExtensionConfig
import com.github.triplet.gradle.play.internal.buildExtension
import com.github.triplet.gradle.play.internal.config
import com.github.triplet.gradle.play.internal.flavorNameOrDefault
import com.github.triplet.gradle.play.internal.getCommitEditTask
import com.github.triplet.gradle.play.internal.getGenEditTask
import com.github.triplet.gradle.play.internal.newTask
import com.github.triplet.gradle.play.internal.playPath
import com.github.triplet.gradle.play.internal.resolutionStrategyOrDefault
import com.github.triplet.gradle.play.internal.validateCreds
import com.github.triplet.gradle.play.internal.validateDebuggability
import com.github.triplet.gradle.play.tasks.Bootstrap
import com.github.triplet.gradle.play.tasks.GenerateResources
import com.github.triplet.gradle.play.tasks.InstallInternalSharingArtifact
import com.github.triplet.gradle.play.tasks.ProcessArtifactMetadata
import com.github.triplet.gradle.play.tasks.PromoteRelease
import com.github.triplet.gradle.play.tasks.PublishApk
import com.github.triplet.gradle.play.tasks.PublishBundle
import com.github.triplet.gradle.play.tasks.PublishInternalSharingApk
import com.github.triplet.gradle.play.tasks.PublishInternalSharingBundle
import com.github.triplet.gradle.play.tasks.PublishListings
import com.github.triplet.gradle.play.tasks.PublishProducts
import com.github.triplet.gradle.play.tasks.internal.BootstrapLifecycleTask
import com.github.triplet.gradle.play.tasks.internal.BootstrapOptions
import com.github.triplet.gradle.play.tasks.internal.GlobalPublishableArtifactLifecycleTask
import com.github.triplet.gradle.play.tasks.internal.PublishableTrackLifecycleTask
import com.github.triplet.gradle.play.tasks.internal.UpdatableTrackLifecycleTask
import com.github.triplet.gradle.play.tasks.internal.WriteTrackLifecycleTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.gradle.kotlin.dsl.container
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.findPlugin
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.the
import org.gradle.kotlin.dsl.withType
import kotlin.reflect.KMutableProperty1
@Suppress("unused") // Used by Gradle
internal class PlayPublisherPlugin : Plugin {
override fun apply(project: Project) {
project.validateRuntime()
project.extensions.create(PLAY_PATH)
project.plugins.withType {
applyInternal(project)
}
project.afterEvaluate {
if (project.plugins.findPlugin(AppPlugin::class) == null) {
throw IllegalStateException(
"The Android Gradle Plugin was not applied. Gradle Play Publisher " +
"cannot be configured.")
}
}
}
private fun applyInternal(project: Project) {
val baseExtension = project.extensions.getByType()
val extensionContainer = project.container()
val bootstrapOptionsHolder = BootstrapOptions.Holder()
val bootstrapAllTask = project.newTask(
"bootstrap",
"""
|Downloads the Play Store listing metadata for all variants.
| See https://github.com/Triple-T/gradle-play-publisher#quickstart
""".trimMargin(),
arrayOf(bootstrapOptionsHolder)
)
val publishAllTask = project.newTask(
"publish",
"""
|Uploads APK or App Bundle and all Play Store metadata for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#managing-artifacts
""".trimMargin(),
arrayOf(baseExtension)
)
val publishApkAllTask = project.newTask(
"publishApk",
"""
|Uploads APK for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-apks
""".trimMargin(),
arrayOf(baseExtension)
)
val publishBundleAllTask = project.newTask(
"publishBundle",
"""
|Uploads App Bundle for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-an-app-bundle
""".trimMargin(),
arrayOf(baseExtension)
)
val promoteReleaseAllTask = project.newTask(
"promoteArtifact",
"""
|Promotes a release for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#promoting-artifacts
""".trimMargin(),
arrayOf(baseExtension)
)
val publishListingAllTask = project.newTask(
"publishListing",
"""
|Uploads all Play Store metadata for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-listings
""".trimMargin(),
arrayOf(baseExtension)
)
val publishProductsAllTask = project.newTask(
"publishProducts",
"""
|Uploads all Play Store in-app products for every variant.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-in-app-products
""".trimMargin()
)
val android = project.the()
(android as ExtensionAware).extensions.add(PLAY_CONFIGS_PATH, extensionContainer)
android.applicationVariants.whenObjectAdded {
val variantName = name.capitalize()
val extension = buildExtension(extensionContainer, baseExtension)
project.logger.debug("Extension computed for variant '$name': $extension")
if (!extension.isEnabled) {
project.logger.info("Gradle Play Publisher is disabled for variant '$name'.")
return@whenObjectAdded
}
extension.validateCreds()
val publishApkTaskDependenciesHack = project.newTask(
"publish${variantName}ApkWrapper"
) {
val addDependencies = {
if (extension.config.artifactDir == null) {
assembleProvider?.let {
dependsOn(it)
} ?: logger.warn("Assemble task not found. Publishing APKs may not work.")
}
}
addDependencies()
extension._callbacks += { property: KMutableProperty1,
_: Any? ->
if (property.name == PlayExtensionConfig::artifactDir.name) {
setDependsOn(emptyList())
addDependencies()
}
}
}
val publishBundleTaskDependenciesHack = project.newTask(
"publish${variantName}BundleWrapper"
) {
val addDependencies = {
if (extension.config.artifactDir == null) {
// TODO blocked by https://issuetracker.google.com/issues/109918868
val bundleTask = project.tasks.findByName("bundle$variantName")?.let {
dependsOn(it)
}
if (bundleTask == null) {
logger.warn("Bundle task not found, make sure to use " +
"'com.android.tools.build:gradle' v3.2+. " +
"Publishing App Bundles may not work.")
}
}
}
addDependencies()
extension._callbacks += { property: KMutableProperty1,
_: Any? ->
if (property.name == PlayExtensionConfig::artifactDir.name) {
setDependsOn(emptyList())
addDependencies()
}
}
}
val publishInternalSharingApkTask = project.newTask(
"upload${variantName}PrivateApk",
"""
|Uploads Internal Sharing APK for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#uploading-an-internal-sharing-artifact
""".trimMargin(),
arrayOf(extension, this)
) {
outputDirectory.set(project.layout.buildDirectory.dir(
"outputs/internal-sharing/apk/${variant.name}"))
dependsOn(publishApkTaskDependenciesHack)
}
val publishInternalSharingBundleTask = project.newTask(
"upload${variantName}PrivateBundle",
"""
|Uploads Internal Sharing App Bundle for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#uploading-an-internal-sharing-artifact
""".trimMargin(),
arrayOf(extension, this)
) {
outputDirectory.set(project.layout.buildDirectory.dir(
"outputs/internal-sharing/bundle/${variant.name}"))
dependsOn(publishBundleTaskDependenciesHack)
}
project.newTask(
"install${variantName}PrivateArtifact",
"""
|Launches an intent to install an Internal Sharing artifact for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#installing-internal-sharing-artifacts
""".trimMargin(),
arrayOf(android)
) {
uploadedArtifacts.set(if (extension.defaultToAppBundles) {
publishInternalSharingBundleTask.flatMap { it.outputDirectory }
} else {
publishInternalSharingApkTask.flatMap { it.outputDirectory }
})
}
if (!validateDebuggability()) return@whenObjectAdded
val genEditTask = project.getGenEditTask(applicationId, extension)
val commitEditTask = project.getCommitEditTask(applicationId, extension)
val editFile = genEditTask.flatMap { it.editIdFile }
genEditTask { finalizedBy(commitEditTask) }
val bootstrapTask = project.newTask(
"bootstrap$variantName",
"""
|Downloads the Play Store listing metadata for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#quickstart
""".trimMargin(),
arrayOf(extension, this, bootstrapOptionsHolder)
) {
srcDir.set(project.file("src/${variant.flavorNameOrDefault}/$PLAY_PATH"))
editIdFile.set(editFile)
dependsOn(genEditTask)
}
bootstrapAllTask { dependsOn(bootstrapTask) }
// TODO(#710): Remove in v3.0
project.newTask("bootstrap${variantName}PlayResources") {
dependsOn(bootstrapTask)
doFirst { logger.warn("$name is deprecated, use ${bootstrapTask.get().name} instead") }
}
val resourceDir = project.newTask(
"generate${variantName}PlayResources"
) {
val dirs = sourceSets.map {
project.layout.projectDirectory.dir("src/${it.name}/$PLAY_PATH")
}
resSrcDirs.set(dirs)
resSrcTree.setFrom(dirs.map { project.fileTree(it).apply { exclude("**/.*") } })
resDir.set(project.layout.buildDirectory.dir(playPath))
mustRunAfter(bootstrapTask)
}.flatMap {
it.resDir
}
val publishListingTask = project.newTask(
"publish${variantName}Listing",
"""
|Uploads all Play Store metadata for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-listings
""".trimMargin(),
arrayOf(extension, this)
) {
resDir.set(resourceDir)
editIdFile.set(editFile)
dependsOn(genEditTask)
}
commitEditTask { mustRunAfter(publishListingTask) }
publishListingAllTask { dependsOn(publishListingTask) }
// TODO(#710): Remove in v3.0
project.newTask("publishListing$variantName") {
dependsOn(publishListingTask)
doFirst { logger.warn("$name is deprecated, use ${publishListingTask.get().name} instead") }
}
val publishProductsTask = project.newTask(
"publish${variantName}Products",
"""
|Uploads all Play Store in-app products for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-in-app-products
""".trimMargin(),
arrayOf(extension, this)
) {
productsDir.setFrom(resourceDir.map {
it.dir(PRODUCTS_PATH).asFileTree.matching { include("*.json") }
})
}
publishProductsAllTask { dependsOn(publishProductsTask) }
val processArtifactMetadata = project.newTask(
"process${variantName}Metadata",
constructorArgs = arrayOf(extension, this)
) {
editIdFile.set(editFile)
val shouldRun =
extension.config.resolutionStrategyOrDefault == ResolutionStrategy.AUTO
onlyIf { shouldRun }
if (shouldRun) dependsOn(genEditTask)
}
preBuildProvider { dependsOn(processArtifactMetadata) }
publishApkTaskDependenciesHack { dependsOn(processArtifactMetadata) }
publishBundleTaskDependenciesHack { dependsOn(processArtifactMetadata) }
val publishApkTask = project.newTask(
"publish${variantName}Apk",
"""
|Uploads APK for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-apks
""".trimMargin(),
arrayOf(extension, this)
) {
resDir.set(resourceDir)
editIdFile.set(editFile)
dependsOn(resourceDir)
dependsOn(genEditTask)
dependsOn(publishApkTaskDependenciesHack)
}
commitEditTask { mustRunAfter(publishApkTask) }
publishApkAllTask { dependsOn(publishApkTask) }
// TODO(#710): Remove in v3.0
project.newTask("publishApk$variantName") {
dependsOn(publishApkTask)
doFirst { logger.warn("$name is deprecated, use ${publishApkTask.get().name} instead") }
}
val publishBundleTask = project.newTask(
"publish${variantName}Bundle",
"""
|Uploads App Bundle for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#publishing-an-app-bundle
""".trimMargin(),
arrayOf(extension, this)
) {
resDir.set(resourceDir)
editIdFile.set(editFile)
dependsOn(resourceDir)
dependsOn(genEditTask)
dependsOn(publishBundleTaskDependenciesHack)
}
commitEditTask { mustRunAfter(publishBundleTask) }
publishBundleAllTask { dependsOn(publishBundleTask) }
val promoteReleaseTask = project.newTask(
"promote${variantName}Artifact",
"""
|Promotes a release for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#promoting-artifacts
""".trimMargin(),
arrayOf(extension, this)
) {
resDir.set(resourceDir)
editIdFile.set(editFile)
dependsOn(resourceDir)
dependsOn(genEditTask)
mustRunAfter(publishApkTask)
mustRunAfter(publishBundleTask)
}
commitEditTask { mustRunAfter(promoteReleaseTask) }
promoteReleaseAllTask { dependsOn(promoteReleaseTask) }
val publishTask = project.newTask(
"publish$variantName",
"""
|Uploads APK or App Bundle and all Play Store metadata for variant '$name'.
| See https://github.com/Triple-T/gradle-play-publisher#managing-artifacts
""".trimMargin(),
arrayOf(extension)
) {
dependsOn(if (extension.defaultToAppBundles) publishBundleTask else publishApkTask)
dependsOn(publishListingTask)
dependsOn(publishProductsTask)
}
publishAllTask { dependsOn(publishTask) }
}
project.afterEvaluate {
val allPossiblePlayConfigNames: Set by lazy {
android.applicationVariants.flatMapTo(mutableSetOf()) {
listOf(it.name, it.buildType.getName()) + it.productFlavors.map { it.getName() }
}
}
for (configName in extensionContainer.names) {
if (configName !in allPossiblePlayConfigNames) {
project.logger.warn(
"Warning: Gradle Play Publisher playConfigs object '$configName' " +
"does not match a variant, flavor, or build type.")
}
}
}
}
}