Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .azure-pipelines/templates/variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ variables:
ubuntu_pool: 'pool-ubuntu-2204'
ubuntu_multi_core_pool: 'pool-ubuntu-latest-multi-core'
windows_pool: 'pool-windows-2022'
windows_arm64_pool: 'pool-windows-2022-arm64'
ubuntu_arm64_pool: 'pool-ubuntu-latest-arm64'
macos_pool: 'macOS-14'
macos_intel_pool: 'macOS-15'
Expand Down
45 changes: 40 additions & 5 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ variables:
value: '3.14'

parameters:
- name: enableWindowsArm64
type: boolean
default: false
- name: architectures
type: object
default:
Expand Down Expand Up @@ -177,8 +180,15 @@ jobs:
- job: VerifyWindowsRequirements
displayName: 'Verify src/azure-cli/requirements.*.Windows.txt'
condition: succeeded()
strategy:
matrix:
x64:
PoolName: ${{ variables.windows_pool }}
${{ if eq(parameters.enableWindowsArm64, true) }}:
arm64:
PoolName: ${{ variables.windows_arm64_pool }}
pool:
name: ${{ variables.windows_pool }}
name: $(PoolName)

steps:
- task: UsePythonVersion@0
Expand All @@ -191,6 +201,9 @@ jobs:
filename: ./scripts/ci/dependency_check.bat
displayName: 'Verify src/azure-cli/requirements.py3.Windows.txt'

- script: python build_scripts/windows/tests/test_arm64_packaging.py
displayName: 'Verify Windows packaging configuration'

- job: VerifyVersions
displayName: Verify Command Module Versions
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/release'), eq(variables['System.PullRequest.TargetBranch'], 'release')))
Expand All @@ -216,13 +229,19 @@ jobs:
matrix:
x86:
Platform: x86
PoolName: ${{ variables.windows_pool }}
x64:
Platform: x64
PoolName: ${{ variables.windows_pool }}
${{ if eq(parameters.enableWindowsArm64, true) }}:
arm64:
Platform: arm64
PoolName: ${{ variables.windows_arm64_pool }}

dependsOn: ExtractMetadata
condition: succeeded()
pool:
name: ${{ variables.windows_pool }}
name: $(PoolName)
steps:
- task: DownloadPipelineArtifact@1
displayName: 'Download Build Artifacts'
Expand Down Expand Up @@ -263,11 +282,16 @@ jobs:
matrix:
x64:
Platform: x64
PoolName: ${{ variables.windows_pool }}
${{ if eq(parameters.enableWindowsArm64, true) }}:
arm64:
Platform: arm64
PoolName: ${{ variables.windows_arm64_pool }}

dependsOn: ExtractMetadata
condition: succeeded()
pool:
name: ${{ variables.windows_pool }}
name: $(PoolName)
steps:
- task: DownloadPipelineArtifact@1
displayName: 'Download Build Artifacts'
Expand Down Expand Up @@ -308,13 +332,19 @@ jobs:
matrix:
x86:
Platform: x86
PoolName: ${{ variables.windows_pool }}
x64:
Platform: x64
PoolName: ${{ variables.windows_pool }}
${{ if eq(parameters.enableWindowsArm64, true) }}:
arm64:
Platform: arm64
PoolName: ${{ variables.windows_arm64_pool }}

dependsOn: BuildWindowsMSI
condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Manual', 'Schedule'))
pool:
name: ${{ variables.windows_pool }}
name: $(PoolName)
steps:
- task: DownloadPipelineArtifact@1
displayName: 'Download Build Artifacts'
Expand All @@ -340,9 +370,14 @@ jobs:
matrix:
x64:
Platform: x64
PoolName: ${{ variables.windows_pool }}
${{ if eq(parameters.enableWindowsArm64, true) }}:
arm64:
Platform: arm64
PoolName: ${{ variables.windows_arm64_pool }}
condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Manual', 'Schedule'))
pool:
name: ${{ variables.windows_pool }}
name: $(PoolName)
steps:
- task: DownloadPipelineArtifact@1
displayName: 'Download Build Artifacts'
Expand Down
35 changes: 33 additions & 2 deletions build_scripts/windows/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<?define ProductAuthor = "Microsoft Corporation" ?>
<?define ProductResources = ".\resources\" ?>
<?define UpgradeCode32 = "dff82af0-3f95-4ac9-8efd-948604fdb028" ?>
<?define UpgradeCode64 = "90762fec-9554-4729-a107-c6a8ea316698" ?>
<?define UpgradeCodeArm64 = "E2FCECB7-7E7D-42E3-BC3A-FDF3004AE223" ?>

<?if $(var.Platform) = "x64" ?>
<?define AzureCliRegistryGuid = "90b6367e-4e15-4313-af33-a0ef459a56fc" ?>
Expand All @@ -16,8 +18,20 @@
<?define ProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define RemoveAzureCLIFolderGuid = "7ce8a521-7429-4ded-9cce-0948e393cc83" ?>
<?define RemoveCLIFolderGuid = "59fb416c-91d0-49aa-a185-d4330c435a93" ?>
<?define UpgradeCode = "90762fec-9554-4729-a107-c6a8ea316698" ?>
<?define UpgradeCode = $(var.UpgradeCode64) ?>
<?define Architecture = "64-bit" ?>
<?define InstallerVersion = "200" ?>

<?elseif $(var.Platform) = "arm64" ?>
<?define AzureCliRegistryGuid = "43A564F2-04D5-44CA-AEF6-6188DF3A1816" ?>
<?define AzureCliSystemPathGuid = "3729630C-F41E-4A3C-9F6A-88BADEDF7914" ?>
<?define AzureCliVersionGuid = "57B936E0-734F-47FE-8D82-9303622BF9D7" ?>
<?define ProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define RemoveAzureCLIFolderGuid = "38254D07-0591-4079-96D8-B09406439157" ?>
<?define RemoveCLIFolderGuid = "88D17E6B-925E-4799-8B35-28476A0E7F85" ?>
<?define UpgradeCode = $(var.UpgradeCodeArm64) ?>
<?define Architecture = "ARM64" ?>
<?define InstallerVersion = "500" ?>

<?elseif $(var.Platform) = "x86" ?>
<?define AzureCliRegistryGuid = "BDEEE50E-70D3-4990-BFF9-FCF8114AA701" ?>
Expand All @@ -28,6 +42,7 @@
<?define RemoveCLIFolderGuid = "24DA394D-B03D-4623-A0D9-852DB51EF9F4" ?>
<?define UpgradeCode = $(var.UpgradeCode32) ?>
<?define Architecture = "32-bit" ?>
<?define InstallerVersion = "200" ?>

<?else ?>
<?error Unsupported platform "$(var.Platform)" ?>
Expand All @@ -40,7 +55,7 @@
Manufacturer="$(var.ProductAuthor)"
UpgradeCode="$(var.UpgradeCode)">

<Package InstallerVersion="200"
<Package InstallerVersion="$(var.InstallerVersion)"
Compressed="yes"
InstallScope="perMachine" />

Expand All @@ -59,6 +74,22 @@
<UpgradeVersion Property="WIX_X86_UPGRADE_DETECTED" Maximum="$(var.ProductVersion)" IncludeMaximum="yes" MigrateFeatures="yes" />
<UpgradeVersion Property="WIX_X86_DOWNGRADE_DETECTED" Minimum="$(var.ProductVersion)" IncludeMinimum="no" OnlyDetect="yes" />
</Upgrade>
<?endif ?>

<?if $(var.Platform) = "x64" ?>
<Upgrade Id="$(var.UpgradeCodeArm64)">
<UpgradeVersion Property="WIX_ARM64_INSTALLED" Minimum="0.0.0" IncludeMinimum="yes" OnlyDetect="yes" />
</Upgrade>
<Condition Message="The ARM64 version of $(var.ProductName) is already installed. Uninstall it before installing the 64-bit version.">NOT WIX_ARM64_INSTALLED</Condition>
<?endif ?>

<?if $(var.Platform) = "arm64" ?>
<Upgrade Id="$(var.UpgradeCode64)">
<UpgradeVersion Property="WIX_X64_UPGRADE_DETECTED" Maximum="$(var.ProductVersion)" IncludeMaximum="yes" MigrateFeatures="yes" />
<UpgradeVersion Property="WIX_X64_DOWNGRADE_DETECTED" Minimum="$(var.ProductVersion)" IncludeMinimum="no" OnlyDetect="yes" />
</Upgrade>
<Condition Message="A newer version of $(var.ProductName) is already installed.">NOT (WIX_DOWNGRADE_DETECTED OR WIX_X86_DOWNGRADE_DETECTED OR WIX_X64_DOWNGRADE_DETECTED)</Condition>
<?elseif $(var.UpgradeCode) != $(var.UpgradeCode32) ?>
<Condition Message="A newer version of $(var.ProductName) is already installed.">NOT (WIX_DOWNGRADE_DETECTED OR WIX_X86_DOWNGRADE_DETECTED)</Condition>
<?else ?>
<Condition Message="A newer version of $(var.ProductName) is already installed.">NOT WIX_DOWNGRADE_DETECTED</Condition>
Expand Down
10 changes: 7 additions & 3 deletions build_scripts/windows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Prerequisites

1. Turn on the '.NET Framework 3.5' Windows Feature (required for WIX Toolset).

2. Install 'WIX Toolset build tools' if not already installed. (e.g. WiX v3.10.3)
2. Install 'WIX Toolset build tools' if not already installed. WiX v3.14.1
or later is required for ARM64 MSI packages.
http://wixtoolset.org/releases/

3. Get Git for Windows (it has several tools used for the build).
Expand All @@ -28,6 +29,9 @@ Building

1. Set the `CLI_VERSION` environment variable.

2. Run `build_scripts\windows\scripts\build.cmd`.
2. Set `ARCH` to `x86`, `x64`, or `arm64`. ARM64 builds must run on a native
Windows ARM64 host because the build executes the embedded Python runtime.

3. The unsigned MSI will be in the `.\out` folder.
3. Run `build_scripts\windows\scripts\build.cmd`.

4. The unsigned MSI will be in the `.\out` folder.
6 changes: 6 additions & 0 deletions build_scripts/windows/azure-cli.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Global
Release|x86 = Release|x86
Debug|x64 = Debug|x64
Release|x64 = Release|x64
Debug|arm64 = Debug|arm64
Release|arm64 = Release|arm64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Debug|x86.ActiveCfg = Debug|x86
Expand All @@ -19,6 +21,10 @@ Global
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Debug|x64.Build.0 = Debug|x64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Release|x64.ActiveCfg = Release|x64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Release|x64.Build.0 = Release|x64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Debug|arm64.ActiveCfg = Debug|arm64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Debug|arm64.Build.0 = Debug|arm64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Release|arm64.ActiveCfg = Release|arm64
{9A0DC66D-3186-4EE4-B471-6C0F1DD6E159}.Release|arm64.Build.0 = Release|arm64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
14 changes: 13 additions & 1 deletion build_scripts/windows/azure-cli.wixproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</PropertyGroup>
<!-- Local WiX -->
<PropertyGroup>
<LocalWixRoot>artifacts\wix</LocalWixRoot>
<LocalWixRoot>artifacts\wix-3.14.1</LocalWixRoot>
<WixToolPath>$(MSBuildThisFileDirectory)$(LocalWixRoot)</WixToolPath>
<WixTargetsPath Condition="Exists('$(WixToolPath)\Wix.targets')">$(WixToolPath)\Wix.targets</WixTargetsPath>
<WixTasksPath Condition="Exists('$(WixToolPath)\wixtasks.dll')">$(WixToolPath)\wixtasks.dll</WixTasksPath>
Expand All @@ -41,6 +41,18 @@
<IntermediateOutputPath>out\obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>AzureCliSource=$(AzureCliSource)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|arm64' ">
<OutputPath>out\$(Configuration)\</OutputPath>
<IntermediateOutputPath>out\obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug;AzureCliSource=$(AzureCliSource)</DefineConstants>
<InstallerPlatform>arm64</InstallerPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|arm64' ">
<OutputPath>out\</OutputPath>
<IntermediateOutputPath>out\obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>AzureCliSource=$(AzureCliSource)</DefineConstants>
<InstallerPlatform>arm64</InstallerPlatform>
</PropertyGroup>
<ItemGroup>
<Compile Include="out\azure-cli.wxs">
<Link>azure-cli.wxs</Link>
Expand Down
18 changes: 12 additions & 6 deletions build_scripts/windows/scripts/build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if "%CLI_VERSION%"=="" (
echo Please set the CLI_VERSION environment variable, e.g. 2.0.13
goto ERROR
)
@REM ARCH can be x86 or x64
@REM ARCH can be x86, x64, or arm64
if "%ARCH%"=="" (
set ARCH=x86
)
Expand All @@ -26,13 +26,16 @@ if "%ARCH%"=="x86" (
set PYTHON_ARCH=win32
) else if "%ARCH%"=="x64" (
set PYTHON_ARCH=amd64
) else if "%ARCH%"=="arm64" (
set PYTHON_ARCH=arm64
) else (
echo Please set ARCH to "x86" or "x64"
echo Please set ARCH to "x86", "x64", or "arm64"
goto ERROR
)
set PYTHON_VERSION=3.14.8

set WIX_DOWNLOAD_URL="https://azurecliprod.blob.core.windows.net/msi/wix310-binaries-mirror.zip"
set WIX_DOWNLOAD_URL="https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip"
set WIX_DOWNLOAD_SHA256=6AC824E1642D6F7277D0ED7EA09411A508F6116BA6FAE0AA5F2C7DAA2FF43D31
set PYTHON_DOWNLOAD_URL="https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-%PYTHON_ARCH%.zip"

REM https://pip.pypa.io/en/stable/installation/#get-pip-py
Expand All @@ -48,7 +51,7 @@ set ARTIFACTS_DIR=%~dp0..\artifacts
mkdir %ARTIFACTS_DIR%
set TEMP_SCRATCH_FOLDER=%ARTIFACTS_DIR%\cli_scratch
set BUILDING_DIR=%ARTIFACTS_DIR%\cli
set WIX_DIR=%ARTIFACTS_DIR%\wix
set WIX_DIR=%ARTIFACTS_DIR%\wix-3.14.1
set PYTHON_DIR=%ARTIFACTS_DIR%\Python

REM Get the absolute directory since we pushd into different levels of subdirectories.
Expand Down Expand Up @@ -85,9 +88,12 @@ if "%TARGET%" == "msi" (
mkdir %WIX_DIR%
pushd %WIX_DIR%
echo Downloading Wix.
curl --output wix-archive.zip %WIX_DOWNLOAD_URL%
curl --fail --location --output wix-archive.zip %WIX_DOWNLOAD_URL%
if errorlevel 1 goto ERROR
powershell.exe -NoProfile -Command "if ((Get-FileHash -Algorithm SHA256 wix-archive.zip).Hash -ne '%WIX_DOWNLOAD_SHA256%') { throw 'WiX archive SHA-256 mismatch' }"
if errorlevel 1 goto ERROR
unzip wix-archive.zip
if %errorlevel% neq 0 goto ERROR
if errorlevel 1 goto ERROR
del wix-archive.zip
echo Wix downloaded and extracted successfully.
popd
Expand Down
19 changes: 14 additions & 5 deletions build_scripts/windows/scripts/setup_msi_test.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
param(
[ValidateSet('x86', 'x64', 'arm64')]
[string]$Platform = 'x86'
)

# Prerequisites:
# 1. Install the MSI built with current branch
# 2. Run bash azure-cli\scripts\ci\build.sh with Git Bash first to generate artifacts under azure-cli\artifacts\build so we can use the testsdk and fulltest wheels.
Expand All @@ -9,13 +14,17 @@ If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti
Start-Process powershell -Verb runAs -ArgumentList $arguments
}

& 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe' -m pip install pytest
& 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe' -m pip install pytest-xdist
$program_files = if ($Platform -eq 'x86') { ${env:ProgramFiles(x86)} } else { $env:ProgramFiles }
$env:AZURE_CLI_INSTALL_DIR = Join-Path $program_files 'Microsoft SDKs\Azure\CLI2'
$python = Join-Path $env:AZURE_CLI_INSTALL_DIR 'python.exe'

& $python -m pip install pytest
& $python -m pip install pytest-xdist

$testsdk = Get-ChildItem -Path $PSScriptRoot\..\..\..\artifacts\build\azure_cli_testsdk*.whl | Select-Object Name
& 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe' -m pip install $PSScriptRoot\..\..\..\artifacts\build\$($testsdk.Name)
& $python -m pip install $PSScriptRoot\..\..\..\artifacts\build\$($testsdk.Name)

$fulltest = Get-ChildItem -Path $PSScriptRoot\..\..\..\artifacts\build\azure_cli_fulltest*.whl | Select-Object Name
& 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe' -m pip install --no-deps $PSScriptRoot\..\..\..\artifacts\build\$($fulltest.Name)
& $python -m pip install --no-deps $PSScriptRoot\..\..\..\artifacts\build\$($fulltest.Name)

& 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe' $PSScriptRoot\test_msi_package.py
& $python $PSScriptRoot\test_msi_package.py
7 changes: 4 additions & 3 deletions build_scripts/windows/scripts/test_msi_installation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ az --version
# - Microsoft Azure CLI --deprecated
# - Microsoft Azure CLI (32-bit)
# - Microsoft Azure CLI (64-bit)
# - Microsoft Azure CLI (ARM64)
$cli_package = Get-Package -Provider Programs -IncludeWindowsInstaller -Name "Microsoft Azure CLI*"
$cli_package | Format-List
Uninstall-Package -Name $cli_package.Name
Expand Down Expand Up @@ -52,10 +53,10 @@ Get-Package -Provider Programs -IncludeWindowsInstaller -Name "Microsoft Azure C

# We can't restart the current shell in CI to refresh PATH, so use absolute path.
# If we can find a way to refresh PATH in the same shell session, we can directly call az.
if ($env:PLATFORM -eq 'x64') {
$az_full_path = "C:\Program Files\Microsoft SDKs\Azure\CLI2\wbin\az.cmd"
if ($env:PLATFORM -eq 'x86') {
$az_full_path = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\CLI2\wbin\az.cmd"
} else {
$az_full_path = "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin\az.cmd"
$az_full_path = "$env:ProgramFiles\Microsoft SDKs\Azure\CLI2\wbin\az.cmd"
}

& $az_full_path --version
Expand Down
3 changes: 2 additions & 1 deletion build_scripts/windows/scripts/test_msi_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import sys
import subprocess

base_dir = 'C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\Lib\\site-packages\\azure\\cli'
install_dir = os.environ.get('AZURE_CLI_INSTALL_DIR', 'C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2')
base_dir = '{}\\Lib\\site-packages\\azure\\cli'.format(install_dir)
root_dir = '{}\\command_modules'.format(base_dir)
mod_list = [mod for mod in sorted(os.listdir(root_dir)) if os.path.isdir(os.path.join(root_dir, mod)) and mod != '__pycache__']

Expand Down
Loading
Loading