Skip to content

Conversation

@mokagio
Copy link
Contributor

@mokagio mokagio commented Feb 4, 2025

Tested via Automattic/studio#882 and https://github.com/beeper/beeper-desktop-new/pull/1970

  • After realizing that nvm-buildkite-plugin does a better job at setting up Node.js and the custom logic we had in the prepare_windows_host_for_node.ps1 script, I remove said logic from the script
  • Also renamed the script to prepare_windows_host_for_app_distribution.ps1 which I find better explains the script purpose. Besides, now that it no longer sets up Node.js, the name would have been inappropriate.
  • New command to install Windows 10 SDK, reading from the .windows-10-sdk-version file in the repo — Extracted from Studio and currently duplicated in other apps
  • prepare_windows_host_for_app_distribution.ps1 automatically runs the Windows 10 install script if needed, so clients don't have to call two commands

  • I have considered if this change warrants release notes and have added them to the appropriate section in the CHANGELOG.md if necessary.

@mokagio mokagio force-pushed the mokagio/more-windows-utils branch from 7d9f5fc to 76bff10 Compare February 14, 2025 06:36
@mokagio mokagio force-pushed the mokagio/more-windows-utils branch from 76bff10 to cb3e3ff Compare February 14, 2025 06:58
@mokagio mokagio force-pushed the mokagio/more-windows-utils branch from f57b840 to d707ff5 Compare February 17, 2025 03:49
Comment on lines 86 to 99
Write-Host "--- :windows: Checking whether to install Windows 10 SDK..."

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

$windowsSDKVersionFile = ".windows-10-sdk-version"
if (Test-Path $windowsSDKVersionFile) {
Write-Host "Found $windowsSDKVersionFile file, installing Windows 10 SDK..."
& "$PSScriptRoot\install_windows_10_sdk.ps1"
If ($LastExitCode -ne 0) { Exit $LastExitCode }
} else {
Write-Host "No $windowsSDKVersionFile file found, skipping Windows 10 SDK installation."
}
Copy link
Contributor Author

@mokagio mokagio Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example of this finding the SDK file

image

Example of this not finding the SDK file

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that I'm unsure of is whether we should provide a way to bypass or modify this behavior.

Example:

  • Something might be broken in the plugin and a client might need to install the SDK manually; or
  • For whichever reason, it's not possible to use the default file name for the SDK version

I don't think we need to stress much about implementing this flexibility from the get go, so if you agree I'd leave it as a followup, but the code feels incomplete or suboptimal without it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

I wouldn't mind adding an escape hatch, that might be a good idea indeed (though one could argue that'd be YAGNI…)

If it's easy enough to implement and doesn't complicate the script logic too much (which I wouldn't expect to), I'd say go for it.

@mokagio mokagio changed the title Add command to install Windows 10 SDK Windows: Install Win 10 SDK, clearer name, no Node.js setup Feb 17, 2025
@mokagio mokagio requested review from a team, AliSoftware and iangmaia February 17, 2025 23:15
@mokagio mokagio marked this pull request as ready for review February 17, 2025 23:15
Comment on lines 86 to 99
Write-Host "--- :windows: Checking whether to install Windows 10 SDK..."

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

$windowsSDKVersionFile = ".windows-10-sdk-version"
if (Test-Path $windowsSDKVersionFile) {
Write-Host "Found $windowsSDKVersionFile file, installing Windows 10 SDK..."
& "$PSScriptRoot\install_windows_10_sdk.ps1"
If ($LastExitCode -ne 0) { Exit $LastExitCode }
} else {
Write-Host "No $windowsSDKVersionFile file found, skipping Windows 10 SDK installation."
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

I wouldn't mind adding an escape hatch, that might be a good idea indeed (though one could argue that'd be YAGNI…)

If it's easy enough to implement and doesn't complicate the script logic too much (which I wouldn't expect to), I'd say go for it.

Comment on lines +32 to +52
# Install the Windows SDK and other required components
Write-Output "~~~ Installing Visual Studio Build Tools..."
Start-Process `
-FilePath $buildToolsPath `
-ArgumentList "--quiet --wait --add Microsoft.VisualStudio.Component.Windows10SDK.$windows10SDKVersion" `
-NoNewWindow `
-Wait

# Check if the installation was successful in file system
$windowsSDKsRoot = "C:\Program Files (x86)\Windows Kits\10\bin"
$sdkPath = "$windowsSDKsRoot\10.0.$windows10SDKVersion.0\x64"
If (-not (Test-Path $sdkPath)) {
Write-Output "[!] Failed to install Windows 10 SDK: Could not find SDK at $sdkPath."
If (-not (Test-Path $windowsSDKsRoot)) {
Write-Output "[!] Expected $windowsSDKsRoot to exist, but it does not."
} else {
Write-Output " Found:"
Get-ChildItem -Path $windowsSDKsRoot | ForEach-Object { Write-Output " - $windowsSDKsRoot\$_" }
}
Exit 1
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an easy way to check if $windows10SDKVersion is valid (i.e. an existing version, as opposed to if someone tried to use latest or none or whatever invalid text in the version file) and detect it early?

In particular, I'm wondering if the vs_buildtools.exe would fail with an explicit and clear error if that -add … argument we pass to it was invalid (i.e. if it didn't find the component), allowing us to print a specific error message in that case (like "Check the value you set in $windowsSDKVersionFile"), as opposed to the installer happily continuing with the installation of all the other default components—without complaining about this one not existing in the options—and us only finding out the component was not installed after the fact, thanks to your test on lines 42–51… (and even in that case, would it help to provide in the error messages a more explicit suggestion to check the syntax/version used in the version file?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if the vs_buildtools.exe would fail with an explicit and clear error

I've done a few experiments in my VM. It fails silently, with exit code 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll duplicated what I wrote in #153 (comment)

This all makes me wonder whether we might be better off using a default SDK version in the installer, and only falling back to the version file and/or a parameter if the user provides one. After all, I implemented the version file because other tools use it and because the app I was working on had a check for the SDK being installed and so I wanted a single source of truth. But I'd argue now that our tooling takes care of the installing, that check is redundant: the build script should trust the SDK is available.

I think the conversation should continue there, given that's the PR that is editing the script.

I also like the idea of having a list of valid numbers to pick from, given it's published at https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022 but I think that would be a good additional option, while we should still default to installing the latest valid version for the user ourselves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if we end up implementing the behavior of defaulting to install the latest valid version, we could allow latest to be a special valid content for .windows-10-sdk-version, that way if the file is not present it won't install the SDK at all, but if it's present with latest it will install the latest (and if it's present with a specific version it will deterministically install that specific version, acting as a lockfile) 🤔

That way the implicit auto-install from prepare_windows_host_for_app_distibution if file is present would still work for that default-version fallback… 🤔

exit 1
}

$windows10SDKVersion = Get-Content $windowsSDKVersionFile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: how does this Get-Content handles possible newlines?

Especially, if the version file ends with a newline at end of file, is that trimmed?
Or maybe it's not, but that doesn't cause any issues because when you then reference $windows10SDKVersion in other commands like --add Microsoft.VisualStudio.Component.Windows10SDK.$windows10SDKVersion that's when the value is trimmed as usage/substitution site?
What if the file contains 2 newlines at end of file? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the -TotalCount 1 parameter of Get-Content can help?
Though even if that allows to limit only reading the first line of the file, not 100% sure if it'd properly trim the \n at the end of that read line, in that case you might need to also use Trim() or TrimEnd().

Tentative suggestion (not tested):

Suggested change
$windows10SDKVersion = Get-Content $windowsSDKVersionFile
$windows10SDKVersion = (Get-Content -TotalCount 1 $windowsSDKVersionFile).Trim()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spent more time than I care to admit on this but got a bunch of tests for the version parsing

image

I'll clean up tomorrow #153

@mokagio
Copy link
Contributor Author

mokagio commented Feb 21, 2025

Thanks @iangmaia for the missing ps1 suggestions.

Incidentally, yesterday I looked into whether it was possible to remove the extension from the scripts to keep them consistent with the other bash ones. As far as I could see, it was not possible short of wrapping them in a cmdlet thus adding two files for each command. I think the "overhead" of adding the .ps1 extension is acceptable in this case.

Co-authored-by: Ian G. Maia <[email protected]>
This was referenced Feb 21, 2025
@dangermattic
Copy link

1 Warning
⚠️ This PR is larger than 500 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

Copy link
Contributor

@AliSoftware AliSoftware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, left some nitpicks but none being blockers

- github_commit_status:
context: "pr_changed_files Tests: Edge Cases"

- group: ":windows: install_windows_10_sdk Tests"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 For future PR:

Suggested change
- group: ":windows: install_windows_10_sdk Tests"
- group: ":windows: install_windows_10_sdk Tests"
if: build.env('INSTALL_WINDOWS_10_SDK_SCRIPT_CHANGED') == 'true'
  • in shared-pipelines-vars (that we'll need to introduce in this repo, apparently):
export INSTALL_WINDOWS_10_SDK_SCRIPT_CHANGED=$(bin/pr_changed_files --stdout --any-match 'bin/install_windows_10_sdk.ps1' 'tests/test-install-windows-10-sdk.ps1')

Which we'd be able to do in this repo despite the Uploader agent not loading the a8c-ci-toolkit plugin (which is what prevents us from doing that in other repos)… because in the particular case of this repo being the plugin itself, bin/pr_changed_files should be available directly after checkout 😉

(PS: I thought I mentioned that idea somewhere already somewhere but couldn't find it, maybe it was in another PR… so I figured I'd make it appear here too anyway)

Comment on lines +32 to +52
# Install the Windows SDK and other required components
Write-Output "~~~ Installing Visual Studio Build Tools..."
Start-Process `
-FilePath $buildToolsPath `
-ArgumentList "--quiet --wait --add Microsoft.VisualStudio.Component.Windows10SDK.$windows10SDKVersion" `
-NoNewWindow `
-Wait

# Check if the installation was successful in file system
$windowsSDKsRoot = "C:\Program Files (x86)\Windows Kits\10\bin"
$sdkPath = "$windowsSDKsRoot\10.0.$windows10SDKVersion.0\x64"
If (-not (Test-Path $sdkPath)) {
Write-Output "[!] Failed to install Windows 10 SDK: Could not find SDK at $sdkPath."
If (-not (Test-Path $windowsSDKsRoot)) {
Write-Output "[!] Expected $windowsSDKsRoot to exist, but it does not."
} else {
Write-Output " Found:"
Get-ChildItem -Path $windowsSDKsRoot | ForEach-Object { Write-Output " - $windowsSDKsRoot\$_" }
}
Exit 1
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if we end up implementing the behavior of defaulting to install the latest valid version, we could allow latest to be a special valid content for .windows-10-sdk-version, that way if the file is not present it won't install the SDK at all, but if it's present with latest it will install the latest (and if it's present with a specific version it will deterministically install that specific version, acting as a lockfile) 🤔

That way the implicit auto-install from prepare_windows_host_for_app_distibution if file is present would still work for that default-version fallback… 🤔

# Stop script execution when a non-terminating error occurs
$ErrorActionPreference = "Stop"

Write-Output "--- :windows: Setting up Windows for app distribution"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I wonder if all those Write-Output (used in that script and the others) shouldn't be Write-Host, given they're intended to print informational logs (rather than passing results to a follow-up process down the pipeline) 🤔

@mokagio mokagio enabled auto-merge (squash) February 28, 2025 02:30
@mokagio mokagio merged commit 1b6df52 into trunk Feb 28, 2025
25 checks passed
@mokagio mokagio deleted the mokagio/more-windows-utils branch February 28, 2025 02:43
@mokagio mokagio restored the mokagio/more-windows-utils branch February 28, 2025 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants