diff --git a/README.md b/README.md index db194ac..c06692f 100644 --- a/README.md +++ b/README.md @@ -19,20 +19,21 @@ Enables Jenkins to manage and upload Android app files (AAB or APK) to Google Pl - Staged rollout of apps to any release track - Assigning release notes to uploaded files, for various languages - Changing the Jenkins build result to failed if the configuration is bad, or uploading or moving app files fails for some reason -- Every configuration field supports variable and [token](https://wiki.jenkins.io/display/JENKINS/Token+Macro+Plugin) expansion, allowing release notes to be dynamically generated, for example -- Integration with the [Google OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/Google+OAuth+Plugin), so that Google Play credentials can be entered once globally, stored securely, and shared between jobs +- Every configuration field supports variable and [token][plugin-token-macro] expansion, allowing release notes to be dynamically generated, for example +- Integration with the [Google OAuth Credentials Plugin][plugin-google-oauth], so that Google Play credentials can be entered once globally, stored securely, and shared between jobs - Multiple Google Play accounts are also supported via this mechanism ## Requirements ### Jenkins -Jenkins [version 2.138.4](https://jenkins.io/changelog-stable#v2.138.4) or newer is required. +Jenkins [version 2.138.4][lts-changelog] or newer is required. ### Google Play publisher account -For the initial setup only, you must have access to the Google account which owns the [Google Play publisher account](https://developer.android.com/distribute/googleplay/start.html). +For the initial setup only, you must have access to the Google account which owns the [Google Play publisher account][gp-docs-distribute]. This is required to enable API access from Jenkins to your Google Play account. -Note that having admin access is not enough; you need the account owner. You can see who the account owner is under [Settings → User accounts & rights](https://play.google.com/apps/publish/#AdminPlace) in the Google Play developer console. +Note that having admin access is not enough; you need the account owner. +You can see who the account owner is under [Settings → User accounts & rights][gp-console-admin] in the Google Play developer console. ### Please note - Any APKs uploaded will be published by Google Play immediately; they will not be held in a draft or pending state @@ -40,18 +41,16 @@ Note that having admin access is not enough; you need the account owner. You can ## Setup ### One-time: Set up Google Play credentials -The following initial setup process is demonstrated in this video: -[https://www.youtube.com/watch?v=txdPSJF94RM](https://www.youtube.com/watch?v=txdPSJF94RM&list=PLhF0STyfNdUk1R3taEmgFR30yzp41yuRK&index=1) (note that Google has changed the Google API Console (at least twice) since this video was recorded; steps 3–13 in the "Create Google service account" section below have the updated info) +The following initial setup process is demonstrated in this video: [https://www.youtube.com/watch?v=txdPSJF94RM][demo-video-creds] (note that Google has changed the Google API Console (at least twice) since this video was recorded; steps 3–13 in the "Create Google service account" section below have the updated info) #### Install plugin Install this plugin via the Jenkins plugin manager. -Or if installing the plugin via other means, ensure that the -prerequisite [Google OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/Google+OAuth+Plugin), [Token Macro Plugin](https://wiki.jenkins.io/display/JENKINS/Token+Macro+Plugin) and their dependencies are also installed. +Or if installing the plugin via other means, ensure that the prerequisite [Google OAuth Credentials Plugin][plugin-google-oauth], [Token Macro Plugin][plugin-token-macro] and their dependencies are also installed. #### Create Google service account To enable automated access to your Google Play account, you must create a service account: -1. Sign in to the [Google Play developer console](https://play.google.com/apps/publish/) as the account owner +1. Sign in to the [Google Play developer console][gp-console] as the account owner 2. Select Settings → Developer account → API access 3. Under Service Accounts, click "Create Service Account" 4. Follow the link to the Google API Console @@ -67,34 +66,53 @@ To enable automated access to your Google Play account, you must create a servic 14. You can now close the page #### Assign permissions to the service account -1. Return to the Google Play developer console page -2. Click "Done" on the dialog -3. Note that the service account has associated with the Google Play publisher account - 1. If it hasn't, follow these additional steps before continuing: - 2. Click "Users & permissions" in the menu - 3. Click "Invite new user" - 4. Paste in the email address you copied above - 5. Continue from step 5 +1. Return to the Google Play developer console page +2. Click "Done" on the dialog +3. Note that the service account has been associated with the Google Play publisher account + If it hasn't, follow these additional steps before continuing: + 1. Click "Users & permissions" in the menu + 2. Click "Invite new user" + 3. Paste in the email address you copied above + 4. Continue from step 5 4. Click the "Grant access" button for the account (e.g. "jenkins@api-xxxxxxxxx-xxxxx-xxxx.iam.gserviceaccount.com") 5. Ensure that at least the following permissions are enabled: - **View app information** — this is required for the plugin to function - **Manage production releases** — optional, if you want to upload APKs to production - - **Manage testing track releases** — if you want to upload APKs to alpha, beta, or internal + - **Manage testing track releases** — if you want to upload APKs to alpha, beta, or internal 6. Click "Add user" (or "Send invitation", as appropriate) 7. You can now log out of the Google Play publisher account -#### Add the service account credentials to Jenkins: +#### Add the service account credentials to Jenkins +##### Manually 1. Navigate to your Jenkins instance -2. Select "Credentials" from the Jenkins sidebar +2. Select "Credentials" from the Jenkins sidebar, at the top-level, or from within the folder where the credential should live 3. Choose a credentials domain and click "Add Credentials" 4. From the "Kind" drop-down, choose "Google Service Account from private key" -5. Enter a name for the credential — the actual value is not important +5. Enter a meaningful name for the credential, as you'll need to select it during build configuration, or enter it into your Pipeline configuration 6. Choose the "JSON key" type 7. Upload the .json file that was downloaded by the Google API Console -8. Enter a meaningful name, as you'll need to select it during build configuration, or enter it into your Pipeline configuration -9. Click "OK" to create the credential +8. Click "OK" to create the credential + +##### Using Configuration as Code +If you're using the [Configuration as Code plugin][plugin-jcasc] to set up your credentials automatically, you can do something like this, e.g.: +```yaml +credentials: + system: + domainCredentials: + - credentials: + - googleRobotPrivateKey: + projectId: 'Google Play' + serviceAccountConfig: + json: + # Optional + filename: 'my-gp-account.json' + # The contents of your .json file from Google Play, encoded as base 64, e.g.: + # $ cat api-xxxxxxxxx-xxxxx-xxxx.json | base64 - + # You can also provide an environment variable with the same content, to avoid having it in this file + secretJsonKey: 'eyJjbGllbnRfZW1haWwiOiJqZW5raW5z […]' +``` -Jenkins now has the required credentials and permissions in order to publish to Google Play. +Whether done manually or automatically, Jenkins now has the required credentials and permissions in order to publish to Google Play. Once you've set up a job (see the next section) and confirmed that uploading works, either delete the downloaded JSON file or ensure that it's stored somewhere secure. @@ -102,7 +120,7 @@ Once you've set up a job (see the next section) and confirmed that uploading wor #### Freestyle job configuration ##### Uploading an APK The following job setup process is demonstrated in this video: -[https://www.youtube.com/watch?v=iu-bLY9-jkc](https://www.youtube.com/watch?v=iu-bLY9-jkc&list=PLhF0STyfNdUk1R3taEmgFR30yzp41yuRK&index=2) +[https://www.youtube.com/watch?v=iu-bLY9-jkc][demo-video-job] 1. Create a new free-style software project 2. Ensure, via whatever build steps you need, that the file(s) you want to upload will be available in the build's workspace @@ -115,15 +133,13 @@ The following job setup process is demonstrated in this video: - If nothing is entered, the default is `'**/build/outputs/**/*.aab, **/build/outputs/**/*.apk'` 6. Choose the track to which the APKs should be deployed - If nothing is entered, the default is `'production'` -7. Optionally specify a [rollout percentage](https://support.google.com/googleplay/android-developer/answer/3131213) +7. Optionally specify a [rollout percentage][gp-docs-rollout] - If nothing is entered, the default is to roll out to 100% of users 8. Optionally choose "Add language" to associate release notes with the uploaded APK(s) - You add entries for as many or as few of your supported language as you wish, but each language must already have been added to your app, under the "Store Listing" section in the Google Play Developer Console. ###### APK expansion files -You can optionally add up to two [expansion -files](https://developer.android.com/google/play/expansion-files.html) (main + patch) -for each APK being uploaded. +You can optionally add up to two [expansion files][gp-docs-expansions] (main + patch) for each APK being uploaded. A list of expansion files can be specified in the same way as APKs, though note that they must be named in the format `[main|patch]...obb`. @@ -141,9 +157,9 @@ Under the "Build" section of the job configuration, add the "Move Android apps t You can tell Jenkins **which** version codes should be moved by either entering the values directly, or by providing AAB or APK files, from which the plugin will read the application ID and version codes for you. #### Pipeline job configuration -As of version 1.5, this plugin supports the [Pipeline Plugin](https://wiki.jenkins.io/display/JENKINS/Pipeline+Plugin) syntax. +As of version 1.5, this plugin supports the [Pipeline Plugin][plugin-pipeline] syntax. -You can generate the required Pipeline syntax via the [Snippet Generator](https://jenkins.io/blog/2016/05/31/pipeline-snippetizer/), but some examples follow. +You can generate the required Pipeline syntax via the [Snippet Generator][snippets-blog], but some examples follow. Note that you should avoid using these steps in a `parallel` block, as the Google Play API only allows one concurrent "edit session" to be open at a time. @@ -232,7 +248,7 @@ In addition, version 3.0 introduced the default values shown in the tables above Error messages from the plugin (many of which come directly from the Google Play API) should generally be self-explanatory. If you're having trouble getting a certain config to work, try uploading the same APKs manually to Google Play. There you'll likely see the reason for failure, e.g. a version code conflict or similar. -Otherwise, please check the [existing bug reports][jira], and [file a new bug report][report] with details, including the build console log output, if necessary. +Otherwise, please check the [existing bug reports][issues-existing], and [file a new bug report][issues-report] with details, including the build console log output, if necessary. Some known error messages and their solutions are shown below: @@ -246,7 +262,7 @@ Unfortunately, the Google Play API sometimes is not particularly reliable, and w In these cases you can try running your build again, or wait a few hours before retrying, if the problem persists. -Please also consider [contacting Google Play Developer Support](https://support.google.com/googleplay/android-developer/contact/publishing?extra.IssueType=submitting&hl=en&ec=publish&cfsi=publish_cf&cfnti=escalationflow.email&cft=3&rd=1) to help make them aware that people use the Google Play API, and that it should preferably work in a reliable manner. +Please also consider [contacting Google Play Developer Support][gp-support-form] to help make them aware that people use the Google Play API, and that it should preferably work in a reliable manner. This plugin already recognises some temporary Google Play API server problems and works around them; more workarounds may be added in future, e.g. automatically retrying when a generic server error is encountered. @@ -259,7 +275,7 @@ Ensure that the time is correctly synchronised on the Jenkins master and build a #### java.net.SocketTimeoutException: connect timed out This likely means your build machine is behind an HTTP proxy. -In this case, you should set up Jenkins as documented on the [JenkinsBehindProxy](https://wiki.jenkins.io/display/JENKINS/JenkinsBehindProxy#JenkinsBehindProxy-HowJenkinshandlesProxyServers) page. +In this case, you should set up Jenkins as documented on the [JenkinsBehindProxy][jenkins-behind-proxy] page. This plugin only makes secure (HTTPS) requests, so you need to make sure that the `-Dhttps.proxyHost=` and `-Dhttps.proxyPort=` Java properties are set when starting Jenkins. Add the appropriate http versions of those flags too, if unsecured HTTP requests also need to go through the proxy. @@ -276,7 +292,7 @@ If the plugin did allow this and you were to attempt to upload, say three, compl The best practice in this case would be to have one job that builds the different flavours (i.e. the APKs with different application IDs) and then, if the build is successful, it would archive the APKs and start multiple "downstream" Jenkins builds which individually publish each of the applications. This can be achieved, for example, with the Parameterized Trigger Plugin and the Copy Artifacts Plugin, i.e. the "upload" job could be generic, and would receive the APK information via parameter. -Alternatively, if you have version 1.5 of this plugin, and use the [Pipeline Plugin](https://wiki.jenkins.io/display/JENKINS/Pipeline+Plugin), you should be able to use the `androidApkUpload` step multiple times within a single build. +Alternatively, if you have version 1.5 of this plugin, and use the [Pipeline Plugin][plugin-pipeline], you should be able to use the `androidApkUpload` step multiple times within a single build. ## Android apps using this plugin There are several thousand people and companies using this plugin to upload their apps to Google Play, and it's always great to hear from people who are using the plugin. @@ -284,19 +300,35 @@ There are several thousand people and companies using this plugin to upload thei Feel free to let us know via the feedback section below, or open a Pull Request and add yourself and your apps here! :) ## Contributing -You can potentially get a sense of what's being worked on via the [tickets on the Jenkins Jira][jira]. +You can potentially get a sense of what's being worked on via the [tickets on the Jenkins Jira][issues-existing]. Please contact us (see below) before working on new features, as we may be working on something already, or at least be able to give advice or pointers. ## Feedback -If you have issues with the plugin that aren't solved via the Troubleshooting section, you can [file a bug report][report] with details, including the build console log output. +If you have issues with the plugin that aren't solved via the Troubleshooting section, you can [file a bug report][issues-report] with details, including the build console log output. You can also send us an email with your comments, suggestions, or feedback: - [@orrc](https://github.com/orrc) - [@jhansche](https://github.com/jhansche) ## Changelog -See [CHANGELOG.md](https://github.com/jenkinsci/google-play-android-publisher-plugin/blob/master/CHANGELOG.md). - -[jira]:https://issues.jenkins-ci.org/issues/?jql=project%20%3D%20JENKINS%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20component%20%3D%20google-play-android-publisher-plugin -[report]:http://jenkins.io/redirect/report-an-issue +See [CHANGELOG.md][changelog]. + +[changelog]:https://github.com/jenkinsci/google-play-android-publisher-plugin/blob/master/CHANGELOG.md +[demo-video-creds]:https://www.youtube.com/watch?v=txdPSJF94RM&list=PLhF0STyfNdUk1R3taEmgFR30yzp41yuRK&index=1 +[demo-video-job]:https://www.youtube.com/watch?v=iu-bLY9-jkc&list=PLhF0STyfNdUk1R3taEmgFR30yzp41yuRK&index=2 +[gp-console]:https://play.google.com/apps/publish/ +[gp-console-admin]:https://play.google.com/apps/publish/#AdminPlace +[gp-docs-distribute]:https://developer.android.com/distribute/best-practices/launch +[gp-docs-expansions]:https://developer.android.com/google/play/expansion-files.html +[gp-docs-rollout]:https://support.google.com/googleplay/android-developer/answer/6346149 +[gp-support-form]:https://support.google.com/googleplay/android-developer/contact/publishing?extra.IssueType=submitting&hl=en&ec=publish&cfsi=publish_cf&cfnti=escalationflow.email&cft=3&rd=1 +[issues-existing]:https://issues.jenkins-ci.org/issues/?jql=project%20%3D%20JENKINS%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20component%20%3D%20google-play-android-publisher-plugin +[issues-report]:http://jenkins.io/redirect/report-an-issue +[jenkins-behind-proxy]:https://wiki.jenkins.io/display/JENKINS/JenkinsBehindProxy#JenkinsBehindProxy-HowJenkinshandlesProxyServers +[lts-changelog]:https://jenkins.io/changelog-stable#v2.138.4 +[plugin-google-oauth]:https://plugins.jenkins.io/google-oauth-plugin +[plugin-jcasc]:https://plugins.jenkins.io/configuration-as-code +[plugin-token-macro]:https://plugins.jenkins.io/token-macro +[plugin-pipeline]:https://plugins.jenkins.io/workflow-aggregator +[snippets-blog]:https://jenkins.io/blog/2016/05/31/pipeline-snippetizer/