Gradle-play-publisher: Support combining multiple drafts into a single release

Created on 23 Sep 2018  路  39Comments  路  Source: Triple-T/gradle-play-publisher

In projects with multiple modules (Eg: mobile and wear) publishRelease will fail due to the following error:

om.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
  {
    "code" : 403,
    "errors" : [ {
      "domain" : "androidpublisher",
      "message" : "You cannot rollout this release because it does not allow any existing users to upgrade to the newly added APKs.",
      "reason" : "apkNoUpgradePaths"
    } ],
    "message" : "You cannot rollout this release because it does not allow any existing users to upgrade to the newly added APKs."
  }

I believe that's because each APK is creating its own release, hence the second upload will fail with the above message.

Ideally publishRelease should create a multiple APK release.

Thank you!

bug enhancement

Most helpful comment

This feature will be available in v2.1. In the meantime, you can use JitPack to build this branch with a WIP version of the feature.

All 39 comments

Your APK version codes are all too low.

thanks, @SUPERCILEX
But could you please explain what do you mean by "too low"?
I put high numbers that were never used. And also tried to have mobile version code higher the wear version code and vice-versa. It didn't work though.

@alrosot Huh, that's weird. Are you using the 2.0 snapshots? And if you manually upload those APKs to the Play Store, does it let you publish the release?

I did try 2.0 snapshots. And then it failed because of this:

A problem occurred evaluating project ':mobile'.
> Could not set unknown property 'pk12File' for object of type com.github.triplet.gradle.play.PlayPublisherExtension.

And yes, Play Store allows me to upload those APKs manually

@alrosot Oh, ok. I thought you were already using 2.0. Please follow this migration guide and tell me if it still doesn't work with 2.0.

Thanks for the link @SUPERCILEX

However the issue persisted:

Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "androidpublisher",
    "message" : "You cannot rollout this release because it does not allow any existing users to upgrade to the newly added APKs.",
    "reason" : "apkNoUpgradePaths"
  } ],
  "message" : "You cannot rollout this release because it does not allow any existing users to upgrade to the newly added APKs."
}

I noticed it always publishes the mobile module successfully and then fails on the second upload (for the wear module).

Is there a way to change that order (just for science)?

Oh crud, this is similar to #217. BTW, is there a special spot where you upload wear APKs? Or do you upload both and the console figures it out? Sorry, I don't have wear experience.

It's in the same place. You just add both into the box "Android App Bundles and APKs to add" and the platform is clever enough to distinguish them.

Actually that's quite a nice feature. Because if you have a mobile APK published and then in a future release you also add the wear APK, the users will get a notification saying: "Look, this app that you have installed also can be used in your watch"

Alright, thanks for the clarification. This won't happen for v2.0, but we'll keep it on the roadmap. I hope you can understand! 馃槉

Current ideas:

  • Let the user supply a list of projects to publish together

Pros | Cons
--- | ---
Should be simple to implement | Only artifacts could be published together, which makes the feature unintuitive
Could possibly be useful in other cases | Or could cause confusion

  • Add the customizable folder input feature and tell people to build and dump their wear artifacts in there so it gets published with the phone ones

Pros | Cons
--- | ---
Already on the roadmap | A lot of manual setup on the user's part
| Error prone since dependent on ordering - feels like a hack

  • Add a draft editing feature so people can start with a draft then upload the other artifact before committing the edit.

Pros | Cons
--- | ---
Very flexible | API surface will be tough
Applicable in several other cases

Hi @SUPERCILEX ,
Today I realised that's only a problem when you have in your AndroidManifest.xml

      <meta-data
            android:name="com.google.android.wearable.standalone"
            android:value="true" />

If that is false (not standalone), the gradle plugin can embed the wear apk into the mobile apk and it just works.

@alrosot Nice workaround! I'd still like to support the standalone case though. 馃憤

I think this should still be named Support multiple APKs as that is the root of the problem, but I'm also having trouble figuring out how to publish multiple wear app versions to the same app on Play. My Wear 1 app targets min SDK 23 and my Wear 2 app targets SDK 25+. They are by necessity built in separate modules but share the same Application ID and both need to be uploaded in the same app release on Play.

I almost have a workaround: By setting releaseStatus = "draft" I'm able to upload both by specifically calling publishApk per module (i.e. gradle :wear:publishApk :wearapp:publishApk). The second publish will, however, overwrite the first upload and the draft will only contain the second APK. I can then go to the play console and manually add the other APK to the draft by browsing APKs (Add from library). This is not ideal, so I hope you'll have a way of supporting this soon :)

Here are some alternative ideas (not sure if they are possible to implement):

  1. add a separate gradle task to collect all APKs with the same Application ID and upload them
  2. reference other modules (or flavors) to include when publishing
  3. using resolutionStrategy to retain other APKs in the draft then separately publish the draft

Yeah, I think we'll just improve draft support so that they get reused if available when publishing other releases.

This feature will be available in v2.1. In the meantime, you can use JitPack to build this branch with a WIP version of the feature.

Hi there Alex, first, thank you for looking into it.
However, when i tried this line
play { commit = false }
the build will failed with this error "Could not set unknown property 'commit' for object of type com.github.triplet.gradle.play.PlayPublisherExtension."
Same with playConfigs { register("pie") { commit = true } }

Tried with GPP-2.0.0-beta2 and the snapshot version.

@pierx sorry for not being clearer. You need to use https://jitpack.io because we haven't merged this into a dev branch yet. Here's the artifact: com.github.Triple-T:gradle-play-publisher:d77e913.

Hi there again, thanks for the quick hint. It compiles now, however when i tried the line like on the readme files you linked previously i got this error
"Cannot add a ProductFlavor with name 'pie' as a ProductFlavor with that name already exists."

When i comment out that register("pie") line then try to build, i got this

Could not set unknown property 'commit' for ProductFlavor_Decorated{name=pie, dimension=null, minSdkVersion=null, targetSdkVersion=null, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=null, versionName=null, applicationId=null, testApplicationId=null, testInstrumentationRunner=null, testInstrumentationRunnerArguments={}, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields={}, mResValues={}, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders={}, mWearAppUnbundled=null} of type com.android.build.gradle.internal.dsl.ProductFlavor.

https://hastebin.com/cabafafome.php

@pierx hmmm, could you try moving the playConfigs block out of the product flavors one? I'm guessing groovy doesn't handle nested receivers properly.

When out of that block i got this error

Could not find method playConfigs() for arguments [build_ddxa926o4gyvluu908br8kb60$_run_closure5@1931e308] on project ':app' of type org.gradle.api.Project.

@pierx Make sure to keep it in the android block:

android {
    // ...
    productFlavors { ... }
    playConfigs { ... }
}

play { ... }

It works! Just verify it on console too, all flavor uploaded correctly as expected :)
Thank you very much for the first class support @SUPERCILEX

@pierx Awesome! Will update the docs to move playConfigs out of the flavors block. 馃憤

We are trying to get different play configurations per build type (not flavor), as we want our debug/qa/release build types to be published in different tracks.

Is this possible with the current playConfigs feature?

Same here but I can't get it to work with only build types. Also I can't get the CLI options to work.
When I run
./gradlew publishStagingApk --track=alpha,
I get the error message
Unknown command-line option '--track'.

I'm using 2.0-rc1

@alexfdz those should be product flavors. You can't publish debug builds (and probably not QA either if it extends the debug config).

thanks @SUPERCILEX

In our scenario the only difference between release and qa apps is the backend services it points to. We replicate even the publish process to google play.

That's why it would be useful to have the ability to publish to different tracks per build type.

I get that configuration per flavor is enough for the majority of scenarios.

@alexfdz so what are you doing with the build type that you couldn't do my mapping it to a product flavor? From a technical standpoint, it's super easy to support build type specific configs鈥擨'm mostly worried about the philosophical aspects.

Sure, I will try to explain our approach, more than happy to get some feedback.

As _we understand_ the build type vs product flavor dilema:

  • build types (debug, qa, release) define differences in _infrastructure_ features like obfuscation, apk signing, debuggability, crash reporting, backend environment, ... for the same product.

  • product flavors define differences in _functional_ features like free vs premium, different markets, different branding, ...

Quite in line with this thread in stackoverflow.

In our scenario the only difference between release and qa build types is the backend environment (production and pre-production). For us makes sense to deploy the qa build types to an Internal test track (and do all our manual QA), and the release apps to a Beta track (for our beta users).

Alright, you convinced me 馃榿. Please give com.github.Triple-T:gradle-play-publisher:65964bc711 a shot.

It works like a charm!
Thanks @SUPERCILEX

Sorry but I'm trying to use "Combining releases" bu I always get 馃憤

Could not find method commit() for arguments [true] on object of type com.github.triplet.gradle.play.PlayPublisherExtension.

this my implementation:

apply plugin: 'com.github.triplet.play'
android {
...
    productFlavors {
        urbyProduction {
            applicationId "----"
            minSdkVersion ----
            versionCode ----
            versionName ----
            dimension "nodata"
        }
        urbyPreMarshmallow {
            applicationId "------"
            minSdkVersion ----
            maxSdkVersion ----
            versionCode -----
            versionName ----
            dimension "nodata"
        }
}
    playConfigs {
        urbyProduction {
            serviceAccountCredentials = file('key/googlePlayServiceAccounti.json')
            track = 'internal'
            defaultToAppBundles = true
            resolutionStrategy = "auto"
           commit true
        }
        urbyPreMarshmallow {
            serviceAccountCredentials = file('key/googlePlayServiceAccounti.json')
            track = 'internal'
            defaultToAppBundles = true
            resolutionStrategy = "auto"
            commit true
        }
    }
}
play {
    serviceAccountCredentials = file('key/googlePlayServiceAccounti.json')
    track = 'internal'
    defaultToAppBundles = true
    resolutionStrategy = "auto"
    commit false
}

I import plugin with in this way:

   maven {
            url "https://jitpack.io"
        }
}
   dependencies {
classpath 'com.github.Triple-T:gradle-play-publisher:d5ab2ae'
}

Someone Can help me?

I already tried and tried now but still have problem :( I think that the problem is with commit in "playConfigs" block because commit in "play" block seems don't create problem, I still don't understand why there is problem

Ohhh, you need to use commit = ..., _not_ commit ....

Thanks a lot work I think you need to fix the readme in Combining releases Groovy part

Yup, updated the docs: ec1ce9b613acc5e727a3606021a3fcf3265e2ee1 馃憤

Hi guys sorry for my question again I'm using "commit" property as you can see in the previous comments so I will aspects that the flavours "urbyProduction" "urbyPreMarshmallow" should be upload in the same box version (same concept that already spoke @alrosot before), instated I found only last flavour in the internal test release ,other flavour is uploaded but no in the box so I have to manual create other release with both, I misinterpreted the purpose of the "commit" ? I tried to lunch both gradle: publishBundle and gradle: publishUrbyProductionReleaseBundle publishUrbyPreMarshmallowReleaseBundle

You have both flavors with commit set to true. The point is that only the last flavor you want to publish should have commit = true.

This is my question I would like to upload both flavour in same release (mean the box in google play console), my flavours create one app for android with version < 23 and another with >=23 so I wanna upload both

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sloy picture Sloy  路  3Comments

ivoberger picture ivoberger  路  4Comments

ironjan picture ironjan  路  3Comments

SUPERCILEX picture SUPERCILEX  路  6Comments

ToxicBakery picture ToxicBakery  路  4Comments