Configuración de la integración continua para la aplicación WinUI

Puede usar Acciones de GitHub para configurar compilaciones de integración continua para proyectos de WinUI. En este artículo, veremos diferentes maneras de hacerlo. También le mostraremos cómo realizar estas tareas mediante la línea de comandos para que pueda integrarse con cualquier otro sistema de compilación.

Prerrequisitos

Paso 1: Configurar el certificado

Las aplicaciones MSIX deben iniciar sesión para poder instalarse. Si ya tiene un certificado, puede omitir este paso. Para crear fácilmente un certificado de prueba, abra la aplicación en Visual Studio, haga clic con el botón derecho en el proyecto de WinUI y seleccione Empaquetar y publicar ->Crear paquetes de aplicaciones.

A continuación, seleccione Siguiente para ir a la página Seleccionar método de firma y haga clic en el botón Crear... para crear un nuevo certificado. Elija el nombre del publicador y deje el campo contraseña en blanco y cree el certificado.

A continuación, cierre o cancele los diálogos y observe que se ha creado un nuevo archivo .pfx en el proyecto. Este es el certificado con el que puede firmar su MSIX.

Paso 2: Agrega tu certificado a los secretos de Actions

Debe evitar enviar certificados al repositorio si es posible y Git los omite de forma predeterminada. Para gestionar el manejo seguro de archivos confidenciales como certificados, GitHub admite secretos.

Para cargar un certificado para la compilación automatizada:

  1. Codificar el certificado como una cadena base 64: abra PowerShell en el directorio que contiene el certificado y ejecute el siguiente comando, reemplazando el nombre de archivo pfx por el nombre de archivo del certificado.
$pfx_cert = Get-Content 'App1_TemporaryKey.pfx' -AsByteStream

[System.Convert]::ToBase64String($pfx_cert) | Out-File 'App1_TemporaryKey_Base64.txt'
  1. En tu repositorio de GitHub, ve a la página de Configuración y haz clic en Secretos a la izquierda.
  2. Haga clic en Nuevo secreto de repositorio, nómbrelo BASE64_ENCODED_PFX y copie y pegue el texto del archivo de texto de la salida de PowerShell en el valor del secreto.

Paso 3: Configuración del flujo de trabajo

A continuación, en el repositorio, vaya a la pestaña Acciones y cree un flujo de trabajo. Elija la opción configurar un flujo de trabajo usted mismo en lugar de una de las plantillas de flujo de trabajo.

Copie o pegue lo siguiente en el archivo de flujo de trabajo y, a continuación, actualice...

  1. Solution_Name al nombre de su solución
  2. dotnet-version hasta 8.0.x (o cualquier otra versión de .NET a la que esté destinado el proyecto)

Nota:

Para el paso que carga el artefacto (el último paso siguiente), si la salida de la compilación no llega a una carpeta que contiene la solución, reemplace env.Solution_Name por github.workspace (la carpeta Área de trabajo de acciones de GitHub).

# This workflow will build, sign, and package a WinUI MSIX desktop application
# built on .NET.

name: WinUI MSIX app

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:

  build:

    strategy:
      matrix:
        configuration: [Release]
        platform: [x64, x86]

    runs-on: windows-latest  # For a list of available runner types, refer to
                             # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on

    env:
      Solution_Name: your-solution-name                         # Replace with your solution name, i.e. App1.sln.

    steps:
    - name: Checkout
      uses: actions/checkout@v4
      with:
        fetch-depth: 0

    # Install the .NET workload
    - name: Install .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 8.0.x

    # Add  MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
    - name: Setup MSBuild.exe
      uses: microsoft/setup-msbuild@v2

    # Restore the application to populate the obj folder with RuntimeIdentifiers
    - name: Restore the application
      run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
      env:
        Configuration: ${{ matrix.configuration }}

    # Decode the base 64 encoded pfx and save the Signing_Certificate
    - name: Decode the pfx
      run: |
        $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.BASE64_ENCODED_PFX }}")
        $certificatePath = "GitHubActionsWorkflow.pfx"
        [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)

    # Create the app package by building and packaging the project
    - name: Create the app package
      run: msbuild $env:Solution_Name /p:Configuration=$env:Configuration /p:Platform=$env:Platform /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:AppxPackageDir="$env:Appx_Package_Dir" /p:GenerateAppxPackageOnBuild=true
      env:
        Appx_Bundle: Never
        Appx_Package_Build_Mode: SideloadOnly
        Appx_Package_Dir: Packages\
        Configuration: ${{ matrix.configuration }}
        Platform: ${{ matrix.platform }}

    # Remove the pfx
    - name: Remove the pfx
      run: Remove-Item -path GitHubActionsWorkflow.pfx

    # Upload the MSIX package: https://github.com/marketplace/actions/upload-a-build-artifact
    - name: Upload MSIX package
      uses: actions/upload-artifact@v4
      with:
        name: MSIX Package - ${{ matrix.platform }}
        path: ${{ env.Solution_Name }}\\Packages

Paso 4: Confirmar el flujo de trabajo y verlo ejecutar.

Confirme el archivo de flujo de trabajo en la rama principal y, a continuación, vaya a la pestaña Acciones del repositorio de GitHub y vea cómo se ejecuta el flujo de trabajo. Debe ejecutarse con éxito y producir archivos que contengan su aplicación MSIX compilada.

Compilar un paquete x86 y x64 para Microsoft Store

El flujo de trabajo anterior utiliza una matriz para crear paquetes x86 y x64 independientes para la carga lateral. Para crear un archivo de carga de paquetes para el Microsoft Store, compile ambas arquitecturas en una sola invocación de MSBuild en su lugar. La AppxBundlePlatforms propiedad especifica las arquitecturas de la agrupación, AppxBundle=Always crea la agrupación y UapAppxPackageBuildMode=StoreUpload crea el .msixupload archivo .

Use el siguiente flujo de trabajo en lugar del flujo de trabajo en el paso 3:

name: WinUI Microsoft Store package

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: windows-latest

    env:
      Solution_Name: your-solution-name.sln
      Configuration: Release
      Bundle_Platforms: x86|x64
      Appx_Package_Dir: Packages\

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Install .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 8.0.x

    - name: Setup MSBuild.exe
      uses: microsoft/setup-msbuild@v2

    - name: Restore the application
      run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration

    - name: Create the Store package
      run: >
        msbuild $env:Solution_Name
        /p:Configuration=$env:Configuration
        /p:Platform=x86
        /p:AppxBundlePlatforms="$env:Bundle_Platforms"
        /p:AppxBundle=Always
        /p:UapAppxPackageBuildMode=StoreUpload
        /p:AppxPackageDir="$env:Appx_Package_Dir"
        /p:AppxPackageSigningEnabled=false
        /p:GenerateAppxPackageOnBuild=true

    - name: Upload the Store package
      uses: actions/upload-artifact@v4
      with:
        name: Microsoft Store package
        path: '**/Packages/**'

La propiedad Platform=x86 selecciona la configuración de la solución que invoca el objetivo de empaquetado. AppxBundlePlatforms=x86|x64 controla qué arquitecturas compila el destino y se incluyen en el paquete. El Microsoft Store firma el paquete después del envío, por lo que en este ejemplo se deshabilita la firma del paquete.

Antes de cargar el archivo .msixupload, asegúrese de que la identidad del paquete de su manifiesto coincida con la identidad que Partner Center ha asignado a su aplicación. Para conocer los pasos de envío restantes, consulte Creación de un envío de aplicación.

Compilación desde la línea de comandos

Si desea compilar la solución mediante la línea de comandos o mediante cualquier otro sistema de CI, ejecute MSBuild con estos argumentos. La GenerateAppxPackageOnBuild propiedad hace que se genere el paquete MSIX.

/p:AppxPackageDir="Packages"
/p:UapAppxPackageBuildMode=SideloadOnly
/p:AppxBundle=Never
/p:GenerateAppxPackageOnBuild=true

Para crear el archivo de carga del paquete x86 y x64 para el Microsoft Store desde la línea de comandos, ejecute:

msbuild YourSolution.sln `
    /p:Configuration=Release `
    /p:Platform=x86 `
    /p:AppxBundlePlatforms="x86|x64" `
    /p:AppxBundle=Always `
    /p:UapAppxPackageBuildMode=StoreUpload `
    /p:AppxPackageDir="Packages\" `
    /p:AppxPackageSigningEnabled=false `
    /p:GenerateAppxPackageOnBuild=true

Paso 1: Configurar el flujo de trabajo

En el repositorio de GitHub, vaya a la pestaña Acciones y cree un flujo de trabajo. Elija la opción configurar un flujo de trabajo usted mismo en lugar de una de las plantillas de flujo de trabajo.

Copie o pegue lo siguiente en el archivo de flujo de trabajo y, a continuación, actualice...

  1. Solution_Name al nombre de su solución
  2. dotnet-version hasta 8.0.x (o cualquier otra versión de .NET a la que esté destinado el proyecto)

Nota:

Para el paso que carga el artefacto (el último paso siguiente), si la salida de la compilación no llega a una carpeta que contiene la solución, reemplace env.Solution_Name por github.workspace (la carpeta Área de trabajo de acciones de GitHub).

# This workflow will build and publish a WinUI unpackaged desktop application
# built on .NET.

name: WinUI unpackaged app

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:

  build:

    strategy:
      matrix:
        configuration: [Release]
        platform: [x64, x86]

    runs-on: windows-latest  # For a list of available runner types, refer to
                             # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on

    env:
      Solution_Name: your-solution-name                         # Replace with your solution name, i.e. App1.sln.

    steps:
    - name: Checkout
      uses: actions/checkout@v4
      with:
        fetch-depth: 0

    # Install the .NET workload
    - name: Install .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 8.0.x

    # Add  MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
    - name: Setup MSBuild.exe
      uses: microsoft/setup-msbuild@v2

    # Restore the application to populate the obj folder with RuntimeIdentifiers
    - name: Restore the application
      run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
      env:
        Configuration: ${{ matrix.configuration }}

    # Create the app by building and publishing the project
    - name: Create the app
      run: msbuild $env:Solution_Name /t:Publish /p:Configuration=$env:Configuration /p:Platform=$env:Platform
      env:
        Configuration: ${{ matrix.configuration }}
        Platform: ${{ matrix.platform }}

    # Upload the app
    - name: Upload app
      uses: actions/upload-artifact@v4
      with:
        name: Upload app - ${{ matrix.platform }}
        path: ${{ env.Solution_Name }}\\bin

Paso 2: Confirmar el flujo de trabajo y verlo ejecutar.

Confirme el archivo de flujo de trabajo en la rama principal y, a continuación, vaya a la pestaña Acciones del repositorio de GitHub y vea cómo se ejecuta el flujo de trabajo. Debe ejecutarse correctamente y generar artefactos que contengan tu aplicación compilada.

Compilación desde la línea de comandos

Si desea compilar la solución mediante la línea de comandos o mediante cualquier otro sistema de CI, ejecute MSBuild con el /t:Publish argumento .

Azure Pipelines

Si el equipo usa Azure DevOps, puede compilar aplicaciones winUI 3 con Azure Pipelines. La siguiente canalización de YAML compila una aplicación WinUI msIX empaquetada en un agente de Windows:

trigger:
  - main

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'x64'
  buildConfiguration: 'Release'

steps:
- task: UseDotNet@2
  displayName: 'Install .NET SDK'
  inputs:
    packageType: 'sdk'
    version: '8.0.x'

- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Build MSIX package'
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
    msbuildArgs: |
      /p:AppxBundlePlatforms="$(buildPlatform)"
      /p:AppxPackageDir="$(Build.ArtifactStagingDirectory)\AppxPackages\\"
      /p:AppxBundle=Never
      /p:UapAppxPackageBuildMode=SideloadOnly
      /p:GenerateAppInstallerFile=false

- task: PublishBuildArtifacts@1
  displayName: 'Publish MSIX artifacts'
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)\AppxPackages'
    ArtifactName: 'msix-package'

Nota:

Para las compilaciones sin empaquetar, quite los /p:Appx* argumentos de MSBuild y use dotnet publish en lugar de VSBuild. Consulte la sección de línea de comandos anterior para obtener más información.

Para firmar paquetes MSIX en una canalización, almacene el certificado en Azure Pipelines archivos seguros y use la tarea DownloadSecureFile para acceder a él durante la compilación.

Importante

Nunca almacene certificados de firma ni sus contraseñas en el control de código fuente. Use variables secretas de la canalización para la contraseña del certificado y Archivos seguros de Azure Pipelines para el propio certificado.