Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 77 additions & 17 deletions dist/platforms/windows/steps/activate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,27 @@ Push-Location $Env:ACTIVATE_LICENSE_PATH

$global:UNITY_EXIT_CODE = 1

# Same known-transient Unity license-server flakiness as mac/ubuntu (see
# mac/steps/build.sh's matching comment) - this file had NO retry logic at
# all before now, unlike every other activate/return script this session
# (confirmed missing via game-ci/unity-test-runner#310's Windows Docker
# matrix). Retried only on known-transient signatures, so a genuine
# activation failure (bad serial, expired license, etc.) still fails
# immediately.
$MaxAttempts = if ($Env:UNITY_LICENSE_RETRY_MAX_ATTEMPTS) { [int]$Env:UNITY_LICENSE_RETRY_MAX_ATTEMPTS } else { 4 }
$RetryDelaySeconds = 20
$TransientPattern = 'TimeoutPolicy did not complete|Access token is unavailable|entitlement groups and 0 free entitlements|License activation has failed|No valid Unity Editor license found|License is not active'

try {
$UnityExePath = Get-UnityEditorExePath

if ($Env:UNITY_LICENSE -or $Env:UNITY_LICENSE_FILE) {
# Serial mode is preferred over personal-license (below) whenever both are
# configured - see mac/steps/activate.sh's matching comment: a manually-
# activated .ulf is bound to the machine fingerprint of whatever machine
# originally requested it, which doesn't necessarily match every runner.
$HasSerialCredentials = $Env:UNITY_SERIAL -and $Env:UNITY_EMAIL -and $Env:UNITY_PASSWORD

if ((-not $HasSerialCredentials) -and ($Env:UNITY_LICENSE -or $Env:UNITY_LICENSE_FILE)) {
#
# PERSONAL LICENSE MODE
#
Expand All @@ -36,29 +53,56 @@ try {
((Get-Content -Raw $Env:UNITY_LICENSE_FILE) -replace "`r", '') | Set-Content -Path $FilePath -NoNewline
}

Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -manualLicenseFile $FilePath | Out-Host
$global:UNITY_EXIT_CODE = $LASTEXITCODE

# The exit code for personal activation is always 1; determine whether
# activation was successful from the log instead. Successful output
# should include a line like:
# "LICENSE SYSTEM [2020120 18:51:20] Next license update check is after 2019-11-25T18:23:38"
$LogContent = if (Test-Path $LogPath) { Get-Content -Raw $LogPath } else { '' }
if ($LogContent -match 'Next license update check is after') {
$global:UNITY_EXIT_CODE = 0
for ($Attempt = 1; $Attempt -le $MaxAttempts; $Attempt++) {
Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -manualLicenseFile $FilePath | Out-Host
$global:UNITY_EXIT_CODE = $LASTEXITCODE

# The exit code for personal activation is always 1; determine whether
# activation was successful from the log instead. Successful output
# should include a line like:
# "LICENSE SYSTEM [2020120 18:51:20] Next license update check is after 2019-11-25T18:23:38"
$LogContent = if (Test-Path $LogPath) { Get-Content -Raw $LogPath } else { '' }
if ($LogContent -match 'Next license update check is after') {
$global:UNITY_EXIT_CODE = 0
break
}

if ($Attempt -lt $MaxAttempts -and $LogContent -match $TransientPattern) {
# Exponential backoff - see mac/steps/activate.sh's matching comment.
$CurrentRetryDelay = $RetryDelaySeconds * [math]::Pow(2, $Attempt - 1)
Write-Host "Unity activation failed with a known-transient licensing error (attempt $Attempt/$MaxAttempts) - retrying in ${CurrentRetryDelay}s..."
Start-Sleep -Seconds $CurrentRetryDelay
continue
}
break
}

Remove-Item -Force $FilePath -ErrorAction SilentlyContinue
} elseif ($Env:UNITY_SERIAL -and $Env:UNITY_EMAIL -and $Env:UNITY_PASSWORD) {
} elseif ($HasSerialCredentials) {
#
# PROFESSIONAL (SERIAL) LICENSE MODE
#
Write-Host 'Requesting activation (professional license)'

$LogPath = Join-Path $Env:ACTIVATE_LICENSE_PATH 'activate.log'
Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -serial $Env:UNITY_SERIAL -username $Env:UNITY_EMAIL -password $Env:UNITY_PASSWORD | Out-Host
$global:UNITY_EXIT_CODE = $LASTEXITCODE
if (Test-Path $LogPath) { Get-Content $LogPath | Out-Host }

for ($Attempt = 1; $Attempt -le $MaxAttempts; $Attempt++) {
Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -serial $Env:UNITY_SERIAL -username $Env:UNITY_EMAIL -password $Env:UNITY_PASSWORD | Out-Host
$global:UNITY_EXIT_CODE = $LASTEXITCODE
$LogContent = if (Test-Path $LogPath) { Get-Content -Raw $LogPath } else { '' }
if ($LogContent) { Get-Content $LogPath | Out-Host }

if ($global:UNITY_EXIT_CODE -eq 0) { break }

if ($Attempt -lt $MaxAttempts -and $LogContent -match $TransientPattern) {
# Exponential backoff - see mac/steps/activate.sh's matching comment.
$CurrentRetryDelay = $RetryDelaySeconds * [math]::Pow(2, $Attempt - 1)
Write-Host "Unity activation failed with a known-transient licensing error (attempt $Attempt/$MaxAttempts) - retrying in ${CurrentRetryDelay}s..."
Start-Sleep -Seconds $CurrentRetryDelay
continue
}
break
}
} elseif ($Env:UNITY_LICENSING_SERVER) {
#
# Custom Unity License Server
Expand All @@ -67,8 +111,24 @@ try {

$LicensingClientPath = Get-UnityLicensingClientExePath
$LicenseTextPath = Join-Path $Env:ACTIVATE_LICENSE_PATH 'license.txt'
& $LicensingClientPath --acquire-floating | Out-File -FilePath $LicenseTextPath -Encoding UTF8
$global:UNITY_EXIT_CODE = $LASTEXITCODE

for ($Attempt = 1; $Attempt -le $MaxAttempts; $Attempt++) {
$AcquireOutput = & $LicensingClientPath --acquire-floating 2>&1 | Tee-Object -Variable AcquireOutputVar
$AcquireOutput | Out-File -FilePath $LicenseTextPath -Encoding UTF8
$global:UNITY_EXIT_CODE = $LASTEXITCODE
$AcquireText = ($AcquireOutputVar | Out-String)

if ($global:UNITY_EXIT_CODE -eq 0) { break }

if ($Attempt -lt $MaxAttempts -and $AcquireText -match $TransientPattern) {
# Exponential backoff - see mac/steps/activate.sh's matching comment.
$CurrentRetryDelay = $RetryDelaySeconds * [math]::Pow(2, $Attempt - 1)
Write-Host "Floating license acquisition failed with a known-transient licensing error (attempt $Attempt/$MaxAttempts) - retrying in ${CurrentRetryDelay}s..."
Start-Sleep -Seconds $CurrentRetryDelay
continue
}
break
}

$ParsedFile = Select-String -Path $LicenseTextPath -Pattern '"[^"]*"' -AllMatches |
ForEach-Object { $_.Matches } | ForEach-Object { $_.Value -replace '"', '' }
Expand Down
64 changes: 61 additions & 3 deletions dist/platforms/windows/steps/return_license.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,48 @@ $StepsDir = if ($Env:STEPS_DIR) { $Env:STEPS_DIR } else { $PSScriptRoot }
Write-Host "Changing to `"$Env:ACTIVATE_LICENSE_PATH`" directory."
Push-Location $Env:ACTIVATE_LICENSE_PATH

# A failed license *return* is worse than a failed activate/build: it leaks
# the seat back to Unity's license pool - see mac/steps/return_license.sh's
# matching comment. This branch never checked its exit code and never
# retried before now (confirmed live via game-ci/unity-test-runner#310's
# Windows Docker matrix: "Serial number unavailable for ULF return" /
# "Connection attempt to the License Client ... failed" on the very first
# attempt, with no retry and -returnlicense missing -username/-password -
# both required for a SERIAL-mode return, same as
# mac/steps/return_license.sh and the host-mode windows/return_license.ps1
# already pass).
$MaxAttempts = if ($Env:UNITY_LICENSE_RETRY_MAX_ATTEMPTS) { [int]$Env:UNITY_LICENSE_RETRY_MAX_ATTEMPTS } else { 4 }
$RetryDelaySeconds = 20
$TransientPattern = 'TimeoutPolicy did not complete|Access token is unavailable|entitlement groups and 0 free entitlements|License activation has failed|No valid Unity Editor license found|License is not active|Serial number unavailable'

try {
if ($Env:UNITY_LICENSING_SERVER) {
#
# Return any floating license used.
#
Write-Host "Returning floating license: `"$($global:FLOATING_LICENSE)`""
$LicensingClientPath = Get-UnityLicensingClientExePath
& $LicensingClientPath --return-floating $global:FLOATING_LICENSE

for ($Attempt = 1; $Attempt -le $MaxAttempts; $Attempt++) {
$ReturnOutput = & $LicensingClientPath --return-floating $global:FLOATING_LICENSE 2>&1 | Tee-Object -Variable ReturnOutputVar
$ReturnOutput | Out-Host
$ReturnExitCode = $LASTEXITCODE
$ReturnText = ($ReturnOutputVar | Out-String)

if ($ReturnExitCode -eq 0) { break }

if ($Attempt -lt $MaxAttempts -and $ReturnText -match $TransientPattern) {
# Exponential backoff - see mac/steps/activate.sh's matching comment.
$CurrentRetryDelay = $RetryDelaySeconds * [math]::Pow(2, $Attempt - 1)
Write-Host "Floating license return failed with a known-transient licensing error (attempt $Attempt/$MaxAttempts) - retrying in ${CurrentRetryDelay}s..."
Start-Sleep -Seconds $CurrentRetryDelay
continue
}
break
}
if ($ReturnExitCode -ne 0) {
Write-Host "##[warning] Failed to return floating license `"$($global:FLOATING_LICENSE)`" after $MaxAttempts attempts - this seat may still be held by Unity's license server."
}
} elseif ($Env:UNITY_SERIAL) {
#
# PROFESSIONAL (SERIAL) LICENSE MODE
Expand All @@ -23,10 +57,34 @@ try {
# reimport its library against whatever the editor's default target
# is) just to return the license (game-ci/cli#33).
#
# -username/-password are required here - without them Unity has no
# way to tell this was a serial-mode activation and instead attempts a
# personal-license (ULF) return, which fails immediately with "Serial
# number unavailable for ULF return".
#
$UnityExePath = Get-UnityEditorExePath
$LogPath = Join-Path $Env:ACTIVATE_LICENSE_PATH 'return_license.log'
Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -returnlicense -projectPath $Env:ACTIVATE_LICENSE_PATH | Out-Host
if (Test-Path $LogPath) { Get-Content $LogPath | Out-Host }

for ($Attempt = 1; $Attempt -le $MaxAttempts; $Attempt++) {
Invoke-UnityLaunch -ExePath $UnityExePath -logFile $LogPath -quit -returnlicense -username $Env:UNITY_EMAIL -password $Env:UNITY_PASSWORD -projectPath $Env:ACTIVATE_LICENSE_PATH | Out-Host
$ReturnExitCode = $LASTEXITCODE
$LogContent = if (Test-Path $LogPath) { Get-Content $LogPath -Raw } else { '' }
if ($LogContent) { Get-Content $LogPath | Out-Host }

if ($ReturnExitCode -eq 0) { break }

if ($Attempt -lt $MaxAttempts -and $LogContent -match $TransientPattern) {
# Exponential backoff - see mac/steps/activate.sh's matching comment.
$CurrentRetryDelay = $RetryDelaySeconds * [math]::Pow(2, $Attempt - 1)
Write-Host "License return failed with a known-transient licensing error (attempt $Attempt/$MaxAttempts) - retrying in ${CurrentRetryDelay}s..."
Start-Sleep -Seconds $CurrentRetryDelay
continue
}
break
}
if ($ReturnExitCode -ne 0) {
Write-Host "##[warning] Failed to return the Unity license after $MaxAttempts attempts - this seat may still be held by Unity's license server."
}
}
} catch {
Write-Host "Could not return license: $($_.Exception.Message)"
Expand Down
Loading