Skip to content

Hidden Implementation Techniques for MAUI iOS Azure DevOps Build Pipelines

Getting Started with MAUI

The Microsoft documentation for building and deploying a MAUI app is quite comprehensive, but the lack of certain implementation details can hinder the speed of your template development. This post covers two useful implementation techniques, for constructing an iOS build pipeline for Azure DevOps for your MAUI project, which are not always clearly explained in the documentation.

  1. Installing App Store Distribution certificates on the agent
    • Ensuring the build tooling knows what certificate to use
  1. MAUI SDK’s csproj property to info.plist value feature
    • Example: Incrementing the Application version (iOS: cfbundleversion)
💡 For assistance with the basics, here are some documentation links: MAUI iOS Deployment (Microsoft) https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/

Installing and Picking Certificates

Adding the build certificate and provisioning profile is straightforward with the Microsoft provided tasks:

- task: InstallAppleCertificate@2
    inputs:
      certSecureFile: "$(IOS:CertificateSecureFileName)"
      certPwd: "$(IOS:CertPassword)"
      keychain: "temp"
  - task: InstallAppleProvisioningProfile@1
    inputs:
      provisioningProfileLocation: "secureFiles"
      provProfileSecureFile: "$(IOS:ProvisioningSecureFileName)"
Code language: YAML (yaml)

An obscure but important detail is that building with Automatic provisioning (Visual Studios default setting) doesn’t always work, and you will likely need to explicitly pick the signing certificate to use. If it’s not working, you will get the error “Could not find any available provisioning profiles." To resolve this, either predefine the CodesignKey property in your MAUI .csproj file with the description of your certificate (e.g., iPhone Distribution: Foo, Inc. (HS222268M)), or if you need dynamic use of certificates, then you can get the name of the certificate from the InstallAppleCertificate@2 and pass it as a parameter to the eventual dotnet build call:

#APPLE_CERTIFICATE_SIGNING_IDENTITY is a string composed of Certificate Type: Certificate Issuer and Certificate Identifier and is set by InstallAppleCertificate@2 
dotnet publish -f net7.0-ios -c Release -p:CodesignKey="$(APPLE_CERTIFICATE_SIGNING_IDENTITY)"
Code language: YAML (yaml)

Note: You will need to format any commas in the certificate description so that it works as a parameter:

- powershell: |
      $certName = "$(APPLE_CERTIFICATE_SIGNING_IDENTITY)"
      $replacedString = $certName -replace ",", "%2c"
      Write-Host "##vso[task.setvariable variable=FormattedCertName]$replacedString"
Code language: YAML (yaml)

Setting info.plist Entries with MAUI SDK

As mentioned above, with the CodesignKey property, the MAUI SDK will grab specific properties from your csproj file to populate info.plist values. For example, every build of an iOS needs to have a build version (cfbundleversion) greater than the previous one. You can leverage MAUI SDK to ensure your bundle version is properly set via the ApplicationVersion property. However you choose to implement your bundle version incrementation (commit number, build date, manual, etc.), you can set it via the MAUI .csproj ApplicationVersion property manually:

<ApplicationVersion>123</ApplicationVersion>Code language: HTML, XML (xml)

Or passed via a build parameter:

dotnet publish -f net7.0-ios -c Release -p:ApplicationVersion="$(APPLICATIONVERSION)"Code language: YAML (yaml)

Other Useful Project Properties

  • ApplicationId
    • Becomes the Bundle ID (CFBundleIdentifier)
    • e.g. com.foocompany.app
  • ApplicationTitle
    • Becomes the app name (CFBundleDisplayName)

Please comment if you know of other good ones, as I haven’t found a good resource that lists them all.

Example Build Step

- task: Bash@3
    displayName: Build iOS App
    inputs:
      targetType: "inline"
      script: |
        echo "building with application version: $(APPLICATIONVERSION)"
        cd MyMauiApp
        dotnet publish -f net7.0-ios -c Release -p:ApplicationVersion="$(APPLICATIONVERSION)" -p:ApplicationTitle="$(Maui:AppName)" -p:ApplicationId="$(IOS:BundleId)" -p:CodesignKey="$(FormattedCertName)"
Code language: YAML (yaml)

Wrapping Up

By installing and selecting certificates appropriately, leveraging the MAUI SDK’s csproj properties for info.plist values, and utilizing other essential project properties, developers can optimize their MAUI app development process and streamline the deployment using Azure DevOps. With these insights and practical examples, you are now equipped to confidently overcome challenges, enhance your productivity, and build successful MAUI apps.

Want More?

Do you want to learn more about MAUI? Check out Kevin Bost’s Warm Up with .NET MAUI presentation from the Spokane .NET Conference.

Does Your Organization Need a Custom Solution?

Let’s chat about how we can help you achieve excellence on your next project!

Tags: