Templates/Initialize-QAFrameworkAgent.ps1
|
<# .SYNOPSIS Prepares a DataMiner agent to run QAFramework tests. .DESCRIPTION This script runs ON a DataMiner agent, started by Initialize-QAFrameworkAgents through a QAOps Bridge execution. It is a parameterised port of the legacy 1.TestPackageSetup.ps1: - installs and restores the dataminer-run-automation-script dotnet tool, - creates the RTManager root and its Settings\SystemSettings.json, including FailoverState, - stops the device simulator so it cannot interfere with the tests, - replaces the GlobalDependencies, TeamDependencies and TestDependencies folders and the knownautomationtests.txt file with the ones harvested into the test package. Copy this file into your test package, for example to TestPackagePipeline\helpers\Initialize-QAFrameworkAgent.ps1. .PARAMETER PathToTestPackageContent The test package content root on this agent. .PARAMETER RtManagerRoot The RTManager root folder. Defaults to C:\RTManager\. .PARAMETER FailoverState The failover state to write into SystemSettings.json. 0 is before the switch, 10 after the switch and 20 after switching back. .PARAMETER SystemSettings Extra SystemSettings.json values as a JSON string, merged over the defaults. .PARAMETER SkipToolInstall Do not install or restore the dotnet tool. .PARAMETER SkipDependencies Only write the settings; do not touch the dependency folders. Used when the script is called again to change the failover state between test phases. #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$PathToTestPackageContent, [Parameter(Mandatory = $false)] [string]$RtManagerRoot = 'C:\RTManager\', [Parameter(Mandatory = $false)] [int]$FailoverState = 0, [Parameter(Mandatory = $false)] [string]$SystemSettings, [Parameter(Mandatory = $false)] [switch]$SkipToolInstall, [Parameter(Mandatory = $false)] [switch]$SkipDependencies ) $ErrorActionPreference = 'Stop' function Stop-ProcessIfRunning { param([Parameter(Mandatory = $true)][string]$Name) $processes = Get-Process -Name $Name -ErrorAction SilentlyContinue if (-not $processes) { return } Write-Host "Stopping $Name (found $($processes.Count))." foreach ($process in $processes) { Stop-Process -Id $process.Id -Force -ErrorAction Stop } Start-Sleep -Seconds 2 } function Remove-PathWithRetry { param( [Parameter(Mandatory = $true)][string]$TargetPath, [switch]$IsDirectory ) if (-not (Test-Path -Path $TargetPath)) { return } try { Remove-Item -Path $TargetPath -Recurse:$IsDirectory -Force -ErrorAction Stop return } catch { Write-Warning "Deletion failed for '$TargetPath': $($_.Exception.Message). Stopping SLAutomation and retrying." } Stop-ProcessIfRunning -Name 'SLAutomation' Start-Sleep -Seconds 1 Remove-Item -Path $TargetPath -Recurse:$IsDirectory -Force -ErrorAction Stop Write-Host 'Waiting 120 seconds for SLAutomation to initialise again.' Start-Sleep -Seconds 120 # SLAutomation being killed produces a minidump; remove the one of this run so it does not # end up being reported as a system problem. try { $miniDumpRoot = 'C:\Skyline DataMiner\Logging\MiniDump' if (Test-Path -Path $miniDumpRoot) { $now = Get-Date $closest = Get-ChildItem -Path $miniDumpRoot -Filter '*_Processes disappeared.zip' -File -ErrorAction SilentlyContinue | Sort-Object -Property @{ Expression = { [math]::Abs(($_.LastWriteTime - $now).TotalSeconds) } } | Select-Object -First 1 if ($closest) { Write-Host "Removing minidump '$($closest.FullName)'." Remove-Item -LiteralPath $closest.FullName -Force -ErrorAction Stop } } } catch { Write-Warning "Failed to remove the minidump: $($_.Exception.Message)" } } function Copy-Tree { param( [Parameter(Mandatory = $true)][string]$Source, [Parameter(Mandatory = $true)][string]$Destination ) if (-not (Test-Path -Path $Source)) { Write-Warning "Source not found, skipping: $Source" return } if (-not (Test-Path -Path $Destination)) { New-Item -ItemType Directory -Force -Path $Destination | Out-Null } Copy-Item -Path (Join-Path $Source '*') -Destination $Destination -Recurse -Force } $settingsFolder = Join-Path $RtManagerRoot 'Settings' $settingsPath = Join-Path $settingsFolder 'SystemSettings.json' $knownTestsFile = Join-Path $RtManagerRoot 'knownautomationtests.txt' New-Item -ItemType Directory -Force -Path $settingsFolder | Out-Null $settings = [ordered]@{ PushToPortal = $true TearDownNeeded = $true ClientId = '' EndpointUrl = '' ApiKey = '' FailoverState = $FailoverState ProxyUrl = '' PushThroughEmail = $false RegressionRunID = 0 } if (-not [string]::IsNullOrWhiteSpace($SystemSettings)) { $extra = $SystemSettings | ConvertFrom-Json foreach ($property in $extra.PSObject.Properties) { $settings[$property.Name] = $property.Value } } # The explicit parameter always wins so a failover phase can rewrite only this value. $settings['FailoverState'] = $FailoverState Write-Host "Writing $settingsPath with FailoverState $FailoverState." ($settings | ConvertTo-Json -Depth 5) | Out-File -FilePath $settingsPath -Encoding utf8 -Force if ($SkipDependencies) { Write-Host 'Dependency deployment was skipped.' return } if ([string]::IsNullOrWhiteSpace($PathToTestPackageContent)) { throw 'PathToTestPackageContent is required unless -SkipDependencies is used.' } if (-not (Test-Path -Path $PathToTestPackageContent)) { throw "The specified path '$PathToTestPackageContent' does not exist." } if (-not $SkipToolInstall) { $pipelineFolder = Join-Path $PathToTestPackageContent 'TestPackagePipeline' $toolFolder = if (Test-Path $pipelineFolder) { $pipelineFolder } else { $PathToTestPackageContent } Push-Location $toolFolder try { Write-Host 'Installing dotnet tool skyline.dataminer.cicd.tools.runautomationscript.' dotnet tool install skyline.dataminer.cicd.tools.runautomationscript --create-manifest-if-needed --add-source https://api.nuget.org/v3/index.json if ($LASTEXITCODE -ne 0) { throw 'Failed to install skyline.dataminer.cicd.tools.runautomationscript.' } dotnet tool restore if ($LASTEXITCODE -ne 0) { throw 'Failed to restore the dotnet tools.' } } finally { Pop-Location } } Stop-ProcessIfRunning -Name 'QADeviceSimulator' $dependenciesPath = Join-Path (Join-Path $PathToTestPackageContent 'TestHarvesting') 'dependencies.generated' if (-not (Test-Path -Path $dependenciesPath)) { $found = Get-ChildItem -Path $PathToTestPackageContent -Recurse -Directory -Filter 'dependencies.generated' -ErrorAction SilentlyContinue | Where-Object { $_.FullName -match '(?i)[\\/]TestHarvesting[\\/]dependencies\.generated$' } | Select-Object -First 1 if (-not $found) { throw "Could not find 'TestHarvesting/dependencies.generated' under '$PathToTestPackageContent'." } $dependenciesPath = $found.FullName } Write-Host "Using dependencies from $dependenciesPath." $folders = @('GlobalDependencies', 'TeamDependencies', 'TestDependencies') foreach ($folder in $folders) { Remove-PathWithRetry -TargetPath (Join-Path $RtManagerRoot $folder) -IsDirectory } Remove-PathWithRetry -TargetPath $knownTestsFile $knownTestsSource = Join-Path $dependenciesPath 'knownautomationtests.generated' if (Test-Path -Path $knownTestsSource -PathType Leaf) { Copy-Item -Path $knownTestsSource -Destination $knownTestsFile -Force } else { Write-Warning "No knownautomationtests.generated found in '$dependenciesPath'." } foreach ($folder in $folders) { Copy-Tree -Source (Join-Path $dependenciesPath $folder) -Destination (Join-Path $RtManagerRoot $folder) } Write-Host "QAFramework agent setup completed. Dependencies are in $RtManagerRoot." |