In this post I will show you how you can set up continuous integration (CI) for your .NET MAUI Windows app in Azure DevOps. If you want to check out how you can do this for Android and iOS, you can check out my other posts for them here and here. This post is heavily inspired by Gerald Versluis’s video on how to sideload or publish your MAUI Windows app.
Create your pipeline
Start off by creating a new pipeline from Azure DevOps. Select the “Starter pipeline” and name your YAML file something like
windows-maui-build.yml. We’ll modify this with the steps needed to create the MSIX file for your Windows app.
Select your VM image
In your new YAML file, we need to modify this to use an image running Windows. We’ll be using the
pool: vmImage: windows-latest
Install the MAUI workload
Next, we’ll install the .NET MAUI workload onto the build agent. We need this to be able to build .NET MAUI apps. This can be done using the Command Line task and the
dotnet workload command:
- task: CmdLine@2 inputs: script: 'dotnet workload install maui'
Now we can build the app using the .NET Core task with some arguments. We’ll use the
publish command to output a MSIX file and set the target framework to
net6.0-windows10.0.19041.0. Make sure that this matches the one in your csproj.
- task: DotNetCoreCLI@2 inputs: command: 'publish' publishWebProjects: false projects: 'MyMAUIProject.sln' arguments: '-c $(buildConfiguration) -f:net6.0-windows10.0.19041.0' zipAfterPublish: false modifyOutputPath: false
Where do I sign?
If you want to publish the resulting MSIX file to Windows Store, you can use this without having to sign your package. However, if you plan on sideloading your app, you’ll need to sign your app. You can do this with a self-signed certificate (mostly used for testing) or a certificate issued by a trusted source. For instructions on how to create a self-signed certificate, follow this guide.
Once you have created and exported this certificate, go ahead and upload this to Secure Files in your project in Azure DevOps.
In your pipeline, add the Download Secure File task and point it at the certificate you just uploaded:
- task: DownloadSecureFile@1 inputs: secureFile: 'mymauiwindowscert.pfx'
Copy the MSIX file over to the artifact staging directory so that we more easily can sign it from there:
- task: CopyFiles@2 inputs: SourceFolder: '$(Agent.BuildDirectory)' Contents: '**/MyMauiProject*.msix' TargetFolder: '$(Build.ArtifactStagingDirectory)' flattenFolders: true
Now we’re ready to do the actual signing. We’ll run a custom script to sign the MSIX package using our certificate and the password we used to generate the certificate.
- script: '"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\SignTool" sign /fd SHA256 /f $(Agent.TempDirectory)/mymauiwindowscert.pfx /p sup3rs3cr3tp4ssw0rd $(Build.ArtifactStagingDirectory)\MyMauiProject_126.96.36.199_x64.msix' displayName: 'Sign MSIX Package'
And that should provide you with a signed MSIX package ready for distribution!
Here’s the final YAML file:
As you might have noticed, the signing step is hard-coded to a specific version, so this could probably be set as a pipeline variable or be tied to some auto-incrementing of build number during CI.
Microsoft also recently published a great blog post regarding DevOps for .NET MAUI, which I recommend checking out.