mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
81 lines
5.1 KiB
PowerShell
81 lines
5.1 KiB
PowerShell
# Load operator-owned network settings without evaluating code or logging their values.
|
|
function Read-RunnerNetwork([string]$ConfigRoot) {
|
|
$path = Join-Path $ConfigRoot 'runner-network.json'
|
|
if (-not (Test-Path -LiteralPath $path)) { return $null }
|
|
try { $config = Get-Content -LiteralPath $path -Raw | ConvertFrom-Json -AsHashtable -ErrorAction Stop }
|
|
catch { throw 'Cannot read runner-network.json; inspect its JSON locally.' }
|
|
$keys = @('proxyUrl','noProxy','serviceName','probeUrl','attempts','timeoutSeconds','retrySeconds')
|
|
if ($config -isnot [Collections.IDictionary] -or $config.Count -ne $keys.Count -or @($config.Keys | Where-Object { $_ -cnotin $keys }).Count) {
|
|
throw 'runner-network.json requires exactly proxyUrl, noProxy, serviceName, probeUrl, attempts, timeoutSeconds and retrySeconds.'
|
|
}
|
|
foreach ($key in @('proxyUrl','noProxy','serviceName','probeUrl')) {
|
|
if ($config[$key] -isnot [string] -or $config[$key] -match '[\r\n\x00]') { throw 'Invalid network string setting; inspect runner-network.json locally.' }
|
|
}
|
|
if ([Management.Automation.WildcardPattern]::ContainsWildcardCharacters($config.serviceName)) { throw 'Network service must be an exact name.' }
|
|
foreach ($key in @('attempts','timeoutSeconds','retrySeconds')) {
|
|
if ($config[$key] -isnot [long] -and $config[$key] -isnot [int]) { throw 'Network budgets must be integers.' }
|
|
if ($config[$key] -lt 1 -or $config[$key] -gt 60) { throw 'Network budgets must be between 1 and 60.' }
|
|
}
|
|
foreach ($key in @('proxyUrl','probeUrl')) {
|
|
if ($key -eq 'proxyUrl' -and $config[$key] -eq '') { continue }
|
|
$uri = $null
|
|
if (-not [Uri]::TryCreate($config[$key], [UriKind]::Absolute, [ref]$uri) -or $uri.Scheme -notin @('http','https') -or $uri.UserInfo -or $uri.Query -or $uri.Fragment) {
|
|
throw 'Network URLs must be absolute HTTP(S) URLs without credentials, queries or fragments.'
|
|
}
|
|
if ($key -eq 'proxyUrl' -and $uri.AbsolutePath -ne '/') { throw 'Proxy URL must not contain a path.' }
|
|
}
|
|
return $config
|
|
}
|
|
|
|
# Called after the runner environment is scrubbed; only declared network values reach child jobs.
|
|
function Set-RunnerNetwork($Config) {
|
|
if ($null -eq $Config) { return }
|
|
[Environment]::SetEnvironmentVariable('HTTP_PROXY', $Config.proxyUrl, 'Process')
|
|
[Environment]::SetEnvironmentVariable('HTTPS_PROXY', $Config.proxyUrl, 'Process')
|
|
[Environment]::SetEnvironmentVariable('NO_PROXY', $Config.noProxy, 'Process')
|
|
[Environment]::SetEnvironmentVariable('NODE_USE_ENV_PROXY', '1', 'Process')
|
|
}
|
|
|
|
# Only probe retries are allowed here. Service recovery belongs to its installed Windows service.
|
|
function Wait-RunnerNetwork($Config) {
|
|
if ($null -eq $Config) { return }
|
|
$info = [Diagnostics.ProcessStartInfo]::new((Get-Command node -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source)
|
|
$info.UseShellExecute = $false
|
|
$info.CreateNoWindow = $true
|
|
$info.RedirectStandardOutput = $true
|
|
$info.RedirectStandardError = $true
|
|
$info.Environment['DSH_NETWORK_PROBE_URL'] = $Config.probeUrl
|
|
$info.Environment['DSH_NETWORK_PROBE_TIMEOUT'] = [string]($Config.timeoutSeconds * 1000)
|
|
$info.ArgumentList.Add('--input-type=module')
|
|
$info.ArgumentList.Add('-e')
|
|
$info.ArgumentList.Add('try { const r = await fetch(process.env.DSH_NETWORK_PROBE_URL, { method: "HEAD", redirect: "error", signal: AbortSignal.timeout(Number(process.env.DSH_NETWORK_PROBE_TIMEOUT)) }); await r.body?.cancel(); process.exit(r.ok ? 0 : 1); } catch { process.exit(1); }')
|
|
for ($attempt = 1; $attempt -le $Config.attempts; $attempt++) {
|
|
$ready = $true
|
|
if ($Config.serviceName) {
|
|
try { $service = Get-Service -Name $Config.serviceName -ErrorAction Stop }
|
|
catch { throw 'Configured network service is unavailable; inspect its installation locally.' }
|
|
$ready = $service.Status -eq 'Running'
|
|
}
|
|
if ($ready) {
|
|
$process = [Diagnostics.Process]::new()
|
|
$process.StartInfo = $info
|
|
try {
|
|
if (-not $process.Start()) { throw 'Cannot launch network probe.' }
|
|
$out = $process.StandardOutput.ReadToEndAsync()
|
|
$err = $process.StandardError.ReadToEndAsync()
|
|
if (-not $process.WaitForExit(($Config.timeoutSeconds + 5) * 1000)) {
|
|
$process.Kill($true)
|
|
$process.WaitForExit()
|
|
$ready = $false
|
|
} else { $ready = $process.ExitCode -eq 0 }
|
|
$null = $out.GetAwaiter().GetResult()
|
|
$null = $err.GetAwaiter().GetResult()
|
|
} finally { $process.Dispose() }
|
|
}
|
|
if ($ready) { Write-Output 'Runner network dependency ready (Node HEAD probe).'; return }
|
|
Write-Output "Runner network dependency not ready (probe $attempt/$($Config.attempts))."
|
|
if ($attempt -lt $Config.attempts) { Start-Sleep -Seconds $Config.retrySeconds }
|
|
}
|
|
throw 'Runner network dependency unavailable; runner was not started. Inspect local service and network configuration. No job or signing retry was requested.'
|
|
}
|