Skip to content

Unity Cloud Build #5220

Unity Cloud Build

Unity Cloud Build #5220

name: Unity Cloud Build
on:
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
- labeled
merge_group: {}
push:
branches:
- dev
workflow_dispatch:
inputs:
profile:
description: 'Select level of profiling'
required: true
default: 'none'
type: choice
options:
- none
- profile
- deep
clean_build:
description: 'Clean Build'
required: false
default: false
type: boolean
cache_strategy:
description: 'Select cache strategy'
required: true
default: 'library'
type: choice
options:
- none
- library
- workspace
- inherit
workflow_call:
inputs:
profile:
required: true
type: string
default: 'none'
clean_build:
required: true
default: true
type: boolean
cache_strategy:
required: true
default: 'library'
type: string
version:
required: true
type: string
sentry_enabled:
required: false
type: boolean
default: false
is_release_build:
type: boolean
required: false
default: false
install_source:
required: false
default: 'launcher'
type: string
tag_version:
type: string
required: false
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ inputs.install_source }}
cancel-in-progress: true
jobs:
prebuild:
name: Prebuild
runs-on: ubuntu-latest
timeout-minutes: 10
if: |
(github.ref == 'refs/heads/dev') ||
(github.ref == 'refs/heads/main') ||
(github.event_name == 'pull_request' && !github.event.pull_request.draft) ||
(github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'force-build') ||
(github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'clean-build') ||
(github.event_name == 'workflow_dispatch')
outputs:
commit_sha: ${{ steps.get_commit_sha.outputs.commit_sha }}
options: ${{ steps.get_options.outputs.options }}
version: ${{ github.event.inputs.version || inputs.version || steps.get_version.outputs.full_version }}
sentry_environment: ${{ steps.get_sentry.outputs.environment }}
sentry_upload_symbols: ${{ steps.get_sentry.outputs.upload_symbols }}
sentry_enabled: ${{ steps.get_sentry.outputs.sentry_enabled }}
clean_build: ${{ steps.set_defaults.outputs.clean_build }}
cache_strategy: ${{ steps.set_defaults.outputs.cache_strategy }}
install_source: ${{ steps.set_defaults.outputs.install_source }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get commit SHA
id: get_commit_sha
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
echo "commit_sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
else
echo "commit_sha=$GITHUB_SHA" >> $GITHUB_OUTPUT
fi
- name: Debug Commit SHA
run: |
echo "Ref from Pull Request: ${{ github.event.pull_request.head.sha }}"
echo "Full Commit from git rev-parse: $(git rev-parse $GITHUB_SHA)"
echo "HEAD Commit: $(git rev-parse HEAD)"
- name: Get version
id: get_version
if: ${{ github.event.inputs.version == '' && inputs.version == '' }}
uses: ./.github/actions/version
with:
commit_sha: ${{ steps.get_commit_sha.outputs.commit_sha }}
- name: Get Sentry parameters
id: get_sentry
run: |
#!/bin/bash
if [[ "${{ github.event.inputs.sentry_enabled || inputs.sentry_enabled }}" == "true" ]]; then
echo "environment=production" >> "$GITHUB_OUTPUT"
echo "upload_symbols=true" >> "$GITHUB_OUTPUT"
echo "sentry_enabled=true" >> "$GITHUB_OUTPUT"
else
echo "environment=" >> "$GITHUB_OUTPUT"
echo "upload_symbols=false" >> "$GITHUB_OUTPUT"
echo "sentry_enabled=false" >> "$GITHUB_OUTPUT"
fi
- name: Set default values
id: set_defaults
run: |
if [ "${{ github.event.inputs.clean_build }}" ]; then
clean_build=${{ github.event.inputs.clean_build }}
elif [ "${{ inputs.clean_build }}" ]; then
clean_build=${{ inputs.clean_build }}
elif [ "${{ github.event.label.name }}" == "clean-build" ]; then
clean_build=true
else
clean_build=false
fi
echo "Set clean_build to: $clean_build"
echo "clean_build=${clean_build}" >> $GITHUB_OUTPUT
if [ "${{ github.event.inputs.cache_strategy }}" ]; then
cache_strategy=${{ github.event.inputs.cache_strategy }}
elif [ "${{ inputs.cache_strategy }}" ]; then
cache_strategy=${{ inputs.cache_strategy }}
else
cache_strategy='library'
fi
echo "Set cache_strategy to: $cache_strategy"
echo "cache_strategy=${cache_strategy}" >> $GITHUB_OUTPUT
if [ "${{ github.event.inputs.install_source }}" ]; then
install_source=${{ github.event.inputs.install_source }}
elif [ "${{ inputs.install_source }}" ]; then
install_source=${{ inputs.install_source }}
else
install_source='launcher'
fi
echo "Set install_source to: $install_source"
echo "install_source=${install_source}" >> $GITHUB_OUTPUT
- name: Get BuildOptions
id: get_options
run: |
#!/bin/bash
#options=("DetailedBuildReport")
options=()
# input.profile
profile="${{ github.event.inputs.profile || inputs.profile }}"
if [[ "$profile" == "profile" || "$profile" == "deep" ]]; then
options+=("Development")
options+=("AllowDebugging")
options+=("ConnectWithProfiler")
fi
if [[ "$profile" == "deep" ]]; then
options+=("EnableDeepProfilingSupport")
fi
# Write the array as a comma-separated string
# Set the Internal Field Separator to comma
IFS=,
echo "options=${options[*]}" >> "$GITHUB_OUTPUT"
build:
name: Build
runs-on: ubuntu-latest
needs: prebuild
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
target: ['windows64', 'macos']
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref || github.ref_name }}
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: 3.12.3
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r scripts/cloudbuild/requirements.txt
- name: Execute Unity Cloud build
env:
API_KEY: ${{ secrets.UNITY_CLOUD_API_KEY }}
ORG_ID: ${{ secrets.UNITY_CLOUD_ORG_ID }}
PROJECT_ID: ${{ secrets.UNITY_CLOUD_PROJECT_ID }}
POLL_TIME: 60 # In seconds (int)
TARGET: t_${{ matrix.target }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
COMMIT_SHA: ${{ needs.prebuild.outputs.commit_sha }}
BUILD_OPTIONS: ${{ needs.prebuild.outputs.options }}
CLEAN_BUILD: ${{ needs.prebuild.outputs.clean_build }}
CACHE_STRATEGY: ${{ needs.prebuild.outputs.cache_strategy }}
IS_RELEASE_BUILD: ${{ inputs.is_release_build }}
TAG_VERSION: ${{ inputs.tag_version }}
#Possible values: { none, library, workspace, inherit }
# Any ENV variables starting with "PARAM_" will be passed to Unity without the prefix
# (The "PARAM_" prefix exists to allow any future values config-free)
# e.g.: PARAM_ALLOW_DEBUG -> In Unity will be available as "ALLOW_DEBUG"
# e.g.: Editor.CloudBuild.Parameters["ALLOW_DEBUG"]
PARAM_BUILD_VERSION: ${{ needs.prebuild.outputs.version }}
PARAM_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
PARAM_SENTRY_ENVIRONMENT: ${{ needs.prebuild.outputs.sentry_environment }}
PARAM_SENTRY_CLI_AUTH_TOKEN: ${{ secrets.SENTRY_CLI_AUTH_TOKEN }}
PARAM_SENTRY_ENABLED: ${{ needs.prebuild.outputs.sentry_enabled }}
PARAM_SENTRY_UPLOAD_DEBUG_SYMBOLS: ${{ needs.prebuild.outputs.sentry_upload_symbols }}
PARAM_SEGMENT_WRITE_KEY: ${{ secrets.SEGMENT_WRITE_KEY }}
PARAM_INSTALL_SOURCE: ${{ needs.prebuild.outputs.install_source }}
run: python -u scripts/cloudbuild/build.py
- name: 'Tar artifact to maintain original permissions'
if: matrix.target == 'macos'
run: tar --exclude='build/Decentraland_BackUpThisFolder_ButDontShipItWithYourGame' -cvf build.tar build
- name: Set artifact name
id: set_artifact_name
run: |
if [ "${{ needs.prebuild.outputs.install_source }}" == "launcher" ]; then
echo "artifact_name=Decentraland_${{ matrix.target }}" >> $GITHUB_ENV
else
echo "artifact_name=Decentraland_${{ matrix.target }}_${{ needs.prebuild.outputs.install_source }}" >> $GITHUB_ENV
fi
- name: Upload artifact for macOS
id: upload-macos-artifact
if: matrix.target == 'macos'
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_name }}
path: build.tar
if-no-files-found: error
- name: Upload artifact for Windows
id: upload-windows-artifact
if: matrix.target == 'windows64'
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_name }}
path: |
build
!build/**/*_BackUpThisFolder_ButDontShipItWithYourGame
!build/**/*_BurstDebugInformation_DoNotShip
if-no-files-found: error
- name: Compress the build folder to upload it to S3
run: |
mkdir upload_to_s3/ && \
if [ "${{ matrix.target }}" == "macos" ]; then
zip -r upload_to_s3/${{ env.artifact_name }}.zip build.tar
elif [ "${{ matrix.target }}" == "windows64" ]; then
cd build
zip -r ../upload_to_s3/${{ env.artifact_name }}.zip . -x "*_BackUpThisFolder_ButDontShipItWithYourGame**" -x "*_BurstDebugInformation_DoNotShip**"
fi
- name: Upload artifact to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.EXPLORER_TEAM_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.EXPLORER_TEAM_AWS_SECRET_ACCESS_KEY }}
EXPLORER_TEAM_S3_BUCKET: ${{ secrets.EXPLORER_TEAM_S3_BUCKET }}
DESTINATION_PATH: ${{ inputs.is_release_build && format('@dcl/{0}/releases/{1}', github.event.repository.name, inputs.tag_version) || format('@dcl/{0}/branch/{1}', github.event.repository.name, github.head_ref || github.ref_name) }}
run: |
npx @dcl/cdn-uploader@next \
--bucket $EXPLORER_TEAM_S3_BUCKET \
--local-folder upload_to_s3 \
--bucket-folder $DESTINATION_PATH
- name: Upload debug symbols
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_name }}_debug_symbols
path: |
build/**/*_BackUpThisFolder_ButDontShipItWithYourGame
build/**/*_BurstDebugInformation_DoNotShip
if-no-files-found: error
# Will run always (even if failing)
- name: Upload cloud logs
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target }}_${{ needs.prebuild.outputs.install_source }}_unity_log
path: unity_cloud_log.log
if-no-files-found: error
# Will run always (even if failing)
- name: Print cloud logs
if: always()
run: cat unity_cloud_log.log
- name: Extract and display errors
if: always()
run: |
echo "=== Extracted Errors for ${{ matrix.target }} ${{ needs.prebuild.outputs.install_source }} ==="
grep -iE "error c|fatal" unity_cloud_log.log | sed 's/^/\x1b[31m/' | sed 's/$/\x1b[0m/' || echo "No 'error c' or 'fatal' errors found in ${{ matrix.target }} log."
# Will run always (even if failing)
- name: Generate Shader Compilation Report
shell: pwsh
run: |
./scripts/Generate-ShaderReport.ps1 -InputLog "unity_cloud_log.log" -OutputReport "shader_compilation_report.log"
# Upload Shader Compilation Report
- name: Upload Shader Compilation Report
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target }}_${{ needs.prebuild.outputs.install_source }}_shader_compilation_report
path: shader_compilation_report.log
if-no-files-found: error
# Will run on cancel or timeout only
- name: Cancel Unity Cloud build
if: ${{ cancelled() }}
env:
API_KEY: ${{ secrets.UNITY_CLOUD_API_KEY }}
ORG_ID: ${{ secrets.UNITY_CLOUD_ORG_ID }}
PROJECT_ID: ${{ secrets.UNITY_CLOUD_PROJECT_ID }}
run: python -u scripts/cloudbuild/build.py --cancel