From dffb24ec8f3de4817b13e333d9be3c58f005ca1b Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Wed, 30 Sep 2026 16:25:53 +0100 Subject: [PATCH 1/7] DSTA-691: add script install --- .../3_transfer_to_storage/install_tools.ps1 | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 new file mode 100644 index 0000000..5aeb143 --- /dev/null +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 @@ -0,0 +1,84 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Ensures winget, Azure CLI and AzCopy are installed, pinned to known-good versions. +#> + +$ErrorActionPreference = 'Stop' + +# Pinned versions so tool behaviour stays stable over time. +$AzureCliVersion = '2.90.0' +$AzCopyVersion = '10.32.8' + +function Test-CommandExists { + param([Parameter(Mandatory)][string]$Name) + return [bool](Get-Command -Name $Name -ErrorAction SilentlyContinue) +} + +function Install-Winget { + Write-Host 'winget not found. Attempting to install the App Installer (winget)...' + + # winget ships with the Microsoft.DesktopAppInstaller package on Windows 10/11. + try { + $progressPreference = 'SilentlyContinue' + $tempInstaller = Join-Path $env:TEMP 'Microsoft.DesktopAppInstaller.msixbundle' + $downloadUrl = 'https://aka.ms/getwinget' + + Write-Host "Downloading App Installer from $downloadUrl ..." + Invoke-WebRequest -Uri $downloadUrl -OutFile $tempInstaller -UseBasicParsing + + Write-Host 'Registering App Installer package...' + Add-AppxPackage -Path $tempInstaller + + Remove-Item -Path $tempInstaller -Force -ErrorAction SilentlyContinue + } + catch { + throw "Failed to install winget automatically. Install 'App Installer' from the Microsoft Store, then re-run this script. Details: $($_.Exception.Message)" + } + + if (-not (Test-CommandExists -Name 'winget')) { + throw "winget is still not available after installation. Restart the shell (or the machine) and re-run this script." + } + + Write-Host 'winget installed successfully.' +} + +function Install-WingetPackage { + param( + [Parameter(Mandatory)][string]$DisplayName, + [Parameter(Mandatory)][string]$Id, + [Parameter(Mandatory)][string]$Version + ) + + $installed = winget list --exact --id $Id 2>$null | Select-String -SimpleMatch $Id + if ($installed) { + Write-Host "$DisplayName is already installed. Skipping." + return + } + + Write-Host "Installing $DisplayName ($Id) version $Version ..." + winget install --exact --id $Id --version $Version ` + --accept-package-agreements --accept-source-agreements + + if ($LASTEXITCODE -ne 0) { + throw "Failed to install $DisplayName ($Id) version $Version. winget exit code: $LASTEXITCODE" + } + + Write-Host "$DisplayName installed successfully." +} + +# 1. Ensure winget is available. +if (-not (Test-CommandExists -Name 'winget')) { + Install-Winget +} +else { + Write-Host 'winget is already installed.' +} + +# 2. Ensure Azure CLI is installed (pinned version). +Install-WingetPackage -DisplayName 'Azure CLI' -Id 'Microsoft.AzureCLI' -Version $AzureCliVersion + +# 3. Ensure AzCopy is installed (pinned version). +Install-WingetPackage -DisplayName 'AzCopy' -Id 'Microsoft.Azure.AZCopy.10' -Version $AzCopyVersion + +Write-Host 'All tools are installed.' From 4adaff2c5da13e2c9c9b7f6cb68e32f53ec9716a Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Wed, 30 Sep 2026 17:00:27 +0100 Subject: [PATCH 2/7] DSTA-691: update bat file --- .../bso_process/3_transfer_to_storage/install_azcopy.bat | 2 +- .../bso_process/3_transfer_to_storage/install_tools.ps1 | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat index 89c61ef..59de041 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat @@ -2,4 +2,4 @@ REM This batch file runs the PowerShell AzCopy install script with execution policy bypass REM Users can simply run this file without needing to unblock or configure anything -powershell -ExecutionPolicy Bypass -NoProfile -File "%~dp0install_azcopy.ps1" %* +powershell -ExecutionPolicy Bypass -NoProfile -File "%~dp0install_tools.ps1" %* diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 index 5aeb143..b9adcb3 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 @@ -50,7 +50,8 @@ function Install-WingetPackage { [Parameter(Mandatory)][string]$Version ) - $installed = winget list --exact --id $Id 2>$null | Select-String -SimpleMatch $Id + $installed = winget list --exact --id $Id --accept-source-agreements --disable-interactivity 2>$null | + Select-String -SimpleMatch $Id if ($installed) { Write-Host "$DisplayName is already installed. Skipping." return From c63d0b78977e9b8d9246af9ca030936abf2bf9b7 Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Wed, 30 Sep 2026 17:15:33 +0100 Subject: [PATCH 3/7] DSTA-691: update bat file name --- .../{install_azcopy.bat => install_tools.bat} | 2 +- .../bso_process/3_transfer_to_storage/install_tools.ps1 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) rename nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/{install_azcopy.bat => install_tools.bat} (65%) diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.bat similarity index 65% rename from nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat rename to nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.bat index 59de041..c2a22ce 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.bat +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.bat @@ -1,5 +1,5 @@ @echo off -REM This batch file runs the PowerShell AzCopy install script with execution policy bypass +REM This batch file runs the PowerShell tools install script with execution policy bypass REM Users can simply run this file without needing to unblock or configure anything powershell -ExecutionPolicy Bypass -NoProfile -File "%~dp0install_tools.ps1" %* diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 index b9adcb3..5aeb143 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_tools.ps1 @@ -50,8 +50,7 @@ function Install-WingetPackage { [Parameter(Mandatory)][string]$Version ) - $installed = winget list --exact --id $Id --accept-source-agreements --disable-interactivity 2>$null | - Select-String -SimpleMatch $Id + $installed = winget list --exact --id $Id 2>$null | Select-String -SimpleMatch $Id if ($installed) { Write-Host "$DisplayName is already installed. Skipping." return From 70a531fb58efc63013a21290d471f8ba27fdd047 Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Wed, 30 Sep 2026 17:36:20 +0100 Subject: [PATCH 4/7] DSTA-691: remove old install script and update read me --- .../3_transfer_to_storage/README.md | 10 ++- .../3_transfer_to_storage/install_azcopy.ps1 | 75 ------------------- 2 files changed, 6 insertions(+), 79 deletions(-) delete mode 100644 nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.ps1 diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md index 4660e7a..6f1ac38 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md @@ -4,14 +4,16 @@ The upload script signs in to Azure CLI with your Microsoft Entra account, then ## Requirements -- **AzCopy** — Install from , or install and add it to the PATH by running: +- **AzCopy** — Install from + +- **Azure CLI** — Install from + +or install both tools by running this script which uses winget to add the tools to your environment: ```powershell -.\install_azcopy.bat +.\install_tools.bat ``` -- **Azure CLI** — Install from - ## Usage From this directory, run the script with the zip created in `bso_process`. Use the Microsoft Entra tenant ID associated with the storage account, not the subscription ID: diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.ps1 b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.ps1 deleted file mode 100644 index 9865f8a..0000000 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/install_azcopy.ps1 +++ /dev/null @@ -1,75 +0,0 @@ -<# -.SYNOPSIS - Downloads and installs AzCopy v10 for Windows, then adds it to the User PATH. - -.DESCRIPTION - This script performs the following steps: - 1. Downloads the latest AzCopy v10 Windows 64-bit ZIP from Microsoft. - 2. Extracts azcopy.exe into the install folder (default C:\azcopy). - 3. Adds the install folder to the current user's PATH environment variable (only if it isn't already present). - 4. Verifies that azcopy is available and prints its version. - - Reopen PowerShell or VS Code after running this script so the updated PATH - is picked up by new terminal sessions. - -.PARAMETER InstallPath - Folder to install azcopy.exe into. Defaults to "C:\Program Files (x86)\azcopy". - -.EXAMPLE - .\install_azcopy.ps1 - -.EXAMPLE - .\install_azcopy.ps1 -InstallPath "D:\tools\azcopy" - -.NOTES - The default InstallPath is under Program Files (x86), so this script must be - run as Administrator unless a different, user-writable InstallPath is given. -#> - -param ( - # Folder to install azcopy.exe into - [string]$InstallPath = "C:\Program Files (x86)\azcopy" -) - -$ErrorActionPreference = "Stop" - -$downloadUrl = "https://aka.ms/downloadazcopy-v10-windows" -$zipPath = Join-Path $env:TEMP "azcopy.zip" -$extractPath = Join-Path $env:TEMP "azcopy_extract" - -Write-Host "Downloading AzCopy from $downloadUrl..." -Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath -UseBasicParsing - -if (Test-Path $extractPath) { - Remove-Item $extractPath -Recurse -Force -} -Write-Host "Extracting AzCopy..." -Expand-Archive -Path $zipPath -DestinationPath $extractPath -Force - -$azcopyExe = Get-ChildItem -Path $extractPath -Filter "azcopy.exe" -Recurse | Select-Object -First 1 -if (-not $azcopyExe) { - throw "azcopy.exe was not found in the downloaded archive." -} - -if (-not (Test-Path $InstallPath)) { - New-Item -Path $InstallPath -ItemType Directory -Force | Out-Null -} -Write-Host "Installing azcopy.exe to $InstallPath..." -Copy-Item -Path $azcopyExe.FullName -Destination $InstallPath -Force - -Remove-Item $zipPath -Force -Remove-Item $extractPath -Recurse -Force - -$userPath = [Environment]::GetEnvironmentVariable("Path", "User") -if (($userPath -split ';') -notcontains $InstallPath) { - Write-Host "Adding $InstallPath to the User PATH..." - [Environment]::SetEnvironmentVariable("Path", "$userPath;$InstallPath", "User") - $env:Path += ";$InstallPath" -} else { - Write-Host "$InstallPath is already in the User PATH." -} - -Write-Host "Verifying AzCopy installation..." -& (Join-Path $InstallPath "azcopy.exe") --version - -Write-Host "AzCopy installed successfully. Close and reopen PowerShell or VS Code so the updated PATH is loaded in new sessions." From a6f57dc536c5a74706236db75dec4da5adc67f5f Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Thu, 1 Oct 2026 11:49:19 +0100 Subject: [PATCH 5/7] DSTA-691: update vale allowed list of word include winget --- .../config/vale/styles/config/vocabularies/words/accept.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index 74c7eeb..96cac3c 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -25,4 +25,5 @@ uv lockfile CsessionPath az -[Aa]z[Cc]opy +[Aa]z[Cc]opy\ +[Ww]in[Gg]et From 1ea78039f00e688f3bc6c58ddf7316eb711fc958 Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Thu, 1 Oct 2026 13:59:28 +0100 Subject: [PATCH 6/7] DSTA-691: undid previous change and add back ticks to winget --- .../bso_process/3_transfer_to_storage/README.md | 2 +- scripts/config/vale/styles/config/vocabularies/words/accept.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md index 6f1ac38..c5528e9 100644 --- a/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md +++ b/nbss/playcd/poc_backup_restore_pipeline/bso_process/3_transfer_to_storage/README.md @@ -8,7 +8,7 @@ The upload script signs in to Azure CLI with your Microsoft Entra account, then - **Azure CLI** — Install from -or install both tools by running this script which uses winget to add the tools to your environment: +or install both tools by running this script which uses `winget` to add the tools to your environment: ```powershell .\install_tools.bat diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index 96cac3c..8e520ee 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -26,4 +26,3 @@ lockfile CsessionPath az [Aa]z[Cc]opy\ -[Ww]in[Gg]et From 6b306905b20a0d27f9955df5f199911e529b1fae Mon Sep 17 00:00:00 2001 From: LouisD7 Date: Thu, 1 Oct 2026 14:02:51 +0100 Subject: [PATCH 7/7] DSTA-691: removed invalid symbol --- scripts/config/vale/styles/config/vocabularies/words/accept.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index 8e520ee..74c7eeb 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -25,4 +25,4 @@ uv lockfile CsessionPath az -[Aa]z[Cc]opy\ +[Aa]z[Cc]opy