From 17283d19ccc01df5320102ea1934075706e53354 Mon Sep 17 00:00:00 2001 From: Hang Date: Tue, 30 Jan 2024 14:13:33 +0800 Subject: [PATCH] {Packaging} Support Windows ZIP package (#27911) --- azure-pipelines.yml | 72 ++++++++++++++++++- .../windows/scripts/{az.cmd => az_msi.cmd} | 0 build_scripts/windows/scripts/az_zip.cmd | 12 ++++ build_scripts/windows/scripts/build.cmd | 70 +++++++++++------- .../windows/scripts/test_zip_installation.ps1 | 27 +++++++ .../azure/cli/command_modules/util/custom.py | 4 ++ 6 files changed, 159 insertions(+), 26 deletions(-) rename build_scripts/windows/scripts/{az.cmd => az_msi.cmd} (100%) create mode 100644 build_scripts/windows/scripts/az_zip.cmd create mode 100644 build_scripts/windows/scripts/test_zip_installation.ps1 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0b15c6478fb..456a2e70e3f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -211,6 +211,7 @@ jobs: - script: | set ARCH=$(Platform) + set TARGET=msi set /p CLI_VERSION=<$(System.ArtifactsDirectory)/metadata/version set @@ -228,6 +229,45 @@ jobs: TargetPath: 'build_scripts/windows/out/' ArtifactName: msi-$(Platform) +- job: BuildWindowsZIP + displayName: Build Windows ZIP + strategy: + matrix: + x64: + Platform: x64 + + dependsOn: ExtractMetadata + condition: succeeded() + pool: + name: ${{ variables.windows_pool }} + steps: + - task: DownloadPipelineArtifact@1 + displayName: 'Download Build Artifacts' + inputs: + TargetPath: '$(Build.ArtifactStagingDirectory)/metadata' + artifactName: metadata + + + - script: | + set ARCH=$(Platform) + set TARGET=zip + set /p CLI_VERSION=<$(System.ArtifactsDirectory)/metadata/version + set + + build_scripts/windows/scripts/build.cmd + displayName: 'Build Windows ZIP' + + - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'SBOM' + inputs: + BuildDropPath: 'build_scripts/windows/out/' + + - task: PublishPipelineArtifact@0 + displayName: 'Publish Artifact: ZIP' + inputs: + TargetPath: 'build_scripts/windows/out/' + ArtifactName: zip-$(Platform) + - job: TestMsiInstallation displayName: Test MSI Installation strategy: @@ -259,6 +299,34 @@ jobs: inputs: filePath: build_scripts\windows\scripts\test_msi_installation.ps1 +- job: TestZipInstallation + displayName: Test ZIP Installation + dependsOn: BuildWindowsZIP + strategy: + matrix: + x64: + Platform: x64 + condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Manual', 'Schedule')) + pool: + name: ${{ variables.windows_pool }} + steps: + - task: DownloadPipelineArtifact@1 + displayName: 'Download Build Artifacts' + inputs: + TargetPath: '$(Build.ArtifactStagingDirectory)/metadata' + artifactName: metadata + + - task: DownloadPipelineArtifact@1 + displayName: 'Download Build Artifacts' + inputs: + TargetPath: '$(Build.ArtifactStagingDirectory)/zip' + artifactName: zip-$(Platform) + + - task: PowerShell@2 + displayName: Expand and Load CLI + inputs: + filePath: build_scripts\windows\scripts\test_zip_installation.ps1 + - job: BuildDockerImageAlpine displayName: Build Docker Image Alpine strategy: @@ -302,7 +370,7 @@ jobs: ${{ each arch in parameters.architectures }}: ${{ arch.name }}: pool: ${{ arch.pool }} - artifactName: docker-${{ arch.name }} + artifactName: docker-${{ arch.value }} pool: name: $(pool) steps: @@ -1160,6 +1228,8 @@ jobs: - VerifyVersions - BuildWindowsMSI - TestMsiInstallation + - BuildWindowsZIP + - TestZipInstallation - BuildDockerImageAlpine - TestDockerImageAlpine - BuildDockerImageAzureLinux diff --git a/build_scripts/windows/scripts/az.cmd b/build_scripts/windows/scripts/az_msi.cmd similarity index 100% rename from build_scripts/windows/scripts/az.cmd rename to build_scripts/windows/scripts/az_msi.cmd diff --git a/build_scripts/windows/scripts/az_zip.cmd b/build_scripts/windows/scripts/az_zip.cmd new file mode 100644 index 00000000000..07e4acb73ff --- /dev/null +++ b/build_scripts/windows/scripts/az_zip.cmd @@ -0,0 +1,12 @@ +:: +:: Microsoft Azure CLI - Windows Installer - Author file components script +:: Copyright (C) Microsoft Corporation. All Rights Reserved. +:: + +@IF EXIST "%~dp0\..\python.exe" ( + SET AZ_INSTALLER=ZIP + "%~dp0\..\python.exe" -IBm azure.cli %* +) ELSE ( + echo Failed to load python executable. + exit /b 1 +) diff --git a/build_scripts/windows/scripts/build.cmd b/build_scripts/windows/scripts/build.cmd index 25b7f9f53f8..cc058b4c7d4 100644 --- a/build_scripts/windows/scripts/build.cmd +++ b/build_scripts/windows/scripts/build.cmd @@ -13,10 +13,15 @@ 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 if "%ARCH%"=="" ( set ARCH=x86 ) +@REM TARGET can be msi or zip +if "%TARGET%"=="" ( + set TARGET=msi +) + if "%ARCH%"=="x86" ( set PYTHON_ARCH=win32 ) else if "%ARCH%"=="x64" ( @@ -71,20 +76,22 @@ if exist %REPO_ROOT%\privates ( copy %REPO_ROOT%\privates\*.whl %TEMP_SCRATCH_FOLDER% ) -REM ensure wix is available -if exist %WIX_DIR% ( - echo Using existing Wix at %WIX_DIR% -) -if not exist %WIX_DIR% ( - mkdir %WIX_DIR% - pushd %WIX_DIR% - echo Downloading Wix. - curl --output wix-archive.zip %WIX_DOWNLOAD_URL% - unzip wix-archive.zip - if %errorlevel% neq 0 goto ERROR - del wix-archive.zip - echo Wix downloaded and extracted successfully. - popd +if "%TARGET%" == "msi" ( + REM ensure wix is available + if exist %WIX_DIR% ( + echo Using existing Wix at %WIX_DIR% + ) + if not exist %WIX_DIR% ( + mkdir %WIX_DIR% + pushd %WIX_DIR% + echo Downloading Wix. + curl --output wix-archive.zip %WIX_DOWNLOAD_URL% + unzip wix-archive.zip + if %errorlevel% neq 0 goto ERROR + del wix-archive.zip + echo Wix downloaded and extracted successfully. + popd + ) ) REM ensure Python is available @@ -122,7 +129,6 @@ set PYTHON_EXE=%PYTHON_DIR%\python.exe robocopy %PYTHON_DIR% %BUILDING_DIR% /s /NFL /NDL set CLI_SRC=%REPO_ROOT%\src -%BUILDING_DIR%\python.exe -m pip install --no-warn-script-location --force-reinstall pycparser==2.18 for %%a in (%CLI_SRC%\azure-cli %CLI_SRC%\azure-cli-core %CLI_SRC%\azure-cli-telemetry) do ( pushd %%a %BUILDING_DIR%\python.exe -m pip install --no-warn-script-location --no-cache-dir --no-deps . @@ -137,18 +143,27 @@ if %errorlevel% neq 0 goto ERROR pushd %BUILDING_DIR% %BUILDING_DIR%\python.exe %REPO_ROOT%\scripts\compact_aaz.py +if %errorlevel% neq 0 goto ERROR %BUILDING_DIR%\python.exe %~dp0\patch_models_v2.py +if %errorlevel% neq 0 goto ERROR %BUILDING_DIR%\python.exe %REPO_ROOT%\scripts\trim_sdk.py +if %errorlevel% neq 0 goto ERROR popd REM Remove pywin32 help file to reduce size. del %BUILDING_DIR%\Lib\site-packages\PyWin32.chm -echo Creating the wbin (Windows binaries) folder that will be added to the path... -mkdir %BUILDING_DIR%\wbin -copy %REPO_ROOT%\build_scripts\windows\scripts\az.cmd %BUILDING_DIR%\wbin\ -copy %REPO_ROOT%\build_scripts\windows\scripts\azps.ps1 %BUILDING_DIR%\wbin\ -copy %REPO_ROOT%\build_scripts\windows\scripts\az %BUILDING_DIR%\wbin\ +if "%TARGET%"=="msi" ( + REM Creating the wbin (Windows binaries) folder that will be added to the path... + mkdir %BUILDING_DIR%\wbin + copy %REPO_ROOT%\build_scripts\windows\scripts\az_msi.cmd %BUILDING_DIR%\wbin\az.cmd + copy %REPO_ROOT%\build_scripts\windows\scripts\azps.ps1 %BUILDING_DIR%\wbin\ + copy %REPO_ROOT%\build_scripts\windows\scripts\az %BUILDING_DIR%\wbin\ +) else ( + REM Creating the bin folder that will be added to the path... + mkdir %BUILDING_DIR%\bin + copy %REPO_ROOT%\build_scripts\windows\scripts\az_zip.cmd %BUILDING_DIR%\bin\az.cmd +) if %errorlevel% neq 0 goto ERROR copy %REPO_ROOT%\build_scripts\windows\resources\CLI_LICENSE.rtf %BUILDING_DIR% copy %REPO_ROOT%\build_scripts\windows\resources\ThirdPartyNotices.txt %BUILDING_DIR% @@ -174,6 +189,7 @@ for /f %%f in ('dir /b /s *.pyc') do ( REM Delete __init__.pyc del %%~f ) ELSE ( + REM pip source code is required when install packages from source code echo --SKIP !PARENT_DIR! under pip ) ) @@ -193,14 +209,18 @@ for /d %%d in ("azure*.dist-info") do ( ) popd -if %errorlevel% neq 0 goto ERROR -echo Building MSI... -msbuild /t:rebuild /p:Configuration=Release /p:Platform=%ARCH% %REPO_ROOT%\build_scripts\windows\azure-cli.wixproj +if "%TARGET%"=="msi" ( + echo Building MSI... + msbuild /t:rebuild /p:Configuration=Release /p:Platform=%ARCH% %REPO_ROOT%\build_scripts\windows\azure-cli.wixproj +) else ( + echo Building ZIP... + "%ProgramFiles%\7-Zip\7z.exe" a -tzip "%OUTPUT_DIR%\Microsoft Azure CLI.zip" "%BUILDING_DIR%\*" +) if %errorlevel% neq 0 goto ERROR -echo %OUTPUT_DIR% +echo Output Dir: %OUTPUT_DIR% goto END diff --git a/build_scripts/windows/scripts/test_zip_installation.ps1 b/build_scripts/windows/scripts/test_zip_installation.ps1 new file mode 100644 index 00000000000..a08ca0c323f --- /dev/null +++ b/build_scripts/windows/scripts/test_zip_installation.ps1 @@ -0,0 +1,27 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +Set-PSDebug -Trace 1 + +Write-Output "Extracting zip to $env:SYSTEM_ARTIFACTSDIRECTORY\zip\" +& "C:\Program Files\7-Zip\7z.exe" x -o"$env:SYSTEM_ARTIFACTSDIRECTORY\zip\Azure CLI" "$env:SYSTEM_ARTIFACTSDIRECTORY\zip\Microsoft Azure CLI.zip" + +$az_full_path = "$env:SYSTEM_ARTIFACTSDIRECTORY\zip\Azure CLI\bin\az.cmd" + +& $az_full_path --version + +$installed_version=& $az_full_path version --query '\"azure-cli\"' -o tsv +Write-Output "Installed version: $installed_version" + +$artifact_version=Get-Content $env:SYSTEM_ARTIFACTSDIRECTORY\metadata\version +Write-Output "Artifact version: $artifact_version" + +if ($installed_version -ne $artifact_version){ + Write-Output "The installed version doesn't match the artifact version." + Exit 1 +} + +# Test bundled pip with extension installation +& $az_full_path extension add -n account +& $az_full_path self-test diff --git a/src/azure-cli/azure/cli/command_modules/util/custom.py b/src/azure-cli/azure/cli/command_modules/util/custom.py index ac84141ca9d..e6e4a86c423 100644 --- a/src/azure-cli/azure/cli/command_modules/util/custom.py +++ b/src/azure-cli/azure/cli/command_modules/util/custom.py @@ -140,6 +140,10 @@ def upgrade_version(cmd, update_all=None, yes=None, allow_preview=None): # pyli "or run 'pip install --upgrade azure-cli' in this container") elif installer == 'MSI': _upgrade_on_windows() + elif installer == 'ZIP': + zip_url = 'https://aka.ms/installazurecliwindowszipx64' + logger.warning("Please download the latest ZIP from %s, delete the old installation folder and extract the " + "new version to the same location", zip_url) else: logger.warning(UPGRADE_MSG) if exit_code: