A Github action to upload abb/apk and build metadata artifacts to the Google Play Console.
Specifically designed for Unity Game Engine builds, but can be used for any Android app.
Important
You must also have manually uploaded an initial version of your app to the Google Play Console to create the app record before using this action.
Tip
This example assumes you are using google-github-actions/auth to authenticate to Google Cloud via Workload Identity Federation with a Service Account. Adjust accordingly if you are using a different authentication method.
It is possible to pass your own service account credentials file path via the service-account-credentials input or GOOGLE_APPLICATION_CREDENTIALS environment variable instead of using google-github-actions/auth.
Warning
This action requires Java 21 or higher to run. Make sure to set up Java in your workflow before using this action.
You can use the actions/setup-java action to set up Java.
jobs:
build-and-publish:
permissions:
contents: read
id-token: write # required for google-github-actions/auth
steps:
# ... unity build steps ...
- uses: google-github-actions/auth@v3
id: google-auth
with:
service_account: [email protected]
workload_identity_provider: projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21
- uses: RageAgainstThePixel/upload-google-play-console@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }} # Required
service-account-credentials: ${{ steps.google-auth.outputs.credentials_file_path }} # Required if GOOGLE_APPLICATION_CREDENTIALS is not set in the environment
release-directory: path/to/build/folder # Required, path to the build directory that contains the apks/aabs to upload
release-name: 1 (1.0.0) # Optional, defaults to reading manifest data (version code and version string)
track: internal # Optional, defaults to 'internal'
status: completed # Optional, Must be one of `draft`, `inProgress`, `completed`, or `halted`.
user-fraction: 0.1 # Optional, Fraction of users who are eligible for a staged release. 0 < fraction < 1. Can only be set when status is `inProgress` or `halted`.
in-app-update-priority: 5 # Optional, In-app update priority of the release. Must be between 0 and 5.
metadata: | # Optional, Json string or path to a JSON file that contains additional localized store listing metadata
{
"releaseNotes": {
"language": "en-US",
"text": "Bug fixes and performance improvements."
}
}
changes-not-sent-for-review: 'false' # Optional, don't send the changes for review automatically| name | description | required |
|---|---|---|
github-token |
GitHub token for authentication. Use either secrets.GITHUB_TOKEN, github.token or a personal access token. |
true |
service-account-credentials |
The service account credentials file path. | Required if GOOGLE_APPLICATION_CREDENTIALS is not set in the environment. |
release-directory |
The directory containing the APKs/AABs to upload. | true |
release-name |
The name of the release. | Defaults to reading manifest data (version code and version string). |
track |
The track to upload the app to (e.g., internal, alpha, beta, production). |
Defaults to internal. |
status |
The status of the release. Must be one of draft, inProgress, completed, or halted. |
Defaults to completed. |
user-fraction |
Fraction of users who are eligible for a staged release. 0 < fraction < 1. Can only be set when status is inProgress or halted. |
false |
in-app-update-priority |
In-app update priority of the release. All newly added APKs in the release will be considered at this priority. Can take values in the range [0, 5], with 5 the highest priority. Defaults to 0. in-app-update-priority can not be updated once the release is rolled out. See https://developer.android.com/guide/playcore/in-app-updates. |
false |
metadata |
Json string or path to a JSON file that contains additional localized store listing metadata. see Spec | Defaults to 0. |
changes-not-sent-for-review |
When a rejection happens, the parameter will make sure that the changes in this edit won't be reviewed until they are explicitly sent for review from within the Google Play Console UI. These changes will be added to any other changes that are not yet sent for review. | Defaults to false |
Additional Resources:
-
Create a Google Cloud Project
-
Enable the Google Play Android Developer API for your project in the Google Cloud Console
-
Configure GitHub authentication to Google Cloud via a Workload Identity Federation through a Service Account
- Create or take note of an existing Google Cloud Service Account
gcloud iam service-accounts create "${SERVICE_ACCOUNT_NAME}" --project="${PROJECT_ID}"
- Create a Workload Identity Pool
gcloud iam workload-identity-pools create "${POOL_NAME}" \ --project="${PROJECT_ID}" \ --location="global" \ --display-name="${POOL_DISPLAY_NAME}"
- Get the full ID of the Workload Identity Pool
gcloud iam workload-identity-pools describe "${POOL_NAME}" \ --project="${PROJECT_ID}" \ --location="global" \ --format="value(name)"
- Create a Workload Identity Provider in the Pool
gcloud iam workload-identity-pools providers create-oidc "${PROVIDER_NAME}" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="${POOL_NAME}" \ --display-name="${PROVIDER_DISPLAY_NAME}" \ --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \ --attribute-condition="attribute.repository=='${GITHUB_REPOSITORY}'" \ --issuer-uri="https://token.actions.githubusercontent.com"
- Allow authentications from the Workload Identity Pool to your Google Cloud Service Account
gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT_EMAIL}" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_FULL_ID}/attribute.repository/${GITHUB_REPOSITORY}"
- Extract the Workload Identity Provider resource name
gcloud iam workload-identity-pools providers describe "${PROVIDER_NAME}" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="${POOL_NAME}" \ --format="value(name)"
- Go to the Users & Permissions page on the Google Play Console.
- Click Invite new users
- Put an email address for your service account in the email address field
- Grant the service account Release Manager permissions
- Add additional permissions as needed
- Click Invite User
-
Add
id-token: writepermission to your workflow job so that thegoogle-github-actions/authaction can mint identity tokens
The metadata input can be either a JSON string or a path to a JSON file that follows the schema defined in metadata.schema.json. You can load the schema into your editor or validator to get auto-complete, linting, and type safety for
listing, releaseNotes, countryTargeting, and images objects.
Tip
Each of the top level properties are optional. You can include only the sections you need or all of them.
listing and releaseNotes both accept a single object or an array of objects, so you can target multiple locales in one file.
At a high level the schema supports the following payloads:
listing: one or more localized store listings. Each listing describes the metadata fields that mirror the Android Publisher Listing resource includinglanguage,title,shortDescription,fullDescription, optionalvideo, and animagesarray.releaseNotes: localized release notes following the LocalizedText structure.countryTargeting: optional country targeting options withcountries(ISO 3166-1 alpha-2 codes) andincludeRestOfWorldflags.images: one or more images to upload that follow the Android Publisher Image resource structure includinglanguage,type, andpathto a local asset.- The supported
typevalues (from the Android Publisher API) are:phoneScreenshotssevenInchScreenshotstenInchScreenshotstvScreenshotswearScreenshotsiconfeatureGraphictvBanner
- The supported
Example snippet that shows how the metadata payload might be composed:
{
"listing": {
"language": "en-US",
"title": "Space Explorer",
"shortDescription": "Blast through the cosmos.",
"fullDescription": "Space Explorer is a fast-paced shooter...",
},
"releaseNotes": [
{
"language": "en-US",
"text": "Bug fixes and polish."
}
],
"countryTargeting": {
"countries": ["US", "CA"],
"includeRestOfWorld": false
},
"images": [
{
"language": "en-US",
"type": "phoneScreenshots",
"path": "path/to/images/phone-1.png"
},
{
"language": "en-US",
"type": "icon",
"path": "path/to/images/icon.png"
}
]
}