#launch example #powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'cmd.exe' -ArgumentList @('/c', 'getzig.cmd') -NoNewWindow -Wait" #powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'getzig.cmd' -NoNewWindow -Wait" #Join-Path using verbose method to support powershell 5? #$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.." $outbase = $PSScriptRoot $outbase = Resolve-Path -Path $outbase $toolsfolder = Join-Path -Path $outbase -ChildPath "tools" if (-not(Test-Path -Path $toolsfolder -PathType Container)) { #create folder - (can include missing intermediaries) New-Item -Path $toolsfolder -ItemType Directory } $zigfolder = Join-Path $toolsfolder -ChildPath "zig" $zigexe = Join-Path $zigfolder "zig.exe" $releasearchive = "zig-x86_64-windows-0.15.1.zip" ;#zip on windows, tarball on every other platform Write-Output "powershell version: $($PSVersionTable.PSVersion)" if (Get-Command $zigexe -ErrorAction SilentlyContinue) { Write-Host "zig.exe is installed in tools/zig" $zigv = tools/zig/zig.exe version 2>&1 $stdout = $zigv | Where-Object {$_ -is [string]} $stderr = $zigv | Where-Object {$_ -is [System.Management.Automation.ErrorRecord]} if ($stderr) { Write-Host "Unexpected output from tools/zig/zig.exe: $stderr" Write-Host "Consider deleting tools/zig and re-downloading" } else { Write-Host "tools/zig/zig.exe version is: $stdout" } exit } if (Get-Command "minisign" -ErrorAction SilentlyContinue) { Write-Host "minisign is available" } else { Write-Host "minisign is missing. Will attempt to install using winget." #Find-Module/Install-Module: older mechanism, available in powershell #Find-PSResource/Install-PSResource: only available in newer pwsh etc? $wgclient = Get-Module -ListAvailable -Name Microsoft.WinGet.Client if (${wgclient}.Length -eq 0) { Write-Host "Microsoft.WinGet.Client module not installed.. will try to install." Install-PackageProvider -Name NuGet -Force $psgallery_existing_policy = (Get-PSRepository -Name PSGallery).InstallationPolicy if ($psgallery_existing_policy -eq "Untrusted") { #Applies to all versions of PowerShell for the user, and is persistent for current user. #This has risks in that a powershell session started after this call, and before we reset it, will treat PSGallery as trusted Set-PSRepository -Name PSGallery -InstallationPolicy Trusted } Install-Module -Scope CurrentUser -Name Microsoft.Winget.Client -Force -Repository PSGallery Repair-WinGetPackageManager import-module -name Microsoft.Winget.client if ($psgallery_existing_policy -eq "Untrusted") { Set-PSRepository -Name PSGallery -InstallationPolicy Untrusted } } else { Write-Host "Microsoft.WinGet.Client is available" } $wingetversion = (Find-WinGetPackage jedisct1.minisign).Version if ($wingetversion) { Write-Host "Installing minisign version: ${wingetversion}" Install-WinGetPackage -Id "jedisct1.minisign" } if (Get-Command "minisign" -ErrorAction SilentlyContinue) { Write-Host "minisign is now available" } else { Write-Host "minisign is still not available" #if we automatically relaunch - we could get stuck in a loop - ask user. $response = read-host -Prompt "Relaunching process may make minizip available. Relaunch? Y|N" #if ($PSVersionTable.PSEdition -eq "Desktop") { #powershell.exe #} else { #pwsh.exe #} if ($response -ieq "y") { Start-Process 'getzig.cmd' -NoNewWindow -Wait } exit } } $zigpubkey = "RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U" $mirrors_url = "https://ziglang.org/download/community-mirrors.txt" $mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url) if ($mirrors_response.StatusCode -eq 200) { #https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win64/tools/zig-x86_64-windows-0.15.1.zip $mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win64/tools") $mirror_array += $mirrors_response.Content.TrimEnd("`r`n") -split "`r`n|`n" #$mirror_array += "https://bogusxxx.org" #test behaviour of a bogus/down entry $mirror_array += "https://ziglang.org" #main site $dict_mirrors = [ordered]@{} $host_list = @() #same ordering as dict_mirrors foreach ($mirror in $mirror_array) { $uri = New-Object System.Uri($mirror) $hostname = $uri.Host $dict_mirrors[$hostname] = @{} $dict_mirrors[$hostname]["uri"] = $mirror $dict_mirrors[$hostname]["latency"] = 888888 ;#default $host_list += $hostname #write-host "Host name: $hostname" } #write-host "dict: $($dict_mirrors | out-String)" write-host "host_list: $host_list" $automation_name = "punkshell+julian@precisium.com.au_target_by_latency" $trace = test-netconnection gitea1.intx.com.au -Hops 6 -TraceRoute -ErrorAction Ignore if ((${trace}.PingSucceeded) -and (${trace}.TraceRoute.Count -lt 5)) { $dict_mirrors["gitea1.intx.com.au"]["latency"] = 2 #short-circuit for hosts very near gitea1.intx.com.au #don't even test others. This is primarily for hosts at intx.com.au and associated entities - which are more likely to use punkshell than anyone else. } else { if ($PSVersionTable.PSEdition -eq "Desktop") { #powershell.exe #we seem to need -ErrorAction Ignore for bad/unresponsive host entries - but unlike with pwsh, we don't get any corresponding entry in the test_results, and -Quiet doesn't seem to give us results either REVIEW $test_results = Test-Connection $host_list -Count 1 -ErrorAction Ignore for ($i = 0; $i -lt $test_results.Count; $i++) { $result = $test_results[$i] if ($result) { $targethost = $result.Address if ($result.StatusCode -eq 0) { $dict_mirrors[$targethost]["latency"] = $result.ResponseTime } else { $dict_mirrors[$targethost]["latency"] = 999999 } } else { $targethost = $host_list[$i] $dict_mirrors[$targethost]["latency"] = 999999 } } } else { #pwsh.exe $test_results = Test-Connection -TargetName $host_list -Count 1 -Ipv4 -Detailed -TcpPort 443 -Quiet for ($i = 0; $i -lt $test_results.Count; $i++) { $result = $test_results[$i] if ($result) { $targethost = $result.Target if ($result.Status -eq "Success") { $dict_mirrors[$targethost]["latency"] = $result.Latency } else { $dict_mirrors[$targethost]["latency"] = 999999 } } else { $targethost = $host_list[$i] $dict_mirrors[$targethost]["latency"] = 999999 } } } } $list_mirror_dicts = @() #write-host "dict tested: $($dict_mirrors | Out-String)" foreach ($key in $dict_mirrors.Keys) { $list_mirror_dicts += $($dict_mirrors[$key]) } #need to ensure latency cast to integer (on powershell 5 at least) $sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property { [int]$_.latency } #Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)" Write-Host "Sorted by latency: $($sorted_mirror_dicts | Out-String)" foreach ($hostinfo in $sorted_mirror_dicts) { $uristring = $hostinfo.uri if ($uristring -eq "https://ziglang.org") { $full_uristring = "${uristring}/download/0.15.1/${releasearchive}?source=${automation_name}" $sig_uristring = "${uristring}/download/0.15.1/${releasearchive}.minisig?source=${automation_name}" } else { $full_uristring = "${uristring}/${releasearchive}?source=${automation_name}" $sig_uristring = "${uristring}/${releasearchive}.minisig?source=${automation_name}" } Write-Host "Downloading zig from $full_uristring" #$uriobj = [uri]$full_uristring #$lastSegment = $uriobj.Segments[-1] #$outfile = Join-Path $toolsfolder -ChildPath $lastSegment $outfile = Join-Path $toolsfolder -ChildPath $releasearchive Write-Host "Download to: $outfile" Invoke-WebRequest -Uri $full_uristring -OutFile $outfile if (-not(Test-Path -Path $outfile -PathType Leaf)) { write-Host "Failed to download zig package from $full_uristring to ${outfile} .. aborting download from $uristring" continue } Write-Host "Downloading minisig signature from $sig_uristring" Invoke-WebRequest -Uri $sig_uristring -Outfile "${outfile}.minisig" if (-not(Test-Path -Path "${outfile}.minisig" -PathType Leaf)) { write-Host "Failed to download minisig from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring" continue } write-host "downloaded $outfile and ${outfile}.minisig - validating signature..." #validate releasearchive (tarball/zip) $sigresult = minisign -V -P $zigpubkey -m $outfile 2>&1 $stdout = $sigresult | Where-Object {$_ -is [string]} $stderr = $sigresult | Where-Object {$_ -is [System.Management.Automation.ErrorRecord]} $is_valid = $false if ($stderr) { write-host "Signature validation failed with message: $stderr" } else { if (($stdout | Out-String).Contains("signature verified")) { write-host $stdout $is_valid = $true } else { write-host "Unexpected output from minisign: $stdout" write-host "Did not contain 'signature verified'" } } if (-not($is_valid)) { write-Host "Couldn't verify signature from download site $uristring" Remove-Item -Path $outfile -ErrorAction SilentlyContinue Remove-Item -Path "${outfile}.minisig" -ErrorAction SilentlyContinue continue } Write-Host "Signature OK - extracting archive" Expand-Archive -path $outfile -DestinationPath $toolsfolder -Force #Remove-Item -Path "$outfile" $zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive) #Rename-Item -Path write-host "zip_rootname: $zip_rootname" Rename-Item -Path $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) -NewName $zigfolder Write-Host "Zig installed in ${zigfolder}" $zigexe = Join-Path $zigfolder -ChildPath "zig.exe" $v = Invoke-Expression "$zigexe version" Write-Host "ZIG VERSION: ${v}" $test_ok = 1 ;#todo if ($test_ok) { break } } } else { Write-Host "Unable to retrieve list of zig community mirrors from $mirrors_url" }