@@ -77,10 +77,147 @@ runs:
77
77
}
78
78
}
79
79
80
+ function Invoke-Download {
81
+ Param
82
+ (
83
+ [Parameter(Mandatory)]
84
+ [String] $URL,
85
+ [Alias("Destination")]
86
+ [Int] $Retries = 20,
87
+ [Int] $RetryInterval = 30
88
+ )
89
+
90
+ $InvalidCharacters = [IO.Path]::GetInvalidFileNameChars() -Join ''
91
+ $RE = "[{0}]" -f [RegEx]::Escape($InvalidCharacters)
92
+ $FileName = [IO.Path]::GetFileName($URL) -Replace $RE
93
+
94
+ if ([String]::IsNullOrEmpty($FileName)) {
95
+ $FileName = [System.IO.Path]::GetRandomFileName()
96
+ }
97
+ $Path = Join-Path -Path "${env:Temp}" -ChildPath $FileName
98
+
99
+ Write-Host "Downloading package from $URL to $Path..."
100
+
101
+ $StartTime = Get-Date
102
+ do {
103
+ try {
104
+ $AttemptStartTime = Get-Date
105
+ (New-Object System.Net.WebClient).DownloadFile($URL, $Path)
106
+ $AttemptDuration = [math]::Round(($(Get-Date) - $AttemptStartTime).TotalSeconds, 2)
107
+ Write-Host "Package downloaded in $AttemptDuration seconds"
108
+ break
109
+ } catch {
110
+ $AttemptDuration = [math]::Round(($(Get-Date) - $AttemptStartTime).TotalSeconds, 2)
111
+ Write-Warning "Package download failed after $AttemptDuration seconds"
112
+ Write-Warning $_.Exception.Message
113
+ }
114
+
115
+ if ($Retries -eq 1) {
116
+ $Duration = [math]::Round(($(Get-Date) - $StartTime).TotalSeconds, 2)
117
+ throw "Package download failed after $Duration seconds"
118
+ }
119
+
120
+ Write-Warning "Waiting $RetryInterval seconds before retrying (retries remaining: $($Retries - 1))..."
121
+ Start-Sleep -Seconds $RetryInterval
122
+ } while (--$Retries -gt 0)
123
+
124
+ return $Path
125
+ }
126
+
127
+ function Verify-Checksum {
128
+ Param
129
+ (
130
+ [Parameter(Mandatory)]
131
+ [String] $Actual,
132
+ [Parameter(Mandatory)]
133
+ [String] $Expected
134
+ )
135
+
136
+ Write-Verbose "Performing Checksum Verification"
137
+ if ($Actual -eq $Expected) {
138
+ Write-Verbose "Checksum verification passed"
139
+ } else {
140
+ throw "Checksum verification failure (Actual: $Actual vs Expected: $Expected)"
141
+ }
142
+ }
143
+
144
+ function Invoke-Installer {
145
+ Param
146
+ (
147
+ [Parameter(Mandatory, ParameterSetName = "URL")]
148
+ [String] $URL,
149
+ [Parameter(Mandatory, ParameterSetName = "LocalPath")]
150
+ [String] $LocalPath,
151
+ [ValidateSet("MSI", "EXE")]
152
+ [String] $Type,
153
+ [String[]] $InstallArgs = $null, # Use default for installer format
154
+ [String[]] $ExtraInstallArgs = @(),
155
+ [String] $ExpectedSHA256
156
+ )
157
+
158
+ if ($PSCmdlet.ParameterSetName -eq "LocalPath") {
159
+ if (-not (Test-Path -Path $LocalPath)) {
160
+ throw "LocalPath parameter is specified, but the file does not exist"
161
+ }
162
+ $FilePath = $LocalPath
163
+ } else {
164
+ $FileName = [System.IO.Path]::GetFileName($URL)
165
+ $FilePath = Invoke-Download -URL $URL
166
+ }
167
+
168
+ if ($ExpectedSHA256) {
169
+ $Hash = (Get-FileHash -Path $FilePath -Algorithm SH256).Hash
170
+ Verify-Checksum -Actual $Hash -Expected $ExpectedSHA256
171
+ }
172
+
173
+ if (-not $Type) {
174
+ $Type = ([System.IO.Path]::GetExtension($FilePath)).Replace(".", "").ToUpper()
175
+ }
176
+
177
+ switch ($Type) {
178
+ "EXE" {
179
+ if (-not $InstallArgs) { $InstallArgs = @() }
180
+ $InstallArgs += $ExtraInstallArgs
181
+ }
182
+ "MSI" {
183
+ if (-not $InstallArgs) {
184
+ Write-Host "Using default MSI arguments: /i, /qn, /norestart"
185
+ $InstallArgs = @("/i", $FilePath, "/qn", "/norestart")
186
+ }
187
+
188
+ $InstallArgs += $ExtraInstallArgs
189
+ $FilePath = "msiexec.exe"
190
+ }
191
+ default {
192
+ throw "Unknown installer type (${Type}), please specify via `-Type` parameter"
193
+ }
194
+ }
195
+
196
+ $StartTime = Get-Date
197
+ Write-Host "Starting Install..."
198
+ try {
199
+ $Process = Start-Process -FilePath $FilePath -ArgumentList $InstallArgs -Wait -PassThru -Verb RunAs
200
+ $ExitCode = $Process.ExitCode
201
+ $Duration = [math]::Round(($(Get-Date) - $StartTime).TotalSeconds, 2)
202
+ switch ($ExitCode) {
203
+ 0 { Write-Host "Installation successful in $Duration seconds" }
204
+ 3010 { Write-Host "Installation successful in $Duration seconds; reboot required"}
205
+ default {
206
+ Write-Host "Installation process returned unexpected exit code: $ExitCode"
207
+ Write-Host "Time elapsed: $Duration seconds"
208
+ exit $ExitCode
209
+ }
210
+ }
211
+ } catch {
212
+ $Duration = [math]::Round(($(Get-Date) - $StartTime).TotalSeconds, 2)
213
+ Write-Host "Installation failed after $Duration seconds"
214
+ }
215
+ }
216
+
80
217
if ("${{ steps.validation.outputs.use_custom_url }}" -eq "1") {
81
- Install-Binary -FilePath "${{ inputs.release-asset-name }}" -ArgumentList ("-q ")
218
+ Invoke-Installer -FilePath "${{ inputs.release-asset-name }}" -InstallArgs ("/quiet ")
82
219
} else {
83
- Install-Binary -Url "https://download.swift.org/${{ inputs.branch }}/windows10/swift-${{ inputs.tag }}/swift-${{ inputs.tag }}-windows10.exe" -Name "installer.exe" -ArgumentList ("-q ")
220
+ Invoke-Installer -URL "https://download.swift.org/${{ inputs.branch }}/windows10/swift-${{ inputs.tag }}/swift-${{ inputs.tag }}-windows10.exe" -InstallArgs ("/quiet ")
84
221
}
85
222
Update-EnvironmentVariables
86
223
0 commit comments