Skip to content

Commit 356fe9b

Browse files
authored
Refine Windows 10 SDK install command and add tests (#153)
1 parent 18cf230 commit 356fe9b

File tree

6 files changed

+275
-23
lines changed

6 files changed

+275
-23
lines changed

.buildkite/pipeline.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,98 @@ steps:
118118
notify:
119119
- github_commit_status:
120120
context: "pr_changed_files Tests: Edge Cases"
121+
122+
- group: ":windows: install_windows_10_sdk Tests"
123+
steps:
124+
- label: ":windows: install_windows_10_sdk Tests - Version file with valid format and version"
125+
command: |
126+
"20348" | Out-File .windows-10-sdk-version
127+
.\tests\test-install-windows-10-sdk.ps1 -ExpectedExitCode 0
128+
agents:
129+
queue: windows
130+
notify:
131+
- github_commit_status:
132+
context: "install_windows_10_sdk Tests - Version file with valid format and version"
133+
134+
- label: ":windows: install_windows_10_sdk Tests - Version file with one new line"
135+
command: |
136+
"20348`n" | Out-File .windows-10-sdk-version
137+
.\tests\test-install-windows-10-sdk.ps1 -ExpectedExitCode 0
138+
agents:
139+
queue: windows
140+
notify:
141+
- github_commit_status:
142+
context: "install_windows_10_sdk Tests - Version file with one new line"
143+
144+
- label: ":windows: install_windows_10_sdk Tests - Version file with more than one new line"
145+
command: |
146+
"20348`n`n" | Out-File .windows-10-sdk-version
147+
.\tests\test-install-windows-10-sdk.ps1 -ExpectedExitCode 0
148+
agents:
149+
queue: windows
150+
notify:
151+
- github_commit_status:
152+
context: "install_windows_10_sdk Tests - Version file with more than one new line"
153+
154+
- label: ":windows: install_windows_10_sdk Tests - Version file with leading whitespaces"
155+
command: |
156+
" 19041" | Out-File .windows-10-sdk-version
157+
.\tests\test-install-windows-10-sdk.ps1 -ExpectedExitCode 0
158+
agents:
159+
queue: windows
160+
notify:
161+
- github_commit_status:
162+
context: "install_windows_10_sdk Tests - Version file with leading whitespaces"
163+
164+
- label: ":windows: install_windows_10_sdk Tests - Version file with trailing whitespaces"
165+
command: |
166+
"18362 " | Out-File .windows-10-sdk-version
167+
.\tests\test-install-windows-10-sdk.ps1 -ExpectedExitCode 0
168+
agents:
169+
queue: windows
170+
notify:
171+
- github_commit_status:
172+
context: "install_windows_10_sdk Tests - Version file with trailing whitespaces"
173+
174+
- label: ":windows: install_windows_10_sdk Tests - Version file with a word"
175+
command: |
176+
"not an integer" | Out-File .windows-10-sdk-version
177+
.\tests\test-install-windows-10-sdk.ps1 `
178+
-ExpectedExitCode 1 `
179+
-ExpectedErrorKeyphrase "Expected an integer"
180+
agents:
181+
queue: windows
182+
notify:
183+
- github_commit_status:
184+
context: "install_windows_10_sdk Tests - Version file with a word"
185+
186+
- label: ":windows: install_windows_10_sdk Tests - Missing version file"
187+
command: |
188+
.\tests\test-install-windows-10-sdk.ps1 `
189+
-ExpectedExitCode 1 `
190+
-ExpectedErrorKeyphrase "No Windows 10 SDK version file found at .windows-10-sdk-version"
191+
agents:
192+
queue: windows
193+
notify:
194+
- github_commit_status:
195+
context: "install_windows_10_sdk Tests - Version file with a word"
196+
197+
- label: ":windows: install_windows_10_sdk Tests - Version file with version number that is not in the allowed list"
198+
command: |
199+
"12345" | Out-File .windows-10-sdk-version
200+
.\tests\test-install-windows-10-sdk.ps1 `
201+
-ExpectedExitCode 1 `
202+
-ExpectedErrorKeyphrase "Invalid Windows 10 SDK version: 12345"
203+
agents:
204+
queue: windows
205+
notify:
206+
- github_commit_status:
207+
context: "install_windows_10_sdk Tests - Version file with version number that is not in the allowed list"
208+
209+
- label: ":windows: prepare_windows_host_for_app_distribution Tests - Skip Windows 10 SDK Installation"
210+
command: .\tests\test-prepare-windows-host-for-app-distribution.ps1
211+
agents:
212+
queue: windows
213+
notify:
214+
- github_commit_status:
215+
context: "prepare_windows_host_for_app_distribution Tests - Skip Windows 10 SDK Installation"

bin/install_windows_10_sdk.ps1

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,64 @@
1+
# Install the Windows 10 SDK and Visual Studio Build Tools using the value in .windows-10-sdk-version.
2+
#
3+
# The expected .windows-10-sdk-version format is a integer representing a valid SDK component id.
4+
# The list of valid component ids can be found at
5+
# https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022
6+
#
7+
# Example:
8+
#
9+
# 20348
10+
11+
param (
12+
[switch]$DryRun = $false
13+
)
14+
115
# Stop script execution when a non-terminating error occurs
216
$ErrorActionPreference = "Stop"
317

4-
Write-Host "--- :windows: Installing Windows 10 SDK and Visual Studio Build Tools"
18+
Write-Output "--- :windows: Installing Windows 10 SDK and Visual Studio Build Tools"
19+
20+
# See list at https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022
21+
$allowedVersions = @(
22+
"20348",
23+
"19041",
24+
"18362",
25+
"17763",
26+
"17134",
27+
"16299",
28+
"15063",
29+
"14393"
30+
)
531

632
$windowsSDKVersionFile = ".windows-10-sdk-version"
733
if (-not (Test-Path $windowsSDKVersionFile)) {
834
Write-Output "[!] No Windows 10 SDK version file found at $windowsSDKVersionFile."
935
exit 1
1036
}
1137

12-
$windows10SDKVersion = Get-Content $windowsSDKVersionFile
38+
$windows10SDKVersion = (Get-Content -TotalCount 1 $windowsSDKVersionFile).Trim()
39+
40+
if ($windows10SDKVersion -notmatch '^\d+$') {
41+
Write-Output "[!] Invalid version file format."
42+
Write-Output "Expected an integer, got: '$windows10SDKVersion'"
43+
exit 1
44+
}
45+
46+
if ($allowedVersions -notcontains $windows10SDKVersion) {
47+
Write-Output "[!] Invalid Windows 10 SDK version: $windows10SDKVersion"
48+
Write-Output "Allowed versions are:"
49+
foreach ($version in $allowedVersions) {
50+
Write-Output "- $version"
51+
}
52+
Write-Output "More info at https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022"
53+
exit 1
54+
}
55+
56+
Write-Output "Will attempt to set up Windows 10 ($windows10SDKVersion) SDK and Visual Studio Build Tools..."
1357

14-
Write-Host "Will attempt to set up Windows 10 ($windows10SDKVersion) SDK and Visual Studio Build Tools..."
58+
if ($DryRun) {
59+
Write-Output "Running in dry run mode, finishing here."
60+
exit 0
61+
}
1562

1663
# Download the Visual Studio Build Tools Bootstrapper
1764
Write-Output "~~~ Downloading Visual Studio Build Tools..."
@@ -26,7 +73,7 @@ If (-not (Test-Path $buildToolsPath)) {
2673
Write-Output "[!] Failed to download Visual Studio Build Tools"
2774
Exit 1
2875
} else {
29-
Write-Output "Successfully downloaded Visual Studio Build Toosl at $buildToolsPath."
76+
Write-Output "Successfully downloaded Visual Studio Build Tools at $buildToolsPath."
3077
}
3178

3279
# Install the Windows SDK and other required components

bin/path_aware_refreshenv.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
# Stop script execution when a non-terminating error occurs
1717
$ErrorActionPreference = "Stop"
1818

19-
Write-Host "PATH before refreshenv is $env:PATH"
19+
Write-Output "PATH before refreshenv is $env:PATH"
2020
$originalPath = "$env:PATH"
21-
Write-Host "Calling refreshenv..."
21+
Write-Output "Calling refreshenv..."
2222
refreshenv
2323
$mergedPath = "$env:PATH;$originalPath" -split ";" | Select-Object -Unique -Skip 1
2424
$env:PATH = ($mergedPath -join ";")
25-
Write-Host "PATH after refreshenv is $env:PATH"
25+
Write-Output "PATH after refreshenv is $env:PATH"

bin/prepare_windows_host_for_app_distribution.ps1

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,28 @@
88
# - Install the Windows 10 SDK if it detected a `.windows-10-sdk-version` file(2)
99
#
1010
# (1) The certificate it installs is stored in our AWS SecretsManager storage (`windows-code-signing-certificate` secret ID)
11-
# (2) You can skip the Win10 install even if `.windows-10-sdk-version` file is present by using the `SKIP_WINDOWS_10_SDK_INSTALL=1` env var before calling this script
11+
# (2) You can skip the Windows 10 SDK installation regardless of whether `.windows-10-sdk-version` is present by calling the script with `-SkipWindows10SDKInstallation`.
1212
#
1313
# Note: In addition to calling this script, and depending on your client app, you might want to also install `npm` and the `Node.js` packages used by your client app on the agent too. For that part, you should use the `automattic/nvm` Buildkite plugin on the pipeline step's `plugins:` attribute.
1414
#
1515

16+
param (
17+
[switch]$SkipWindows10SDKInstallation = $false
18+
)
19+
1620
# Stop script execution when a non-terminating error occurs
1721
$ErrorActionPreference = "Stop"
1822

19-
Write-Host "--- :windows: Setting up Windows for app distribution"
23+
Write-Output "--- :windows: Setting up Windows for app distribution"
2024

21-
Write-Host "Current working directory: $PWD"
25+
Write-Output "Current working directory: $PWD"
2226

23-
Write-Host "Enable long path behavior"
27+
Write-Output "Enable long path behavior"
2428
# See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation
2529
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
2630

2731
# Disable Windows Defender before starting – otherwise our performance is terrible
28-
Write-Host "Disable Windows Defender..."
32+
Write-Output "Disable Windows Defender..."
2933
$avPreference = @(
3034
@{DisableArchiveScanning = $true}
3135
@{DisableAutoExclusions = $true}
@@ -61,54 +65,59 @@ $avPreference | Foreach-Object {
6165
# https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-compatibility?view=o365-worldwide
6266
$atpRegPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection'
6367
if (Test-Path $atpRegPath) {
64-
Write-Host "Set Microsoft Defender Antivirus to passive mode"
68+
Write-Output "Set Microsoft Defender Antivirus to passive mode"
6569
Set-ItemProperty -Path $atpRegPath -Name 'ForceDefenderPassiveMode' -Value '1' -Type 'DWORD'
6670
}
6771

6872
# From https://stackoverflow.com/a/46760714
69-
Write-Host "--- :windows: Setting up Package Manager"
73+
Write-Output "--- :windows: Setting up Package Manager"
7074
$env:ChocolateyInstall = Convert-Path "$((Get-Command choco).Path)\..\.."
7175
Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
7276

7377
# This should avoid issues with symlinks not being supported in Windows.
7478
#
7579
# See how this build failed
7680
# https://buildkite.com/automattic/beeper-desktop/builds/2895#01919738-7c6e-4b82-8d1d-1c1800481740
77-
Write-Host "--- :windows: :linux: Enable developer mode to use symlinks"
81+
Write-Output "--- :windows: :linux: Enable developer mode to use symlinks"
7882

7983
$developerMode = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
8084

8185
if ($developerMode.State -eq 'Enabled') {
82-
Write-Host "Developer Mode is already enabled."
86+
Write-Output "Developer Mode is already enabled."
8387
} else {
84-
Write-Host "Enabling Developer Mode..."
88+
Write-Output "Enabling Developer Mode..."
8589
try {
8690
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart
8791
} catch {
88-
Write-Host "Failed to enable Developer Mode. Continuing without it..."
92+
Write-Output "Failed to enable Developer Mode. Continuing without it..."
8993
}
9094
}
9195

92-
Write-Host "--- :lock_with_ink_pen: Download Code Signing Certificate"
96+
Write-Output "--- :lock_with_ink_pen: Download Code Signing Certificate"
9397
$certificateBinPath = "certificate.bin"
9498
$EncodedText = aws secretsmanager get-secret-value --secret-id windows-code-signing-certificate `
9599
| jq -r '.SecretString' `
96100
| Out-File $certificateBinPath
97101
$certificatePfxPath = "certificate.pfx"
98102
certutil -decode $certificateBinPath $certificatePfxPath
99-
Write-Host "Code signing certificate downloaded at: $((Get-Item $certificatePfxPath).FullName)"
103+
Write-Output "Code signing certificate downloaded at: $((Get-Item $certificatePfxPath).FullName)"
100104

101-
Write-Host "--- :windows: Checking whether to install Windows 10 SDK..."
105+
Write-Output "--- :windows: Checking whether to install Windows 10 SDK..."
102106

103107
# When using Electron Forge and electron2appx, building Appx requires the Windows 10 SDK
104108
#
105109
# See https://github.com/hermit99/electron-windows-store/tree/v2.1.2?tab=readme-ov-file#usage
106110

111+
if ($SkipWindows10SDKInstallation) {
112+
Write-Output "Run with SkipWindows10SDKInstallation = true. Skipping Windows 10 SDK installation check."
113+
exit 0
114+
}
115+
107116
$windowsSDKVersionFile = ".windows-10-sdk-version"
108117
if (Test-Path $windowsSDKVersionFile) {
109-
Write-Host "Found $windowsSDKVersionFile file, installing Windows 10 SDK..."
118+
Write-Output "Found $windowsSDKVersionFile file, installing Windows 10 SDK..."
110119
& "$PSScriptRoot\install_windows_10_sdk.ps1"
111120
If ($LastExitCode -ne 0) { Exit $LastExitCode }
112121
} else {
113-
Write-Host "No $windowsSDKVersionFile file found, skipping Windows 10 SDK installation."
122+
Write-Output "No $windowsSDKVersionFile file found, skipping Windows 10 SDK installation."
114123
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
param (
2+
[int]$ExpectedExitCode = 0,
3+
[string]$ExpectedErrorKeyphrase = ""
4+
)
5+
6+
# Ensure the output is UTF-8 encoded so we can use emojis...
7+
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8
8+
$emojiGreenCheck = "$([char]0x2705)"
9+
$emojiRedCross = "$([char]0x274C)"
10+
11+
Write-Output "Running test-install-windows-10-sdk.ps1 with ExpectedExitCode=$ExpectedExitCode and ExpectedErrorKeyphrase=$ExpectedErrorKeyphrase"
12+
13+
if (($ExpectedExitCode -eq 0) -and ($ExpectedErrorKeyphrase -ne "")) {
14+
Write-Output "$emojiRedCross Expected call to succeed (expected error code = 0), but given an error keyphrase to check."
15+
exit 1
16+
}
17+
18+
$output = & "$PSScriptRoot\..\bin\install_windows_10_sdk.ps1" -DryRun
19+
$exitCode = $LASTEXITCODE
20+
21+
if ($exitCode -ne $ExpectedExitCode) {
22+
Write-Output "$emojiRedCross Expected exit code $ExpectedExitCode, got $exitCode"
23+
Write-Output "Output was:"
24+
Write-Output "$output"
25+
exit 1
26+
} else {
27+
Write-Output "$emojiGreenCheck Exit code matches expected value ($ExpectedExitCode)"
28+
}
29+
30+
# Only check error keyphrase if exit code is not 0
31+
if ($exitCode -eq 0) {
32+
exit 0
33+
}
34+
35+
# If keyphrase is empty, assume the caller is satisfied with only testing the exit code
36+
if ($ExpectedErrorKeyphrase -eq "") {
37+
Write-Output "Exit code match expectation and no error keyphrase was provided. Test completed."
38+
exit 0
39+
}
40+
41+
if ($output -match [regex]::Escape($ExpectedErrorKeyphrase)) {
42+
Write-Output "$emojiGreenCheck Error keyphrase matches expected value ($ExpectedErrorKeyphrase)"
43+
Write-Output "Test completed."
44+
} else {
45+
Write-Output "$emojiRedCross Expected error to contain '$ExpectedErrorKeyphrase', but got:"
46+
Write-Output "$output"
47+
exit 1
48+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Tests the prepare_windows_host_for_app_distribution.ps1 script with the -SkipWindows10SDKInstallation parameter.
2+
#
3+
# We only test the skip behavior because the installation takes a "long" time to run.
4+
5+
param (
6+
[int]$ExpectedExitCode = 0
7+
)
8+
9+
# Ensure the output is UTF-8 encoded so we can use emojis...
10+
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8
11+
$emojiGreenCheck = "$([char]0x2705)"
12+
$emojiRedCross = "$([char]0x274C)"
13+
14+
Write-Output "Testing prepare_windows_host_for_app_distribution.ps1 with -SkipWindows10SDKInstallation"
15+
16+
# Create a valid SDK version file to ensure it's not being used
17+
$sdkVersion = "20348"
18+
"$sdkVersion" | Out-File .windows-10-sdk-version
19+
20+
# Run the script with skip parameter
21+
$output = & "$PSScriptRoot\..\bin\prepare_windows_host_for_app_distribution.ps1" -SkipWindows10SDKInstallation
22+
$exitCode = $LASTEXITCODE
23+
24+
# Check exit code
25+
if ($exitCode -ne $ExpectedExitCode) {
26+
Write-Output "$emojiRedCross Expected exit code $ExpectedExitCode, got $exitCode"
27+
Write-Output "Output was:"
28+
Write-Output "$output"
29+
exit 1
30+
} else {
31+
Write-Output "$emojiGreenCheck Exit code matches expected value ($ExpectedExitCode)"
32+
}
33+
34+
$expectedSkipMessage = "Run with SkipWindows10SDKInstallation = true. Skipping Windows 10 SDK installation check."
35+
if ($output -match [regex]::Escape($expectedSkipMessage)) {
36+
Write-Output "$emojiGreenCheck Found expected skip message in output"
37+
} else {
38+
Write-Output "$emojiRedCross Expected to find message about skipping due to parameter, but got:"
39+
Write-Output "$output"
40+
exit 1
41+
}
42+
43+
# Verify SDK was not installed by checking the file system
44+
$windowsSDKsRoot = "C:\Program Files (x86)\Windows Kits\10\bin"
45+
$sdkPath = "$windowsSDKsRoot\10.0.$sdkVersion\x64"
46+
If (Test-Path $sdkPath) {
47+
Write-Output "$emojiRedCross Found SDK installation at $sdkPath when it should have been skipped"
48+
exit 1
49+
} else {
50+
Write-Output "$emojiGreenCheck Confirmed SDK was not installed at $sdkPath"
51+
}
52+
53+
Write-Output "Test completed successfully."

0 commit comments

Comments
 (0)