<p align="center">
</p>
<h1 align="center">
Gradle Play Publisher
</h1>
<p align="center">
<a href="https://circleci.com/gh/Triple-T/gradle-play-publisher" rel='nofollow' onclick='return false;'>
<img src="https://circleci.com/gh/Triple-T/gradle-play-publisher.svg?style=svg" />
</a>
<a href="https://plugins.gradle.org/plugin/com.github.triplet.play" rel='nofollow' onclick='return false;'>
<img src="https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/com/github/triplet/play/com.github.triplet.play.gradle.plugin/maven-metadata.xml.svg?label=Gradle%20Plugins%20Portal" />
</a>
</p>
Gradle Play Publisher is Android's unofficial release automation Gradle Plugin. It can do anything
from building, uploading, and then promoting your App Bundle or APK to publishing app listings and
other metadata.
## Table of contents
1. [Quickstart guide](#quickstart-guide)
1. [Prerequisites](#prerequisites)
1. [Initial Play Store upload](#initial-play-store-upload)
1. [Signing configuration](#signing-configuration)
1. [Service Account](#service-account)
1. [Basic setup](#basic-setup)
1. [Installation](#installation)
1. [Authenticating Gradle Play Publisher](#authenticating-gradle-play-publisher)
1. [Task organization](#task-organization)
1. [Managing artifacts](#managing-artifacts)
1. [Common configuration](#common-configuration)
1. [Publishing an App Bundle](#publishing-an-app-bundle)
1. [Publishing APKs](#publishing-apks)
1. [Uploading an Internal Sharing artifact](#uploading-an-internal-sharing-artifact)
1. [Promoting artifacts](#promoting-artifacts)
1. [Handling version conflicts](#handling-version-conflicts)
1. [Managing Play Store metadata](#managing-play-store-metadata)
1. [Quickstart](#quickstart)
1. [Directory structure](#directory-structure)
1. [Publishing listings](#publishing-listings)
1. [Publishing in-app products](#publishing-in-app-products)
1. [Working with product flavors](#working-with-product-flavors)
1. [Disabling publishing](#disabling-publishing)
1. [Combining artifacts into a single release](#combining-artifacts-into-a-single-release)
1. [Using multiple Service Accounts](#using-multiple-service-accounts)
1. [Advanced topics](#advanced-topics)
1. [Using CLI options](#using-cli-options)
1. [Encrypting Service Account keys](#encrypting-service-account-keys)
1. [Using HTTPS proxies](#using-https-proxies)
## Quickstart guide
1. Upload the first version of your APK or App Bundle using the
[Google Play Console](https://play.google.com/apps/publish)
1. [Create a Google Play Service Account](#service-account)
1. [Sign your release builds](https://developer.android.com/studio/publish/app-signing#gradle-sign)
with a valid `signingConfig`
1. [Add and apply the plugin](#installation)
1. [Authenticate GPP](#authenticating-gradle-play-publisher)
## Prerequisites
### Initial Play Store upload
The first APK or App Bundle needs to be uploaded via the Google Play Console because registering the
app with the Play Store cannot be done using the Play Developer API. For all subsequent uploads and
changes, GPP may be used.
### Signing configuration
To successfully upload apps to the Play Store, they must be signed with your developer key. Make
sure you have
[a valid signing configuration](https://developer.android.com/studio/publish/app-signing#gradle-sign).
### Service Account
To use GPP, you must create a service account with access to the Play Developer API:
1. If you don't already have one, create a GCP project for your app(s)
1. Create a
[service account key](https://console.cloud.google.com/apis/credentials/serviceaccountkey)
1. Select `New service account`
1. Give it a name, but don't select any roles
1. Leave JSON checked
1. If it asks for roles, continue without selecting any
1. Move the downloaded JSON credentials into your project and
[tell GPP about it](#authenticating-gradle-play-publisher)
1. [Link your developer account](https://play.google.com/apps/publish#ApiAccessPlace) to the GCP
project in which you created the service account
1. Give your service account
[permissions to publish apps](https://play.google.com/apps/publish#AdminPlace) on your behalf
1. Click `Invite new user`
1. Copypasta the service account email (you can find it in the JSON credentials)
1. Don't touch the roles
1. Specify which apps the service account should have access to:
## Basic setup
### Installation
Apply the plugin to each individual `com.android.application` module where you want to use GPP
through the `plugins {}` DSL:
<details open><summary>Kotlin</summary>
```kt
plugins {
id("com.android.application")
id("com.github.triplet.play") version "2.4.1"
}
```
</details>
<details><summary>Groovy</summary>
```groovy
plugins {
id 'com.android.application'
id 'com.github.triplet.play' version '2.4.1'
}
```
</details>
#### Snapshot builds
If you're prepared to cut yourself on the bleeding edge of GPP development, snapshot builds are
available from
[Sonatype's `snapshots` repository](https://oss.sonatype.org/content/repositories/snapshots/com/github/triplet/gradle/play-publisher/):
<details open><summary>Kotlin</summary>
```kt
buildscript {
repositories {
// ...
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
dependencies {
// ...
classpath("com.github.triplet.gradle:play-publisher:2.5.0-SNAPSHOT")
}
}
```
</details>
<details><summary>Groovy</summary>
```groovy
buildscript {
repositories {
// ...
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
}
dependencies {
// ...
classpath 'com.github.triplet.gradle:play-publisher:2.5.0-SNAPSHOT'
}
}
```
</details>
### Authenticating Gradle Play Publisher
After you've gone through the [Service Account setup](#service-account), you should have a JSON file
with your private key. Add a `play` block alongside your `android` one with the file's location:
```kt
android { ... }
play {
serviceAccountCredentials = file("your-key.json")
}
```
#### Using a PKCS12 key instead
```kt
play {
serviceAccountEmail = "service-account-name@project-id.iam.gserviceaccount.com"
serviceAccountCredentials = file("your-key.p12")
}
```
## Task organization
GPP follows the Android Gradle Plugin's naming convention: `[action][Variant][Thing]`. For example,
`publishPaidReleaseBundle` will be generated if have a `paid` product flavor.
Lifecycle tasks to publish multiple product flavors at once are also available. For example,
`publishBundle` publishes all variants.
To find available tasks, run `./gradlew tasks --group publishing` and use
`./gradlew help --task [task]` where `task` is something like `publishBundle` to get more detailed
documentation for a specific task.
> Note: if a task conflict occurs, say with the `maven-publish` plugin for example, be sure to apply
> the GPP plugin *last*. Conflicting tasks will then be prefixed with `gpp` (ex: `publish` ->
> `gppPublish`).
## Managing artifacts
GPP supports uploading both the App Bundle and APK. Once uploaded, GPP also supports promoting those
artifacts to different tracks.
### Common configuration
Several options are available to customize how your artifacts are published:
* `track` is the target stage for an artifact, i.e. `internal`/`alpha`/`beta`/`production` or any
custom track
* Defaults to `internal`
* `releaseStatus` is the type of release, i.e. `completed`/`draft`/`inProgress`/`halted`
* Defaults to `completed`
* `userFraction` is the percentage of users who will receive a staged release
* Defaults to `0.1` aka 10%
* **Note:** the `userFraction` is only applicable where `releaseStatus=[inProgress/halted]`
Example configuration:
```kt
play {
// Overrides defaults