Skip to content

Add PowerShell command to setup Windows environment #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5b9e637
Add script to set up Windows host for Node development
mokagio May 31, 2024
34682d3
Ignore PowerShell scripts in test for executable property
mokagio Jun 3, 2024
03f2525
Address RuboCop violation
mokagio Jun 3, 2024
cbaa1fd
Update ShellCheck command to exclude PowerShell files
mokagio Jun 3, 2024
ead0b64
Log more information in `hooks/environment`
mokagio Jun 17, 2024
12528d3
Print CI header upon running `add_ssh_key_to_agent`
mokagio Jun 17, 2024
eec8d92
Make `hooks/environment` properly set `PATH` in Windows
mokagio Jun 17, 2024
c8d375f
Remove OS-specific handling of paths in `hooks/environment`
mokagio Aug 28, 2024
8009582
Add debug `PATH` print statement in Windows PS1
mokagio Aug 28, 2024
bf824fb
Fix typo
mokagio Aug 28, 2024
f4654bf
Add `$PATH` retaining workaround to `refreshenv` call
mokagio Aug 28, 2024
c431864
Try to set dev mode for Windows machines
mokagio Aug 28, 2024
151a397
Use `CurrentUser` instead of `LocalMachine`
mokagio Aug 28, 2024
95c3be2
Try different approach for developer mode
mokagio Aug 28, 2024
be308db
Debug print user roles in Windows
mokagio Aug 28, 2024
416c04a
Implement conditional behavior for tar in Windows
mokagio Aug 28, 2024
ec9374e
Remove --no-symlinks
mokagio Aug 28, 2024
690f664
Restore using the same `tar` across platforms in `restore_cache`
mokagio Aug 28, 2024
3e08260
Run `nvm` setup at the end of the prepare Win host script
mokagio Nov 12, 2024
b5c57e7
If now `.nvmrc` found, skip Node set up
mokagio Nov 12, 2024
ee9ff8f
Fix early exit check for `.nvmrc` in Windows
mokagio Nov 12, 2024
c2ff6c6
Do not open roles group
mokagio Nov 15, 2024
647299c
Make `prepare_windows_host_for_node.ps1` executable
mokagio Feb 3, 2025
4990c22
Merge remote-tracking branch 'origin/trunk' into mokagio/windows-utils
mokagio Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildkite-plugin-lint:

shellcheck:
@echo ~~~ 🕵️ ShellCheck
$(docker_run) koalaman/shellcheck hooks/** bin/** --exclude=SC1071
$(docker_run) koalaman/shellcheck $(shell find hooks bin -type f -not -name "*.ps1") --exclude=SC1071
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

(I wonder if there's a shellcheck equivalent for PowerShell btw… though probably only a thing to look at when we'll start tacking #101 more officially/broadly?)

Copy link
Contributor

@AliSoftware AliSoftware Jun 25, 2024

Choose a reason for hiding this comment

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

I wonder if there's a shellcheck equivalent for PowerShell btw…

Found this… in case we want to look into it at some point


rubocop:
@echo ~~~ 🕵️ Rubocop
Expand Down
2 changes: 2 additions & 0 deletions bin/add_ssh_key_to_agent
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
NEW_SSH_KEY=$1
NEW_SSH_KEY_NAME=$2

echo "--- :lock_with_ink_pen: Adding custom SSH key to agent ($NEW_SSH_KEY_NAME)"

# Create key in ~/.ssh dir
NEW_SSH_KEY_PATH="$HOME"/.ssh/"$NEW_SSH_KEY_NAME"
echo -e "$NEW_SSH_KEY" > "$NEW_SSH_KEY_PATH"
Expand Down
134 changes: 134 additions & 0 deletions bin/prepare_windows_host_for_node.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Stop script execution when a non-terminating error occurs
$ErrorActionPreference = "Stop"

if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) {
Write-Host "--- :bug: Running as Administrator"
} else {
Write-Host "--- :bug: Running as not Administrator"
$principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$roles = $principal.Identity.Groups | ForEach-Object {
$_.Translate([Security.Principal.NTAccount]).Value
}
Write-Host "Your roles are:"
$roles | ForEach-Object { Write-Host " - $_" }
}

Write-Host "--- :windows: Setting up Windows for Node and Electorn builds"

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

# Disable Windows Defender before starting – otherwise our performance is terrible
Write-Host "Disable Windows Defender..."
$avPreference = @(
@{DisableArchiveScanning = $true}
@{DisableAutoExclusions = $true}
@{DisableBehaviorMonitoring = $true}
@{DisableBlockAtFirstSeen = $true}
@{DisableCatchupFullScan = $true}
@{DisableCatchupQuickScan = $true}
@{DisableIntrusionPreventionSystem = $true}
@{DisableIOAVProtection = $true}
@{DisablePrivacyMode = $true}
@{DisableScanningNetworkFiles = $true}
@{DisableScriptScanning = $true}
@{MAPSReporting = 0}
@{PUAProtection = 0}
@{SignatureDisableUpdateOnStartupWithoutEngine = $true}
@{SubmitSamplesConsent = 2}
@{ScanAvgCPULoadFactor = 5; ExclusionPath = @("D:\", "C:\")}
@{DisableRealtimeMonitoring = $true}
@{ScanScheduleDay = 8}
)

$avPreference += @(
@{EnableControlledFolderAccess = "Disable"}
@{EnableNetworkProtection = "Disabled"}
)

$avPreference | Foreach-Object {
$avParams = $_
Set-MpPreference @avParams
}

# https://github.com/actions/runner-images/issues/4277
# https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-compatibility?view=o365-worldwide
$atpRegPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection'
if (Test-Path $atpRegPath) {
Write-Host "Set Microsoft Defender Antivirus to passive mode"
Set-ItemProperty -Path $atpRegPath -Name 'ForceDefenderPassiveMode' -Value '1' -Type 'DWORD'
}

Write-Host "--- :lock_with_ink_pen: Downloading Code Signing Certificate"
$EncodedText = aws secretsmanager get-secret-value --secret-id windows-code-signing-certificate | jq -r '.SecretString' | Out-File 'certificate.bin'
certutil -decode certificate.bin certificate.pfx
If ($LastExitCode -ne 0) { Exit $LastExitCode }

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

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

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

if ($developerMode.State -eq 'Enabled') {
Write-Host "Developer Mode is already enabled."
} else {
Write-Host "Enabling Developer Mode..."
try {
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart
} catch {
Write-Host "Failed to enable Developer Mode. Continuing without it..."
}
}

Write-Host "--- :node: Installing NVM"
choco install nvm.portable -y
If ($LastExitCode -ne 0) { Exit $LastExitCode }

Write-Host "--- :hammer: Custom PATH refresh post NVM installation to avoid losing previous PATH changes"
Write-Host "PATH before refreshenv is $env:PATH"
# It looks like out of the box, calling refreshenv at this point erases various PATH modifications made by the rest of our automation.
#
# See https://buildkite.com/automattic/beeper-desktop/builds/2893#01919717-d0d0-441d-a85d-0fe3223467d2/195
#
# To avoid the issue, we save the PATH pre-refreshenv and then manually add all the components that were removed.
$originalPath = "$env:PATH"
refreshenv
$mergedPath = "$env:PATH;$originalPath" -split ";" | Select-Object -Unique -Skip 1
$env:PATH = ($mergedPath -join ";")
Write-Host "PATH after refreshenv is $env:PATH"

$nvmRCPath = '.nvmrc'
if (-not (Test-Path $nvmRCPath)) {
Write-Host "No .nvmrc found. Skipping Node set up."
Exit 0
}

Write-Host "--- :node: Installing Node"
$nvmVersion=(Get-Content -Path $nvmRCPath -Total 1)
Write-Host "Switching to nvm version defined in .nvmrc: $nvmVersion"

nvm install $nvmVersion
nvm use $nvmVersion
If ($LastExitCode -ne 0) { Exit $LastExitCode }

Write-Host "--- :hammer: Custom PATH refresh post NVM installation to avoid losing previous PATH changes"
Write-Host "PATH before refreshenv is $env:PATH"
# It looks like out of the box, calling refreshenv at this point erases various PATH modifications made by the rest of our automation.
#
# See https://buildkite.com/automattic/beeper-desktop/builds/2893#01919717-d0d0-441d-a85d-0fe3223467d2/195
#
# To avoid the issue, we save the PATH pre-refreshenv and then manually add all the components that were removed.
$originalPath = "$env:PATH"
refreshenv
$mergedPath = "$env:PATH;$originalPath" -split ";" | Select-Object -Unique -Skip 1
$env:PATH = ($mergedPath -join ";")
Write-Host "PATH after refreshenv is $env:PATH"
14 changes: 11 additions & 3 deletions hooks/environment
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@

set -e

echo "~~~ :file_cabinet: Loading Automattic plugin commands in the environment"

HOOKS_ROOT=$( dirname "${BASH_SOURCE[0]}" )
PLUGIN_ROOT=$( dirname "$HOOKS_ROOT" )
PLUGIN_BIN="$PLUGIN_ROOT/bin"

export PATH="$PATH:$PLUGIN_BIN"
OS=$(uname -s)
echo "FYI: Running on OS $OS"

echo "~~~ :file_cabinet: Loaded Caching Plugin"
# Notice that we don't need any OS-specific treatment of the path format for UNIX vs Windows.
# When Windows runs this script via bash, it handles the path separation conversion from / to \ internally.
PLUGIN_BIN="${PLUGIN_ROOT}/bin"

echo "Original PATH: $PATH"
export PATH="$PATH:$PLUGIN_BIN"
echo "PATH updated to: $PATH"
14 changes: 9 additions & 5 deletions tests/test-that-all-files-are-executable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
# it seems that running `[ -x ]` under `bats` in Docker on a Mac returns invalid results, and this was more reliable.
#
# See: https://github.com/Automattic/a8c-ci-toolkit-buildkite-plugin/pull/42
context 'All Commands Should Be Executable' do
Dir.children('bin').map { |f| File.new(File.join('bin', f)) }.each do |file|
it file.path do
expect(file.stat.executable?).to be true
context 'All Unix Commands Should Be Executable' do
Dir
.children('bin')
# Ignore Windows PowerShell scripts
.reject { |f| f.end_with?('.ps1') }
Comment on lines -14 to +18
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

.map { |f| File.new(File.join('bin', f)) }.each do |file|
it file.path do
expect(file.stat.executable?).to be true
end
end
end
end