I’m currently building an app that targets both Android and iOS, and using Unity Cloud Build as a CI manager. Currently, I have one build profile each set up for iOS and Android, and in the iOS profile there’s a field for specifying a custom fastfile configuration, since Unity relies on fastlane to deploy to AppStoreConnect.
However, the Fastlane API suggests it also works with the Android platform and deploying to the Google Play Console, but there is no such option for it in the Android version of the Unity Cloud Build profile. It still builds the apps correctly which can be downloaded and uploaded to the Console manually, but I (and likely many others) would like the process to be automated as well.
Is this a feature that is planned for a future release of Unity Cloud Build, and if so, when?
Failing that, the best workaround I can think of is calling a shell script in the post-build script field, which in turn calls on Fastlane to run the lanes I want. How feasible is this? Is fastlane only installed in the iOS image of the cloud builder? Would I need the shell script to install/verify the existence of fastlane in order to execute the lanes I want to run?
I’ve been messing with this for a while. Used to have a ridiculously complicated bash script for this, until I realized that fastlane is installed, and you can easily use it in a bash script in the post build event. Now it’s literally a 4 line script (minus comments), here it is:
#!/bin/bash
# Passed in as environment variables from CI, you must get this from Google and put
# it in the environment variable PLAYSTORE_KEY in the Unity build config.
# $PLAYSTORE_KEY - The JSON file with the credentials for the Google Developer account
# You can also just hardcode your package name, e.g. com.candycrush.game or whatever here...
PACKAGE_NAME=$(cat "$WORKSPACE/build.json" | jq -j '.[].bundleid')
# Unity environment variables replace the "\n" signs from the private key with spaces for some reason,
# so we replaces spaces with "\n" signs again so it works properly.
KEY_WITH_NEWLINES=$(echo $PLAYSTORE_KEY | jq '.private_key |= sub(" (?!PRIVATE|KEY)"; "\n"; "g")' -c -j)
# You could also use shorter argument names here, but DO NOT use -e for --release-status, there's some error there where
# fastlane thinks -e should mean the -env option and fails.
# Also, you could put the "draft" and "internal" into environment variables if you want to never have to modify the script
# again and just control it with environment variables.
fastlane supply --package_name "$PACKAGE_NAME" --aab "$UNITY_PLAYER_PATH" --json_key_data "$KEY_WITH_NEWLINES" --release-status draft --track internal
So just put that in a “upload.sh” file, add it as the post build file in the build config. Get your google key in json format and put it in as the env variable “PLAYSTORE_KEY”. No additional fastlane configuration is needed, which was a pleasant surprise, it actually works with just the right parameters passed in.
Thanks so much for sharing that script @raudas ! We had been using firebase, but wanted to switch over to Google Play Console… this script worked right out of the box for that!
Thanks for this. Trying it out myself but getting this error:
7683: Executing Post-Build Script at scripts/upload.sh
7684: [07:03:12]: [33mSeems like launching fastlane takes a while - please run[0m
7685: [07:03:12]:
7686: [07:03:12]: [36m$ [sudo] gem cleanup[0m
7687: [07:03:12]:
7688: [07:03:12]: [33mto uninstall outdated gems and make fastlane launch faster[0m
7689: [07:03:12]: [33mAlternatively it's recommended to start using a Gemfile to lock your dependencies[0m
7690: [07:03:12]: [33mTo get started with a Gemfile, run[0m
7691: [07:03:12]:
7692: [07:03:12]: [36m$ bundle init[0m
7693: [07:03:12]: [36m$ echo 'gem "fastlane"' >> Gemfile[0m
7694: [07:03:12]: [36m$ bundle install[0m
7695: [07:03:12]:
7696: [07:03:12]: [33mAfter creating the Gemfile and Gemfile.lock, commit those files into version control[0m
7697: [07:03:12]: [33mGet started using a Gemfile for fastlane https://docs.fastlane.tools/getting-started/ios/setup/#use-a-gemfile[0m
7698: [07:03:26]: Sending anonymous analytics information
7699: [07:03:26]: Learn more at https://docs.fastlane.tools/#metrics
7700: [07:03:26]: No personal or sensitive data is sent.
7701: [07:03:26]: You can disable this by adding `opt_out_usage` at the top of your Fastfile
7702: [07:03:26]: [31mError setting value 'BUILD_PATH/p/.build/last/default-android/Default Android.apk' for option 'aab'[0m
7703: [31m
7704: [!] aab file is not an aab[0m
7705: #######################################################################
7706: # fastlane 2.204.3 is available. You are on 2.182.0.
7707: # You should use the latest version.
7708: # Please update using `gem install fastlane`.
7709: #######################################################################
7710: [32m2.204.3 Improvements[0m
7711: * [trainer][scan] identify skipped tests in `xcresult` and export to Junit format and output in scan (#19957) via Igor Makarov
7712: * [Fastlane.Swift] Swift fastlane upgrader #18933 (#19914) via Enrique Garcia
7713: * [pem][spaceship] update development push certificate type ID (#19879) via Igor Makarov
7714: * [snapshot] fix compile error on macCatalyst (#19917) via Philipp Arndt
7715: * [Fastlane.Swift] readPodspec: return map of [String: Any] (#19953) via Hais Deakin
7716: * [match] update :force_for_new_certificates option description (#19938) via Wolfgang Lutz
7717: [32m2.204.2 App Store Connect API is fixed - reverts local filtering[0m
7718: * Revert "[spaceship][deliver][pilot] temporarily fix finding app by filtering by bundle id locally (#19900)" (#19906) via Josh Holtz (@joshdholtz)
7719: Version `2.204.1` will be removed from RubyGems as the temporary fix is no longer needed
7720: [32m2.204.1 Temporary App Store Connect Fix[0m
7721: * [spaceship][deliver][pilot] temporarily fix finding app by filtering by bundle id locally (#19900) via Josh Holtz (@joshdholtz)
7722: [32mTo see all new releases, open https://github.com/fastlane/fastlane/releases[0m
7723: [32mPlease update using `gem install fastlane`[0m
7724: ! build of 'default-android' failed. Post-Build script exited with status 1. Aborting.
7725: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/build/build_handler.rb:104:in `compile'
7726: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/project.rb:129:in `call'
7727: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/project.rb:129:in `build_chain'
7728: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/project.rb:80:in `build'
7729: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/tasks/project.rb:288:in `call'
7730: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/tasks/project.rb:288:in `build_steps'
7731: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/tasks/project.rb:117:in `build'
7732: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
7733: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
7734: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
7735: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
7736: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/runner.rb:44:in `method_missing'
7737: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/runner.rb:25:in `block in method_missing'
7738: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/timing.rb:10:in `wrap'
7739: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/runner.rb:24:in `method_missing'
7740: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:29:in `run'
7741: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:126:in `run'
7742: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
7743: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
7744: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
7745: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/tasks/buildjobs.rb:120:in `buildscript'
7746: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
7747: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
7748: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
7749: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
7750: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/runner.rb:44:in `method_missing'
7751: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/runner.rb:25:in `block in method_missing'
7752: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/timing.rb:10:in `wrap'
7753: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/lib/bvr/thor/runner.rb:24:in `method_missing'
7754: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:29:in `run'
7755: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/command.rb:126:in `run'
7756: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
7757: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
7758: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
7759: /home/buildbot/.rvm/gems/ruby-2.4.2/gems/bvr-3.8.7.2.4.2/bin/bvr_runner:11:in `<main>'
7760: Publishing build 2 of 16767722914694/167929e7-f8c5-4349-b265-cffd612f9fd6 for target 'default-android'...
7761: Uploading extra_data/artifacts/icon.png
7762: ...done
7763: Uploading extra_data/build_report/files.json
7764: ...done
7765: Uploading extra_data/build_report/files.reflected.json ...done
7766: Uploading extra_data/build_report/steps.reflected.json ...done
7767: Uploading extra_data/build_report/strippingInfo.json
7768: ...done
7769: Uploading extra_data/build_report/summary.json
7770: ...done
7771: Uploading extra_data/build_report/summary.reflected.json
7772: ...done
7773: Uploading extra_data/build_report/v2.steps.json
7774: ...done
7775: Uploading Default Android.apk
7776: ...done
7777: Zipping cache files from Library
7778: done.
7779: publishing finished successfully.
7780: Build failed. Please check the log for further details.
7781: Using /home/buildbot/.rvm/gems/ruby-2.4.2
7782: postbuildsteps finished successfully
7783: postbuildstatus finished successfully.
7784: Attempting to return legacy license
7785: No legacy license to return. Exiting
7786: Finished: FAILURE
Another +1 @raudas , thanks for this tip with fastlane and jq.
One more thing I would add to the above post is disabling xtrace and verbose mode for it:
set +x
set +v
# the script
set -x
set -v
Without this, at least in the current incarnation of UCB, all of your raw secrets will be printed in plain text to the build log when xtrace mode prints them out after expansion.
For testflight, I haven’t experimented with fastlane, but we are able to use the xcode command line pretty easily for uploads:
if xcrun altool --upload-app -f $UNITY_PLAYER_PATH -u $APPLE_USERID -p $APPLE_PASSWORD --type ios; then
echo "Uploading to Testflight successful"
else
echo "Failed to upload to testflight"
fi```
Where the apple userid and password env vars are set to whichever appstoreconnect account you want to upload with.
Fastlane supply is only for google play. Fastlane has the deliver/appstore/upload_to_app_store action for testflight:
https://docs.fastlane.tools/actions/upload_to_app_store/
I’ve almost got things working, but I’m still getting stuck at:
“No local metadata, apks, aab, or track to promote were found, make sure to run fastlane supply init to setup supply”
When I try to put fastlane supply init in front of fastlane supply I get:
“[!] No authentication parameters were specified. These must be provided in order to authenticate with Google”
Looking at the fastlane docs it says that you have to run fastlane supply init from [your_project_folder]? Does anyone know how to do this in the UCB environment?
Didn’t you @raudas have to do something similar? Or did you work around this?
UPDATE
had a woopsie in my fastlane supply call. I had ‘-aab’ instead of ‘–aab’. This solved it for me
And thanks for the script!
hello
it’s seems not working for me … with all configurated, i’ve got an UCB error build when executing the bash file
[error] [!] Google Api Error: Invalid request - Invalid package name: null.
So why the script (bash file) can’t achieve to get the PACKAGE_NAME ?
PACKAGE_NAME=$(cat “$WORKSPACE/build.json” | jq -j ‘.[ ].bundleid’)