This actions allows us to run Unity Cloud Build jobs from GitHub on pull request and merge to main branch. The action uses the Unity Cloud Build REST API to kick off a build and then polls it until the job is complete. If the job fails, the action will return an exit code 1. If it succeeds it will return an exit code 0.
For pull requests, the action will create a new build target in Unity Cloud Build first before kicking off a build. We have to do this because Unity Cloud Build does not support overridding the branch name at runtime. So if we didn't do this, all the build would be run against the main branch and not the changes in the PR branch - not ideal for a pull request.
If a PR has further changes to pushed to it after initially being opened, the action will re-use the previous setup PR build target. Doing this allows us to make use of Unity Cloud Build's build target caching mechanism which speeds up subsequent builds slightly.
Use the following commands to extract all the information required from UnityCloudBuild=st
- Run with just
org_id, to get a list of projects & their build targetspoetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG
- Run with
org_idandproject_idto get a list of build targetspoetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName
- Add
primary_build_targetandgithub_branch_refto get a list of existing builds (for use withexisting_build_number)poetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName --primary_build_target=mac --github_branch_ref=refs/tags/v1.2.3 --allow_new_target=false- This also works with just
mainorv1.2.3 poetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName --primary_build_target=mac --github_branch_ref=main --allow_new_target=false
- Add
existing_build_numberto get meta of an existing build's resultpoetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName --primary_build_target=mac --github_branch_ref=refs/tags/v1.2.3 --existing_build_number=1
- Add
download_binary=trueto go withexisting_build_numberto download the artifact to$GITHUB_WORKSPACEpoetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName --primary_build_target=mac --github_branch_ref=refs/tags/v1.2.3 --existing_build_number=1 --download_binary=true
- Run with
org_id,project_id,github_branch_refto start (and wait for) a new build. This will create a new build target if it doesn't existpoetry run python -m action --api_key=YOUR_KEY --org_id=YOUR_ORG --project_id=YourProjectName --github_branch_ref=v1.2.3
- Don't hesitate to use Unity's own unity-cloud-build-api checker; https://build-api.cloud.unity3d.com/docs/1.0.0/index.html
- The action will list out all projectids in an organisation, and if that is successfull, all build targets for a projectid. Check the logs!
403 User not authorisedis a common error for when organisationids or projectids are incorrect.API_KEY missingerror fromaction.pyoften means you have provided a secret which doesn't exist, or is empty.
The action requires a series of inputs from the workflow file. These are then passed to the action as environment variables that the action then picks up and utilises to make relevant calls to Unity Cloud Build.
Required- The Unity Cloud Build API key. This can be found in the Unity Dashboard, under
Dev Ops -> Build Automation -> Settings - See https://build-api.cloud.unity3d.com/docs/1.0.0/index.html
- Store this API key as a
github action secretand then use in the github action via${{ secrets.NAME_OF_YOUR_SECRET }}
Required- The Unity Cloud Build organisation ID
- this is can be found by browsing your organisations and finding the organisation name in any links/urls. (expected to be a string)
- Organisation id's will fail if they have spaces, and UnityCloudBuild expects spaces to be replaced with dashes; https://forum.unity.com/threads/ucb-api-error-not-authorized-user-does-not-have-correct-permissions-to-perform-this-operation.730976/
Required- The Unity Cloud Build project ID
- Unity will fail if the project id has spaces in it, these should be replaced with dashes
My Projecthas a project id ofmy-project
Required- The Unity Cloud Build primary build target - this is build target name. (Find this via urls, expected to be without spaces)
- `Optional
- The frequency with which to query Unity Cloud Build jobs - the default is
60seconds.
optional- default:
false - output:
env.ARTIFACT_FILENAMEis set to the filename of the local file after download - output:
env.ARTIFACT_FILEPATHis set to the full file path of the local file after download - Whether or not to download the built binary to your
GITHUB_WORKSPACE
optional- default:
false - output:
env.SHARE_URLis set to the sharing url - Tell UnityCloudBuild to generate a sharing url to allow easy installation
optional- default:
-1 - Instead of starting a new build, if this is >=0 the action will use an existing build number and still execute downloading artifacts, creating share urls etc
Please find an example usage below for reference.
jobs:
run-unity-cloud-build-condense-live-android:
name: Run Unity Cloud Build - Condense Live (Android)
runs-on: ubuntu-22.04
outputs:
artifact_filepath: ${{ steps.rununitycloudbuildaction.ARTIFACT_FILEPATH }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python 3
uses: actions/setup-python@v4
with:
python-version: "3.10.4"
architecture: "x64"
- name: Export poetry.lock for docker build
run: |
python -m pip install --upgrade pip
pip install poetry==1.1.12
cd .github/actions/unity-cloud-build/ && poetry export -f requirements.txt > requirements.txt
- name: Run Unity Cloud Build Action
uses: ./.github/actions/unity-cloud-build
id: rununitycloudbuildaction
with:
unity_cloud_build_api_key: ${{ secrets.UNITY_CLOUD_BUILD_API_KEY }}
unity_cloud_build_org_id: yourorganisation
unity_cloud_build_project_id: yourgame
unity_cloud_build_polling_interval: 60
unity_cloud_build_primary_target: yourgame-ios-default
unity_cloud_build_download_binary: false
unity_cloud_build_create_share: true
unity_cloud_build_github_head_ref: ${{ github.ref }}
This action outputs several env vars to relay meta back out to the workflow.
These are also written to GITHUB_OUTPUT for use via needs.job.output and steps.step.outputs.xxx
ARTIFACT_FILEPATHlocal path to Unity Cloud Build artifact. Generated ifunity_cloud_build_download_binaryis trueARTIFACT_FILENAMEjust the filename of the Unity Cloud Build artifact. Generated ifunity_cloud_build_download_binaryis trueSHARE_URLurl to sharing url. Generated ifunity_cloud_build_create_shareis true
- Your
api_keycan be found from UnityCloud's dashboard,DevOpsSettingsApi Settings- Should be a hexidecimal key
- This is different to an Adminstration
Service Accountkey.
- Your
org_idis a string (spaces get converted to underscores)
python3 pip install poetrypip3 install poetrypoetry installexport GITHUB_WORKSPACE=./Workspace- Build main on Android target/configuration
poetry run python -m action --api_key=fffff --org_id=YOURORGID --project_id=PROJECT_ID --primary_build_target=Android --github_branch_ref=refs/head/main
- List all projects & their build targets
poetry run python -m action --api_key=fffff --org_id=YOURORGID
- List build targets for a specific project
poetry run python -m action --api_key=fffff --org_id=YOURORGID --project_id=PROJECT_ID
- Download the artifact from an existing build
poetry run python -m action --api_key=fffff --org_id=YOURORGID --project_id=PROJECT_ID --build_target_id=Android --existing_build_number=123 --download_binary=true
- Get a share url from an existing build
poetry run python -m action --api_key=fffff --org_id=YOURORGID --project_id=PROJECT_ID --build_target_id=Android --existing_build_number=123 --create_share_url=true
- Start a build on another branch; assuming the base target isn't configured to it already
poetry run python -m action --api_key=fffff --org_id=YOURORGID --project_id=PROJECT_ID --primary_build_target=Android --github_branch_ref=MyTestBranch
Uploading ios .ipa builds (todo: how to configure build to generate .ipa) to testflight is a simple process via xcode's command line tools.
This can be implemented in a workflow with just a single step
- The step needs to run on a macos runner (eg.
macos-latest)
- name: Upload .ipa to TestFlight
run: xcrun altool --upload-app --file ${IOS_IPA_FILENAME} --type ios --bundle-id ${{ env.IosBundleId }} --bundle-version ${{ env.IosBundleVersion }} --bundle-short-version-string ${{ env.IosBundleShortVersionString }} --apiKey ${APPSTORECONNECT_AUTH_KEY} --apiIssuer ${APPSTORECONNECT_AUTH_ISSUER}
IosBundleIdshould be the bundle id in appstoreconnect, eg.com.you.apptodo: does it need to be correct, or is it taken from ipa?IosBundleVersioncan be 0. AppStoreConnect correctly uses the bundle version in the ipaIosBundleShortVersionStringcan be 0. AppStoreConnect correctly uses the bundle version in the ipatodo: is this the build number?- Note; the
.p8contents should be stored in./private_keys/AuthKey_$APPSTORECONNECT_AUTH_KEY.p8(same filename as downloaded inkeyssection of appstore connecct
This works.
todo: document
This uses a CLI tool from unity
- https://github.com/Unity-Technologies/unity-gaming-services-cli/releases/ Based on these docs
- https://services.docs.unity.com/guides/ugs-cli/latest/general/samples/ci-cd-pipeline-usage/github-actions/
You can download a mac exe for testing locally (To get CLI correct)
A service account (and it's keyid and secret)is required, with the following roles (for that project)
- Game Server Hosting Allocations Admin
- Game Server Hosting API Editor
- Game Server Hosting API Manager
- Game Server Hosting API Viewer
- Unity Environments Viewer
gr: this one is NOT LISTED IN UNITY DOCSvery important!
- Generate
config.vdffile withsteamcmdhttps://developer.valvesoftware.com/wiki/SteamCMD - Encode to base64 and put in a secret
cat config/config.vdf | base64 > config.vdf.base64.txt
This repository contains a re-usable workflow; ./github/workflows/UnityCloudBuild.yml which will
- Trigger this action to do a Build
- Share a Sharing Url to slack if slack channel & bot auth key are provided
- Upload to testflight with appstoreconnect credentials
- Upload to oculus dev release channels