# Prefer a Gitea-hosted node:20-alpine so docker build does not HEAD registry-1.docker.io. # Order: Gitea -> optional NODE_IMAGE_SOURCE -> regional/official mirrors -> Docker Hub last. # ASCII only: Windows PowerShell 5.1 + act_runner mis-parses backtick escapes in this file. param( [Parameter(Mandatory = $true)][string]$RegistryPrefix, [string]$OutFile = '.ci-node-image', [string]$HubImage = 'node:20-alpine', [AllowEmptyString()] [string]$ExtraSources = '' ) $ErrorActionPreference = 'Continue' $mirror = "$RegistryPrefix/node:20-alpine" $nl = [char]10 function Test-Image([string]$Name) { docker image inspect $Name 2>&1 | Out-Null return ($LASTEXITCODE -eq 0) } function Invoke-Pull([string]$Name, [int]$Attempts) { for ($i = 1; $i -le $Attempts; $i++) { Write-Host "docker pull $Name (attempt $i/$Attempts)" docker pull $Name if ($LASTEXITCODE -eq 0) { return $true } if ($i -lt $Attempts) { Start-Sleep -Seconds 5 } } return $false } function Save-Choice([string]$Name) { $utf8 = New-Object System.Text.UTF8Encoding $false $path = Join-Path (Get-Location) $OutFile [System.IO.File]::WriteAllText($path, ($Name + $nl), $utf8) Write-Host "NODE_IMAGE=$Name" } function Publish-Mirror([string]$Src) { Write-Host "Tagging $Src as $mirror" docker tag $Src $mirror if ($LASTEXITCODE -ne 0) { return $false } docker push $mirror if ($LASTEXITCODE -ne 0) { Write-Host "Could not push $mirror - docker build will use the local tag (legacy builder)." $flag = Join-Path (Get-Location) '.ci-use-legacy-builder' New-Item -ItemType File -Path $flag -Force | Out-Null } Save-Choice $mirror return $true } if (Test-Image $mirror) { Write-Host "Using local $mirror" Save-Choice $mirror exit 0 } if (Invoke-Pull $mirror 1) { Save-Choice $mirror exit 0 } $sources = New-Object System.Collections.ArrayList if (-not [string]::IsNullOrWhiteSpace($ExtraSources)) { foreach ($part in ($ExtraSources -split ',')) { $src = $part.Trim() if ($src.Length -gt 0) { [void]$sources.Add($src) } } } # Iran-reachable proxy of Docker Hub official images, then public official mirrors, Hub last. foreach ($src in @( 'docker.arvancloud.ir/library/node:20-alpine', 'public.ecr.aws/docker/library/node:20-alpine', 'mirror.gcr.io/library/node:20-alpine', $HubImage )) { if (-not $sources.Contains($src)) { [void]$sources.Add($src) } } foreach ($src in $sources) { if (Test-Image $src) { Write-Host "Found local $src" if (Publish-Mirror $src) { exit 0 } } } foreach ($src in $sources) { if (Invoke-Pull $src 2) { if (Publish-Mirror $src) { exit 0 } } } Write-Host "Could not pull node:20-alpine from Gitea, mirrors, or Docker Hub." Write-Host "Set repository variable NODE_IMAGE_SOURCE to a reachable image, for example:" Write-Host " docker.arvancloud.ir/library/node:20-alpine" Write-Host "Or on the Windows runner:" Write-Host " docker pull docker.arvancloud.ir/library/node:20-alpine" Write-Host " docker tag docker.arvancloud.ir/library/node:20-alpine $mirror" Write-Host " docker push $mirror" exit 1