使用 YAML 檔案設定 CI/CD 管線

下表列出您可以定義的不同 MSBuild 引數,以設定建置管線。

MSBuild 引數 說明
AppxPackageDir $(Build.ArtifactStagingDirectory)\AppxPackages 定義要儲存所產生成品的資料夾。
AppxBundlePlatforms $(Build.BuildPlatform) 可讓您定義套件組合中要包含的平台。
AppxBundle 永遠 針對指定的平台使用 .msix/.appx 檔案建立 .msixbundle/.appxbundle。
UapAppxPackageBuildMode StoreUpload 產生 .msixupload/.appxupload 檔案和 _Test 資料夾進行側載。
UapAppxPackageBuildMode CI 只會產生 .msixupload/.appxupload 檔案。
UapAppxPackageBuildMode SideloadOnly 僅針對側載產生 _Test 資料夾。
AppxPackageSigningEnabled true 啟用套件簽署。
PackageCertificateThumbprint 憑證指紋 此值必須符合簽署憑證中的指紋,或為空字串。
PackageCertificateKeyFile 路徑 要使用的憑證路徑。 這是從安全檔案中繼資料中擷取的。
PackageCertificatePassword 密碼 憑證中私密金鑰的密碼。 建議您將密碼儲存在 Azure Key Vault,並將密碼連結到變數群組。 您可以將變數傳遞給這個引數。

在使用 MSBuild 命令列建置封裝專案 (其建置方式同於 Visual Studio 中的精靈) 之前,建置程序可以藉由編輯 Package.appxmanifest 檔案中 Package 元素的 Version 屬性,將產生的 MSIX 套件版本化。 在 Azure Pipelines 中,若要達成此目標,您可以使用運算式,設定針對每個建置所遞增的計數器變數,也可以使用 PowerShell 指令碼,其會使用 .NET 中的 XDocument 類別來變更屬性的值。

定義 MSIX 建置管線的範例 YAML 檔案

pool: 
  vmImage: windows-2019
  
variables:
  buildPlatform: 'x86'
  buildConfiguration: 'release'
  major: 1
  minor: 0
  build: 0
  revision: $[counter('rev', 0)]
  
steps:
- powershell: |
     # Update appxmanifest. This must be done before the build.
     [xml]$manifest= get-content ".\Msix\Package.appxmanifest"
     $manifest.Package.Identity.Version = "$(major).$(minor).$(build).$(revision)"    
     $manifest.save("Msix/Package.appxmanifest")
  displayName: 'Version Package Manifest'
  
- task: MSBuild@1
  inputs:
    solution: Msix/Msix.wapproj
    platform: $(buildPlatform)
    configuration: $(buildConfiguration)
    msbuildArguments: '/p:OutputPath=NonPackagedApp
     /p:UapAppxPackageBuildMode=SideLoadOnly  /p:AppxBundle=Never /p:AppxPackageOutput=$(Build.ArtifactStagingDirectory)\MsixDesktopApp.msix /p:AppxPackageSigningEnabled=false'
  displayName: 'Package the App'
  
- task: DownloadSecureFile@1
  inputs:
    secureFile: 'certificate.pfx'
  displayName: 'Download Secure PFX File'
  
- script: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\signtool"
    sign /fd SHA256 /f $(Agent.TempDirectory)/certificate.pfx /p secret $(
    Build.ArtifactStagingDirectory)/MsixDesktopApp.msix'
  displayName: 'Sign MSIX Package'
  
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'

以下是 YAMl 檔案中定義的不同建置工作細目:

設定套件產生屬性

以下定義會設定建置元件 (平台) 的目錄,並定義是否要建置套件組合。

/p:AppxPackageDir="$(Build.ArtifactStagingDirectory)\AppxPackages\"
/p:UapAppxPackageBuildMode=SideLoadOnly
/p:AppxBundlePlatforms="$(Build.BuildPlatform)"
/p:AppxBundle=Never

設定套件簽署

若要簽署 MSIX (或 APPX) 套件,管線必須擷取簽署憑證。 若要這樣做,請在 VSBuild 工作之前新增 DownloadSecureFile 工作。 這可讓您透過 signingCert 存取簽署憑證。

- task: DownloadSecureFile@1
  name: signingCert
  displayName: 'Download CA certificate'
  inputs:
    secureFile: '[Your_Pfx].pfx'

接下來,更新 MSBuild 工作以參考簽署憑證:

- task: MSBuild@1
  inputs:
    platform: 'x86'
    solution: '$(solution)'
    configuration: '$(buildConfiguration)'
    msbuildArgs: '/p:AppxBundlePlatforms="$(buildPlatform)" 
                  /p:AppxPackageDir="$(appxPackageDir)" 
                  /p:AppxBundle=Never 
                  p:UapAppxPackageBuildMode=SideLoadOnly 
                  /p:AppxPackageSigningEnabled=true
                  /p:PackageCertificateThumbprint="" 
                  /p:PackageCertificateKeyFile="$(signingCert.secureFilePath)"'

注意

PackageCertificateThumbprint 引數會刻意設定為空字串做為預防措施。 如果在專案中設定指紋,但不符合簽署憑證,則建置將會失敗,並出現錯誤:Certificate does not match supplied signing thumbprint

檢閱參數

使用 $() 語法定義的參數為組建定義中定義的變數,且在其他的建置系統中將會變更。

若要檢視所有預先定義的變數,請參閱預先定義的建置變數

設定發佈建置成品工作

預設 MSIX 管線不會儲存所產生的成品。 若要將發佈功能新增至您的 YAML 定義,請新增下列工作。

- task: CopyFiles@2
  displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
  inputs:
    SourceFolder: '$(system.defaultworkingdirectory)'
    Contents: '**\bin\$(BuildConfiguration)\**'
    TargetFolder: '$(build.artifactstagingdirectory)'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'

您可以在建置結果頁面的 [成品] 選項中查看產生的成品。

非市集散發的 AppInstaller 檔案

如果您要在 Microsoft Store 之外散發應用程式,則可以利用 AppInstaller 檔案來安裝和更新您的套件

將尋找 \server\foo 上更新檔案的 .appinstaller 檔案

<?xml version="1.0" encoding="utf-8"?>
<AppInstaller xmlns="http://schemas.microsoft.com/appx/appinstaller/2018"
              Version="1.0.0.0"
              Uri="\\server\foo\MsixDesktopApp.appinstaller">
  <MainPackage Name="MyCompany.MySampleApp"
               Publisher="CN=MyCompany, O=MyCompany, L=Stockholm, S=N/A, C=Sweden"
               Version="1.0.0.0"
               Uri="\\server\foo\MsixDesktopApp.msix"
               ProcessorArchitecture="x86"/>
  <UpdateSettings>
    <OnLaunch HoursBetweenUpdateChecks="0" />
  </UpdateSettings>
</AppInstaller>

UpdateSettings 元素是用來告知系統何時檢查是否有更新,以及是否強制使用者進行更新。 如需完整的結構描述參考,包括每個 Windows 10 版本支援的命名空間,請參閱位於 bit.ly/2TGWnCR 的文件。

如果您將 .appinstaller 檔案新增至封裝專案,然後將其 [封裝動作] 屬性設為 [內容],並將 [複製到輸出目錄] 屬性設為 [有更新時才複製],則可以將另一個 PowerShell 工作新增至 YAML 檔案,其會更新根和 MainPackage 元素的 Version 屬性,並將更新的檔案儲存至執行目錄:

- powershell: |
  [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
  $doc = [System.Xml.Linq.XDocument]::Load(
    "$(Build.SourcesDirectory)/Msix/Package.appinstaller")
  $version = "$(major).$(minor).$(build).$(revision)"
  $doc.Root.Attribute("Version").Value = $version;
  $xName =
    [System.Xml.Linq.XName]
      "{http://schemas.microsoft.com/appx/appinstaller/2018}MainPackage"
  $doc.Root.Element($xName).Attribute("Version").Value = $version;
  $doc.Save("$(Build.ArtifactStagingDirectory)/MsixDesktopApp.appinstaller")
displayName: 'Version App Installer File'

接著,您會將 .appinstaller 檔案散發給使用者,並讓他們按兩下此檔案,而不是 .msix 檔案,以安裝封裝的應用程式。

連續部署

應用程式安裝程式檔案本身是未編譯的 XML 檔案,可以在建置之後編輯 (如有需要)。 當您將軟體部署到多個環境時,以及當您想要將建置管線與發行程序分開時,這可讓您輕鬆地使用。

如果您在 Azure 入口網站中使用「空白工作」範本建立發行管線,並使用最近設定的建置管線做為部署成品的來源,則可以將 PowerShell 工作新增至發行階段,以動態方式變更 .appinstaller 檔案中兩個 Uri 屬性的值,來反映應用程式的發佈位置。

在 .appinstaller 檔案中修改 Uri 的發行管線工作

- powershell: |
  [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
  $fileShare = "\\filesharestorageccount.file.core.windows.net\myfileshare\"
  $localFilePath =
    "$(System.DefaultWorkingDirectory)\_MsixDesktopApp\drop\MsixDesktopApp.appinstaller"
  $doc = [System.Xml.Linq.XDocument]::Load("$localFilePath")
  $doc.Root.Attribute("Uri").Value = [string]::Format('{0}{1}', $fileShare,
    'MsixDesktopApp.appinstaller')
  $xName =
    [System.Xml.Linq.XName]"{http://schemas.microsoft.com/appx/appinstaller/2018}MainPackage"
  $doc.Root.Element($xName).Attribute("Uri").Value = [string]::Format('{0}{1}',
    $fileShare, 'MsixDesktopApp.appx')
  $doc.Save("$localFilePath")
displayName: 'Modify URIs in App Installer File'

在上述工作中,URI 會設定為 Azure 檔案共用的 UNC 路徑。 因為這是當您安裝和更新應用程式時,作業系統尋找 MSIX 套件的位置,所以也會將另一個命令列指令碼新增至發行管線,先將雲端中的檔案共用對應至建置代理程式上的本機 Z:\ 磁碟機,然後再使用 xcopy 命令複製 .appinstaller 和. .msix 檔案:

- script: |
  net use Z: \\filesharestorageccount.file.core.windows.net\myfileshare
    /u:AZURE\filesharestorageccount
    3PTYC+ociHIwNgCnyg7zsWoKBxRmkEc4Aew4FMzbpUl/
    dydo/3HVnl71XPe0uWxQcLddEUuq0fN8Ltcpc0LYeg==
  xcopy $(System.DefaultWorkingDirectory)\_MsixDesktopApp\drop Z:\ /Y
  displayName: 'Publish App Installer File and MSIX package'

如果您裝載自己的內部部署 Azure DevOps Server,當然可以將檔案發佈到您自己的內部網路共用。

如果選擇發佈至 Web 服務器,您可以在 YAML 檔案中提供一些額外的引數,告知 MSBuild 產生版本化的 .appinstaller 檔案以及 HTML 頁面,其中包含下載連結和已封裝應用程式的一些相關資訊:

- task: MSBuild@1
  inputs:
    solution: Msix/Msix.wapproj
    platform: $(buildPlatform)
    configuration: $(buildConfiguration)
    msbuildArguments: '/p:OutputPath=NonPackagedApp /p:UapAppxPackageBuildMode=SideLoadOnly  /p:AppxBundle=Never /p:GenerateAppInstallerFile=True
/p:AppInstallerUri=http://yourwebsite.com/packages/ /p:AppInstallerCheckForUpdateFrequency=OnApplicationRun /p:AppInstallerUpdateFrequency=1 /p:AppxPackageDir=$(Build.ArtifactStagingDirectory)/'
  displayName: 'Package the App'

產生的 HTML 檔案包含一個超連結,前面會加上與瀏覽器無關的 ms-appinstaller 通訊協定啟用配置:

<a href="ms-appinstaller:?source=
  http://yourwebsite.com/packages/Msix_x86.appinstaller ">Install App</a>

如果您設定發行管線,將 drop 資料夾的內容發佈至內部網路或任何其他網站,且 Web 服務器支援位元組範圍要求,並已正確設定,則您的使用者可以使用此連結直接安裝應用程式,而無需先下載 MSIX 套件。