From 1c0c21793130186efed5a1159a88a002841d5dc7 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Sun, 29 Jan 2023 10:12:08 +0000 Subject: [PATCH] Add updated test flow for builds --- .github/workflows/buildupmpackages.yml | 26 +- .../workflows/rununitybuildmultiversion.yml | 447 ++++++++++++++++++ 2 files changed, 450 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/rununitybuildmultiversion.yml diff --git a/.github/workflows/buildupmpackages.yml b/.github/workflows/buildupmpackages.yml index 38da957..9fb0abd 100644 --- a/.github/workflows/buildupmpackages.yml +++ b/.github/workflows/buildupmpackages.yml @@ -1,4 +1,4 @@ -name: Build and test UPM packages for platforms +name: Build and test UPM packages for platforms on all available Unity Versions on: pull_request: @@ -14,27 +14,7 @@ concurrency: cancel-in-progress: true jobs: - # Check Unity version requird by the package - validate-environment: - name: Get Unity Version from UPM package - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/getunityversionfrompackage.yml@main - with: - build-target: self-hosted - - # Check Unity Hub and Editor Environment - Setup-Unity: - name: Validate Unity Install - needs: validate-environment - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/validateunityinstall.yml@main - with: - build-target: self-hosted - unityversion: ${{ needs.validate-environment.outputs.unityversion }} - - # Run Unity unit tests defined in the package + # Run Unity multi-version build unit tests defined in the package Run-Unit-Tests: name: Run Unity Unit Tests - needs: Setup-Unity - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/rununityunittests.yml@main - with: - build-target: self-hosted - unityversion: ${{ needs.Setup-Unity.outputs.unityeditorversion }} \ No newline at end of file + uses: ./.github/workflows/rununitybuildmultiversion.yml \ No newline at end of file diff --git a/.github/workflows/rununitybuildmultiversion.yml b/.github/workflows/rununitybuildmultiversion.yml new file mode 100644 index 0000000..ceb16a9 --- /dev/null +++ b/.github/workflows/rununitybuildmultiversion.yml @@ -0,0 +1,447 @@ +name: Run Unity Builds + +on: + workflow_call: + inputs: + dependencies: + description: "json array of dependencies and their targets" + required: false + type: string + +jobs: + run_build: + name: Run Unity Build process + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: macos + unityVersion: 2020.3 + build-target: Android + - os: macos + unityVersion: 2020.3 + build-target: iOS + - os: windows + unityVersion: 2020.3 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2020.3 + build-target: WSAPlayer + - os: macos + unityVersion: 2021.3 + build-target: Android + - os: macos + unityVersion: 2021.3 + build-target: iOS + - os: windows + unityVersion: 2021.3 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2021.3 + build-target: WSAPlayer + - os: macos + unityVersion: 2022.2 + build-target: Android + - os: macos + unityVersion: 2022.2 + build-target: iOS + - os: windows + unityVersion: 2022.2 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2022.2 + build-target: WSAPlayer + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.0" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v3 + with: + submodules: recursive + clean: true + + - id: build + name: 'Run Unity Builds' + run: | + echo "::group::Set Hub and editor locations" + $unityVersion = ${{ matrix.unityVersion }} + + echo "::group::Set Hub and editor locations" + + ## Set Hub and editor locations + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) + { + $hubPath = "C:\Program Files\Unity Hub\Unity Hub.exe" + $editorRootPath = "C:\Program Files\Unity\Hub\Editor\" + $editorFileEx = "\Editor\Unity.exe" + + #"Unity Hub.exe" -- --headless help + #. 'C:\Program Files\Unity Hub\Unity Hub.exe' -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) + { + $hubPath = "/Applications/Unity Hub.app/Contents/MacOS/Unity Hub" + $editorRootPath = "/Applications/Unity/Hub/Editor/" + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + + # /Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) + { + $hubPath = "$HOME/Unity Hub/UnityHub.AppImage" + $editorRootPath = "$HOME/Unity/Hub/Editor/" + $editorFileEx = "/Editor/Unity" + + # /UnityHub.AppImage --headless help + # xvfb-run --auto-servernum "$HOME/Unity Hub/UnityHub.AppImage" --headless help + function unity-hub + { + xvfb-run --auto-servernum "$hubPath" --headless $args.Split(" ") + } + } + + echo "::endgroup::" + + + + echo "::group::Get String function to query a string for a value" + + function GetString($InputString, $InputPattern, $MatchIndex) + { + $regExResult = $InputString | Select-String -Pattern $InputPattern + if($regExResult.Length -gt 0) + { + return $regExResult.Matches[$MatchIndex].Value + } + else + { + return 0 + } + } + + function Get-LetterCount + { + Param ([string]$string) + return $string.Length + } + echo "::endgroup::" + + echo "::group::Get Installed Unity version based on Matrix" + echo 'Script Start' + echo "Unity hub path is {$hubPath}" + echo "Requested unity version is {$unityVersion}" + + $InstalledUnityVersions = unity-hub editors + $editorRootPath = unity-hub ip -g + echo "Installed unity versions are {$InstalledUnityVersions}" + echo "Unity install path is {$editorRootPath}" + + $versionLength = Get-LetterCount $unityVersion + if ($versionLength -eq 4) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,7}" -MatchIndex 0 + } + elseif ($versionLength -eq 6) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,5}" -MatchIndex 0 + } + else { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion" -MatchIndex 0 + } + + echo "Found unity version is {$queryUnityVersion}" + + if ($queryUnityVersion -ne 0) + { + $unityVersion = $queryUnityVersion.Trim(","," ").Trim() + echo "Long Unity version is $unityVersion" + } + else + { + echo "Unity $unityVersion not found on this machine, skipping" + exit 0 + } + + echo "::endgroup::" + + echo "::group::Search for Editor if not found" + $checkPath = Join-Path $editorRootPath $unityVersion + echo "Testing for editor at $checkPath" + while (-not (Test-Path "$checkPath")) { + $source = $unityVersion.Replace("f1","") + $newversion = $source.Split(".") + $newversion[2] = [int]$newversion[2] - 1 + if ([int]$newversion[2] -lt 1) { + echo "Unity ${{ matrix.unityVersion }} not found on this machine, skipping" + exit 0 + } + $newunityVersion = "{0}.{1}.{2}f1" -f $newversion[0],$newversion[1],$newversion[2] + echo "Unity $unityVersion not found on this machine, trying $newunityVersion" + $unityVersion = $newunityVersion + $checkPath = Join-Path $editorRootPath $unityVersion + } + echo "::endgroup::" + + echo "::group::Set editor locations" + + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) { + echo 'Building using Windows' + $editorFileEx = "/Editor/Unity.exe" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) { + echo 'Building using Mac' + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) { + echo 'Building using Linux' + $editorFileEx = "/Editor/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + xvfb-run --auto-servernum "$editorrunpath" -batchmode $args.Split(" ") + } + } + else + { + echo 'Unknown build platform' + } + + echo "::endgroup::" + + echo "::group::Test Unity version is installed" + + if ( -not (Test-Path "$editorrunpath") ) + { + Write-Error "Editor not Found for $unityVersion" + exit 1 + } + else { + echo "Editor Path is {$editorrunpath}" + } + + echo "::endgroup::" + + echo "::group::Setup logging and run Unit tests" + + # Log detail + $logDirectory = "Logs" + if (Test-Path -Path $logDirectory) { + echo "Clearing logs from a previous run" + Remove-item $logDirectory -recurse + } + + $logDirectory = New-Item -ItemType Directory -Force -Path $logDirectory | Select-Object + + echo "Log Directory: $logDirectory" + $date = Get-Date -Format "yyyyMMddTHHmmss" + + # If run manually, the Refname is actually blank, so just use date + if([string]::IsNullOrEmpty(${GITHUB_REF_NAME})) { + $logName = "$logDirectory$directorySeparatorChar$date" + } + else{ + $logName = "$logDirectory$directorySeparatorChar${GITHUB_REF_NAME}-$date" + } + + $logPath = "$logName.log" + $testsLogPath = "$logName-tests.xml" + + echo "Logpath [$logPath]" + echo "TestsPath [$testsLogPath]" + echo "::endgroup::" + + echo "::group::Grouping Package in a UPM folder" + + $UPMFolderName = 'u' + + if ( -not (Test-Path '$UPMFolderName') ) + { + New-Item $UPMFolderName -ItemType Directory + } + + Move-Item -Path * -Destination $UPMFolderName -exclude $UPMFolderName + + echo "::endgroup::" + + echo "::group::Creating Temp Unity project" + + $TempUnityProjectName = 'P' + + unity-editor '-createProject' $TempUnityProjectName -quit + + $destinationPath = $TempUnityProjectName + $directorySeparatorChar + 'packages' + Move-Item -Path $UPMFolderName -Destination $destinationPath + + echo "::endgroup::" + + echo "::group::If required, clone dependencies in to test project" + + <# Dependency option requires specific inputs + + * A dependency input string in json format, listing each dependency by name and git url, e.g. + $dependencies = '[{"ASADependencies": "github.com/SimonDarksideJ/upmGithubActionsTests.git"}]' + *Note, remove the https:// portion to allow using a PAT to access the repo + The Name of the dependency should ALSO MATCH the name of the branch on the repo where the dependency is held (files intended for the packages folder) + + * Additionally, if Manifest entries are required, then a manifest file with those dependencies (and ONLY the new dependancies) should also be in the dependency branch named the same as the branch name + e.g. "ASADependencies.json" - keep the same structure, but only the dependancy entries + + !!Does NOT support additional scoped registries at this time! #> + + echo "---------------------------------------------" + echo "Read dependancy input value" + if([string]::IsNullOrEmpty('${{ inputs.dependencies }}')) + { + echo "No dependencies provided" + echo "input ${{ inputs.dependencies }}" + echo "------------------------------" + } + else { + echo "dependencies provided, validating" + + # Read dependancy input value + $dependencies = '${{ inputs.dependencies }}' + + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}') -or [string]::IsNullOrEmpty('${{ secrets.GIT_PAT }}')){ + echo "" + echo "Secrets for GIT_USER_NAME or GIT_PAT missing, please register them with access to this runner" + echo "*Note, Organisation secrets are not accessible to Forked repos and need registering in the local fork" + exit 1 + } + + echo "---------------------------------------------" + echo "Read dependancy input values as json" + $JSONdependencies = $dependencies | ConvertFrom-Json + + echo $JSONdependencies + + # Read current Manifest json + $manifestPath = $destinationPath + $directorySeparatorChar + 'manifest.json' + $projectManifest = Get-Content -Path $manifestPath | ConvertFrom-Json + $strArray = $projectManifest.dependencies.PsObject.Properties | ForEach-Object {"$($_.Name)@$($_.Value),"} + + echo "---------------------------------------------" + echo "Loop through new dependancies and add them to the project Manifest" + foreach($dependency in $JSONdependencies){ + $dependency.PsObject.Properties | ForEach-Object -Process { + $dependencyName = $_.Name + $dependencyPath = $dependencyName.Replace("/","_") + $dependencyURL = $_.Value + echo "---------------------------------------------" + echo "Cloning dependency - Name [$dependencyName] - Path [$dependencyPath] - URL [$dependencyURL]" + $cloneURL = "https://${{ secrets.GIT_USER_NAME }}:${{ secrets.GIT_PAT }}@$dependencyURL" + + echo "cloning $dependencyName from $dependencyURL and moving to $destinationPath" + echo "git path - $cloneURL" + + # Clone Dependancy repo to destination folder + git clone -b $dependencyName --single-branch $cloneURL $dependencyPath + + if( -not (Test-Path -Path "$dependencyPath")){ + echo "Unable to clone $dependencyName from $dependencyURL" + exit 1 + } + + # Move files from clone path into packages folder, if the dependency contains a UPM package then move the entire folder and not just its contents + if (Test-Path -Path "$dependencyPath/package.json") { + $package_json = Get-Content -Path $dependencyPath/package.json | ConvertFrom-Json + $packageName = $package_json.name + Rename-Item $dependencyPath $packageName + echo "Moving whole $packageName UPM package to $destinationPath" + Move-Item -Path "$packageName" -Destination $destinationPath + } + else { + echo "Moving the contents of $dependencyName into the $destinationPath folder" + Move-Item -Path "$dependencyPath/*" -Destination $destinationPath + } + + # Get Dependency manifest entries (if applicable) + if (Test-Path -Path "$destinationPath/$dependencyName.json") { + $dependencyManifest = Get-Content -Path "$destinationPath/$dependencyName.json" | ConvertFrom-Json + $dependencyManifest.dependencies.PsObject.Properties | ForEach-Object { + $strArray += "$($_.Name)@$($_.Value)," + } + } + else{ + echo "No denendency json found called $destinationPath/$dependencyName.json, skipping adding additional manifest entries" + } + } + } + echo "---------------------------------------------" + + # Reformat combined dependancies list + $strArray = $strArray.Trim(",") | ConvertTo-Json + $strArray = $strArray.Replace("@",'":"').Replace("[","{").Replace("]","}") + $strArrayObject = $strArray | ConvertFrom-Json + + # Save manifest back to project + $projectManifest.dependencies = $strArrayObject + $projectManifest | ConvertTo-Json | Set-Content -Path "$destinationPath/manifest.json" + + echo "Project updated with the following dependencies" + echo "-----------------------------------------------" + echo $projectManifest + } + + echo "::endgroup::" + + echo "::group::Run build" + + echo "---------------------------------------------" + echo "Start Testing" + echo "Unity Command\n[unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }}]" + + unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }} + + echo "---------------------------------------------" + echo "::group::Unity Unit tests Results" + if (Test-Path $testsLogPath) { + echo "Test Run results for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF}" + echo "" + Select-Xml -Path $testsLogPath -XPath '/test-run/test-suite' | ForEach-Object { "Name: " +$_.Node.name, ", Result: " + $_.Node.result, ", Total Tests: " + $_.Node.total, ", Passed: " + $_.Node.passed, ", Failed: " + $_.Node.failed, ", Skipped: " + $_.Node.skipped } + } + else { + echo "No test results found for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF} at $testsLogPath" + echo "" + } + echo "::endgroup::" + + if($LASTEXITCODE -ne '0'){ + echo "::group::Unity Unit tests errors" + $exitCode = $testResult.ExitCode + Get-Content $logPath + echo "Build failed due to errors ($LASTEXITCODE), please check the log at $logPath" + echo "::endgroup::" + + exit $LASTEXITCODE + } + echo "::endgroup::" + + shell: pwsh + - uses: actions/upload-artifact@v3 + if: always() + with: + name: unity-build-log + path: Logs/** \ No newline at end of file