Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant specific application id not respected while publishing #979

Open
shanselm-ergon opened this issue Jul 12, 2021 · 15 comments
Open

Variant specific application id not respected while publishing #979

shanselm-ergon opened this issue Jul 12, 2021 · 15 comments
Labels
bug Indicates an unexpected problem or unintended behavior feature:other Involves a feature that doesn't fit in existing categories
Milestone

Comments

@shanselm-ergon
Copy link

I work in a project, which uses multi-dimension-flavor android builds. Each flavor gets a distinct application id (not just a suffix, the id changes completely). This setup worked well until I updated to AGP 4.2.2 and GPP 3.5.0 (works with AGP 4.1.3 and GPP 3.4.0).

The abstract setup looks like this:

android {
    ...
	flavorDimensions("env", "dim")

	productFlavors {
		create("a") {
			dimension = "env"
		}
		create("b") {
			dimension = "env"
		}
		create("x") {
			dimension = "dim"
		}
		create("y") {
			dimension = "dim"
		}
	}
	...
}
androidComponents.onVariants { variant ->
	variant.applicationId.set(
		when (variant.flavorName) {
			"aX" -> "a.x"
			"bX" -> "b.x"
			"aY" -> "a.y"
			"bY" -> "b.y"
			else -> throw(IllegalStateException("What's your flavor? $flavorName!"))
		}
	)
}

With the old AGP version, the syntax was slightly different, but I guess it was adopted correctly:

android {
	...
	onVariantProperties {
		applicationId.set(
			when (flavorName) {
				"aX" -> "a.x"
				"bX" -> "b.x"
				"aY" -> "a.y"
				"bY" -> "b.y"
				else -> throw(IllegalStateException("What's your flavor? $flavorName!"))
			}
		)
	}
	...
}

When I now try to upload one of my apps to the play store with ./gradlew publishAXReleaseApps I get the following error back:

-------------- REQUEST  --------------
POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/x.y.z/edits
Accept-Encoding: gzip
Authorization: <Not Logged>
User-Agent: gradle-play-publisher Google-API-Java-Client/1.31.5 Google-HTTP-Java-Client/1.39.2 (gzip)
x-goog-api-client: gl-java/11.0.11 gdcl/1.31.5 linux/4.15.0
Content-Encoding: gzip

curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'Authorization: <Not Logged>' -H 'User-Agent: gradle-play-publisher Google-API-Java-Client/1.31.5 Google-HTTP-Java-Client/1.39.2 (gzip)' -H 'x-goog-api-client: gl-java/11.0.11 gdcl/1.31.5 linux/4.15.0' -H 'Content-Encoding: gzip' -d '@-' -- 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications/x.y.z/edits' << $$$
-------------- RESPONSE --------------
HTTP/1.1 404 Not Found
Transfer-Encoding: chunked
X-Frame-Options: SAMEORIGIN
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Cache-Control: private
Server: ESF
X-Content-Type-Options: nosniff
Content-Encoding: gzip
Vary: Referer
Vary: X-Origin
Vary: Origin
X-XSS-Protection: 0
Date: Mon, 12 Jul 2021 08:50:19 GMT
Content-Type: application/json; charset=UTF-8

Total: 308 bytes
{
  "error": {
    "code": 404,
    "message": "Package not found: x.y.z.",
    "errors": [
      {
        "message": "Package not found: x.y.z.",
        "domain": "global",
        "reason": "notFound"
      }
    ],
    "status": "NOT_FOUND"
  }
}

:app:publishAXReleaseApk (Thread[Execution worker for ':',5,main]) completed. Took 0.637 secs.

And here we see the problem, the package it is looking for is not the variants application id, but the default application id defined in the manifest file, which matches the package structure.

It seems like the variants application id adjustments are not propagated to the publish task.

To be honest, I'm not sure if it is a problem in the AGP, or in the GPP, or even in my configuration, but I couldn't figure it out.
Any help would be appreciated.

How To Reproduce

See description above.

Versions

  • Gradle Play Publisher: 3.5.0
  • Gradle Wrapper: 7.0 (also tried with 7.1.1)
  • Android Gradle Plugin: 4.2.2

Tasks executed

./gradlew publishAXReleaseApps.

Expected behavior

The app gets uploaded to the play store.

Additional context (if a crash, provide stack trace)

See description above.

@shanselm-ergon shanselm-ergon added the bug Indicates an unexpected problem or unintended behavior label Jul 12, 2021
@SUPERCILEX
Copy link
Collaborator

Yeah, this one is a duplicate of #948. Looks like it is going to be an issue, so I'll have to give the approach I wrote in the last comment a try.

In the meantime, do id "com.github.triplet.play" version "..." apply false and then at the bottom of your build script put apply(plugin = "com.github.triplet.play"). The problem is that the plugin currently needs correct app IDs at configuration time.

@SUPERCILEX SUPERCILEX added the feature:other Involves a feature that doesn't fit in existing categories label Jul 12, 2021
@shanselm-ergon
Copy link
Author

shanselm-ergon commented Jul 13, 2021

Thanks for your fast reply. The described approach unfortunately won't work for me, because I use the play configuration section, which won't be available if the plugin is not applied. Is there an other way of configuring the plugin?

play {
    serviceAccountCredentials.set(file(extra.get("googlePlayPublishKeyFile")!!))
    track.set("internal") // internal (default) / alpha / beta / production or any custom track
}

@SUPERCILEX
Copy link
Collaborator

SUPERCILEX commented Jul 15, 2021

Right, you'll need to use this syntax:

import com.github.triplet.gradle.play.PlayPublisherExtension

// ...

configure<PlayPublisherExtension> {
  // ...
}

@micer
Copy link

micer commented Jul 20, 2021

I have the same issue with incorrect application id. @SUPERCILEX how to use configure<PlayPublisherExtension> in Groovy build.gradle?

@SUPERCILEX
Copy link
Collaborator

With groovy, you should be able to still use the play block. It's all dynamic so as long as the apply plugin: ... comes before you'll be good.

@micer
Copy link

micer commented Jul 21, 2021

Unfortunately GPP is still using wrong application id for me. I'm setting it by applicationVariants.all { variant -> setApplicationId(variant)

I'm using
id("com.github.triplet.play") version "3.4.0-agp4.2" apply false
in global build.gradle and
apply plugin: "com.github.triplet.play"
in :app build.gradle because of dependencies conflict (#901 (comment)).

I have play block after apply plugin: .... Any idea? I suppose it's not possible to set application id to GPP later than at configuration time?

@SUPERCILEX
Copy link
Collaborator

And you're applying the plugin after touching the application variants?

@micer
Copy link

micer commented Jul 22, 2021

Yes, I tried this order:

android {
	applicationVariants.all { variant ->
	    setApplicationId(variant)
	    println("setApplicationId")
	}
}

apply plugin: 'com.github.triplet.play'

android {
    playConfigs {
        println("GPP playConfigs")
        abcRelease {
            enabled.set(true)
        }
        ...
    }
}

play {
    println("GPP play")
    enabled.set(false)
    serviceAccountCredentials.set(file("config.json"))
    track.set("production")
    releaseStatus.set(com.github.triplet.gradle.androidpublisher.ReleaseStatus.DRAFT)
}

I tried to put apply plugin: 'com.github.triplet.play' in android {} block between touching the application variants and playConfig, but it's the same.

From logs I can see the order:

GPP playConfigs
GPP play
setApplicationId
setApplicationId
setApplicationId
...

@SUPERCILEX
Copy link
Collaborator

Ah shoot, that's nasty. I think you'll have to use the new API:

androidComponents {
    onVariants { variant ->
        variant.applicationId.set("blah")
    }
}

apply plugin: 'com.github.triplet.play'

// ...

What Android Gradle Plugin version are you using? It might look like this instead:

androidComponents {
  onVariantProperties {
    applicationId.set("blah")
  }
}

@SUPERCILEX SUPERCILEX modified the milestones: Backlog, 3.8.0 Sep 29, 2021
@SUPERCILEX SUPERCILEX modified the milestones: 3.8.0, Backlog Nov 28, 2021
@yital9
Copy link

yital9 commented Feb 3, 2022

Hi @SUPERCILEX. Do you have any plans to fix this issue? We are also currently facing this problem and none of workarounds have worked out.

@SUPERCILEX
Copy link
Collaborator

I'd like to, but I haven't come up with a good solution yet. The problem is that we want full parallelism across app IDs while supporting synchronous access to the same app ID across projects, but we can't truly know the app ID until after task creation which means we can't group the tasks into app ID buckets.

In terms of workarounds, this means you need to finalize the app ID before GPP reads it. I'm not sure what your specific case looks like, but if you can fully specify your different app IDs in the productFlavors, that should fix things.

In terms of proper solutions, I did come up with one idea that would maintain our desired functionality. The main problems is that it vastly increases complexity. The gist is this:

  • Create a single global build service that holds a lazily initialized, thread safe cache of publishers and edit managers keyed by the app ID
  • Pass in the app ID property to every task and have the task ask the build service for a publisher using that app ID
    • Tasks will also pass in their project ID, allowing us to track the source of the modification
  • Each project will have a finalizer task that asks the build service to commit the edit for their app ID
    • The project ID tracking will act as a semaphore, meaning the build service will only perform the actual commit if it has received a commit request from each project that made modifications to the edit

I basically need to think about how to guarantee correctness of that last step, but haven't prioritized it.

@Legion2
Copy link

Legion2 commented Feb 4, 2022

Our use case is, that we need to migrate to another app id, but we want to publish to both (new and old) app id during the migration period. Is this currently possible?

@yital9
Copy link

yital9 commented Feb 4, 2022

Yes, we specify the applicationId not only in productFlavors, but also customize them in the following way

android {
   ...
   applicationVariants.all {
       if (name.contains("foo", true)) {
           (mergedFlavor as MergedFlavor).applicationId = "$applicationId.foo"
       }
   }
}

It'd be impossible for us to use only productFlavors, because historically we have such customized app ids, that could not be achieved only with productFlavors.

I thought a bit about a crashlytics plugin, that works fine in this situation. GMS has a static google-services.json file, where the package_name is also defined. So they can match somehow this information between firebase project and local flavor with our customized applicationId.

@tadfisher
Copy link

Have you tried beforeVariants instead of onVariants?

@yital9
Copy link

yital9 commented Feb 8, 2022

A variant from beforeVariants hasn't an applicationId property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior feature:other Involves a feature that doesn't fit in existing categories
Projects
None yet
Development

No branches or pull requests

6 participants