Skip to content

Commit

Permalink
Add support for combined releases (#466)
Browse files Browse the repository at this point in the history
* Make play extension fully configurable across flavors

Signed-off-by: Alex Saveau <[email protected]>

* Add docs

Signed-off-by: Alex Saveau <[email protected]>

* Fix tests

Signed-off-by: Alex Saveau <[email protected]>

* Add support for combined releases

Signed-off-by: Alex Saveau <[email protected]>

* Update docs

Signed-off-by: Alex Saveau <[email protected]>

* Update docs

Signed-off-by: Alex Saveau <[email protected]>

* Fix merge mistakes

Signed-off-by: Alex Saveau <[email protected]>

* Support build type overrides too

Signed-off-by: Alex Saveau <[email protected]>

* Fix groovy docs

* Fix merge mistakes

* Small updates

* Update deps and bump min AGP version to 3.1.4

* Fix build

* Only update homogeneous releases

* Log test progress

* Commit settings.gradle instead of generating it on-demand

* Log test output

* Fiddle with test versions

* Fix travis

* Tidy gen tests

* Improve cleaning tasks

* Kill broken test and add back removed one

* Fix broken clean tasks

* Match AGP test version with compile one

* Create PlayPublishTaskTest.groovy

* Update deps again

Signed-off-by: Alex Saveau <[email protected]>

* Support 3.1.0 min

Signed-off-by: Alex Saveau <[email protected]>

* Add missing property annotations

Signed-off-by: Alex Saveau <[email protected]>

* Fix merge mistakes

Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX authored and bhurling committed Jan 17, 2019
1 parent 25cbd0c commit 3e86503
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 7 deletions.
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ app details to the Google Play Store.
1. [Using CLI options](#using-cli-options)
1. [Encrypting Service Account keys](#encrypting-service-account-keys)
1. [Using multiple Service Accounts](#using-multiple-service-accounts)
1. [Combining releases](#combining-releases)
1. [Using HTTPS proxies](#using-https-proxies)

## Quickstart guide
Expand Down Expand Up @@ -501,6 +502,80 @@ play {

</details>

### Combining releases

If you want to publish multiple product flavors together or upload a wear APK with your app, you'll
need to combine multiple changes together before committing the release. This is achieved through
the commit property:

<details open><summary>Kotlin</summary>

```kt
android {
// ...

flavorDimensions("api")
productFlavors {
register("oreo") {
// ...
}

register("pie") {
// ...
}
}

playConfigs {
register("pie") {
commit = true
}
}
}

play {
commit = false
}
```

</details>

<details><summary>Groovy</summary>

```groovy
android {
// ...
flavorDimensions 'api'
productFlavors {
oreo {
// ...
}
pie {
// ...
}
}
playConfigs {
pie {
commit = true
}
}
}
play {
commit = false
}
```

</details>

The `commit` option can be used for any legal combined updates across any number of build
invocations. The only hard requirement is for a task with `commit = true` to be run _last_. Should
that not already be the case, Gradle's
[`mustRunAfter`](https://docs.gradle.org/current/dsl/org.gradle.api.Task.html#org.gradle.api.Task:mustRunAfter(java.lang.Object[]))
DSL will come in handy.

### Using HTTPS proxies

If you need to use GPP behind an HTTPS-proxy, but it fails with an `SSLHandshakeException`, you can
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ open class PlayPublisherExtension @JvmOverloads constructor(
_defaultToAppBundles = value
}

@get:Internal("Backing property for public input")
internal var _commit: Boolean? = null
/**
* Choose whether or not to apply the changes from this build. Defaults to true.
*/
@get:Input
var commit
get() = _commit ?: true
set(value) {
_commit = value
}

@get:Internal("Backing property for public input")
internal var _fromTrack: String? = null
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class PlayPublisherPlugin : Plugin<Project> {

val extension = productFlavors.mapNotNull {
extensionContainer.findByName(it.name)
}.singleOrNull().mergeWith(baseExtension)
}.singleOrNull().let {
it ?: extensionContainer.findByName(buildType.name)
}.mergeWith(baseExtension)
val variantName = name.capitalize()

if (!isSigningReady && !outputsAreSigned) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ internal const val LISTINGS_PATH = "listings"
internal const val GRAPHICS_PATH = "graphics"
internal const val RELEASE_NOTES_PATH = "release-notes"
internal const val PRODUCTS_PATH = "products"
internal const val RESOURCES_OUTPUT_PATH = "generated/gpp"
internal const val OUTPUT_PATH = "gpp"
internal const val RESOURCES_OUTPUT_PATH = "generated/$OUTPUT_PATH"
internal const val EDIT_ID_FILE = "$OUTPUT_PATH/edit-id.txt"

internal const val MIME_TYPE_STREAM = "application/octet-stream"
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ internal interface ExtensionOptions {
extension.defaultToAppBundles = value
}

@get:Internal
@set:Option(
option = "skip-commit",
description = "Don't commit changes from this build."
)
var skipCommitOption: Boolean
get() = throw UnsupportedOperationException()
set(value) {
extension.commit = !value
}

@get:Internal
@set:Option(
option = "from-track",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,21 @@ abstract class PlayPublishPackageBase : PlayPublishTaskBase() {
protected fun AndroidPublisher.Edits.updateTracks(editId: String, versions: List<Long>) {
progressLogger.progress("Updating tracks")

val track = if (extension.releaseStatusOrDefault == ReleaseStatus.IN_PROGRESS) {
val track = if (hasSavedEdit) {
tracks().get(variant.applicationId, editId, extension.track).execute().apply {
releases = if (releases.isNullOrEmpty()) {
listOf(TrackRelease().applyChanges(versions))
} else {
releases.map {
if (it.status == extension.releaseStatusOrDefault.publishedName) {
it.applyChanges(it.versionCodes.orEmpty() + versions)
} else {
it
}
}
}
}
} else if (extension.releaseStatusOrDefault == ReleaseStatus.IN_PROGRESS) {
tracks().get(variant.applicationId, editId, extension.track).execute().apply {
val keep = releases.orEmpty().filter {
it.status == ReleaseStatus.COMPLETED.publishedName ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@ package com.github.triplet.gradle.play.tasks.internal

import com.android.build.gradle.api.ApplicationVariant
import com.github.triplet.gradle.play.PlayPublisherExtension
import com.github.triplet.gradle.play.internal.EDIT_ID_FILE
import com.github.triplet.gradle.play.internal.areCredsValid
import com.github.triplet.gradle.play.internal.has
import com.github.triplet.gradle.play.internal.nullOrFull
import com.github.triplet.gradle.play.internal.orNull
import com.github.triplet.gradle.play.internal.safeCreateNewFile
import com.google.api.client.googleapis.json.GoogleJsonResponseException
import com.google.api.services.androidpublisher.AndroidPublisher
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.internal.logging.progress.ProgressLogger
import org.gradle.internal.logging.progress.ProgressLoggerFactory
import java.io.File

abstract class PlayPublishTaskBase : DefaultTask(), ExtensionOptions {
@get:Nested override lateinit var extension: PlayPublisherExtension
@get:Internal internal lateinit var variant: ApplicationVariant

private val savedEditId = File(project.rootProject.buildDir, EDIT_ID_FILE)
@get:Internal protected val hasSavedEdit get() = savedEditId.exists()

@get:Internal
protected val progressLogger: ProgressLogger = services[ProgressLoggerFactory::class.java]
.newOperation(javaClass)
Expand All @@ -32,10 +40,9 @@ abstract class PlayPublishTaskBase : DefaultTask(), ExtensionOptions {
block: AndroidPublisher.Edits.(editId: String) -> Unit
) {
val edits = publisher.edits()
val request = edits.insert(variant.applicationId, null)

val id = try {
request.execute().id
savedEditId.orNull()?.readText().nullOrFull()
?: edits.insert(variant.applicationId, null).execute().id
} catch (e: GoogleJsonResponseException) {
if (e has "applicationNotFound") {
if (skipIfNotFound) {
Expand All @@ -47,6 +54,11 @@ abstract class PlayPublishTaskBase : DefaultTask(), ExtensionOptions {
"The first version of your app must be uploaded via the " +
"Play Store console.", e)
}
} else if (e has "editAlreadyCommitted") {
logger.info("Failed to retrieve saved edit.")
project.delete(savedEditId)

return read(skipIfNotFound, block)
} else if (e.statusCode == 401) {
throw IllegalArgumentException(
"Service account not authenticated. See the README for instructions: " +
Expand All @@ -62,6 +74,15 @@ abstract class PlayPublishTaskBase : DefaultTask(), ExtensionOptions {

protected fun write(block: AndroidPublisher.Edits.(editId: String) -> Unit) = read {
block(it)
commit(variant.applicationId, it).execute()

if (extension.commit) {
try {
commit(variant.applicationId, it).execute()
} finally {
project.delete(savedEditId)
}
} else {
savedEditId.safeCreateNewFile().writeText(it)
}
}
}

0 comments on commit 3e86503

Please sign in to comment.