Skip to content

Instantly share code, notes, and snippets.

@LanceMcCarthy
Last active May 7, 2025 19:25
Show Gist options
  • Select an option

  • Save LanceMcCarthy/0fa5c1af7c2b73f5c51b703db72da144 to your computer and use it in GitHub Desktop.

Select an option

Save LanceMcCarthy/0fa5c1af7c2b73f5c51b703db72da144 to your computer and use it in GitHub Desktop.

Revisions

  1. LanceMcCarthy revised this gist Dec 19, 2023. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -104,7 +104,7 @@ dotnet publish -f net8.0-android -c Release \

    ### iOS

    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile).
    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile), also see how you can import these items to the runner easily [here](https://github.com/marketplace/actions/import-code-signing-certificates).

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
    @@ -129,7 +129,7 @@ dotnet publish -f net8.0-ios -c Release \

    ### MacCatalyst

    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile).
    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile), also see how you can import these items to the runner easily [here](https://github.com/marketplace/actions/import-code-signing-certificates).

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
  2. LanceMcCarthy revised this gist Dec 19, 2023. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -68,7 +68,7 @@ To help jumpstart your workflow commands, here are some publish commands that us

    ### Windows

    Example secrets and thier values (important, these should not be plain-text env vars)
    Example secrets and thier values (important, these should not be plain-text env vars). See how I prepare a Windows signing certificate file from a GitHub secret [here](https://github.com/LanceMcCarthy/MediaFileManager/blob/7e0fadc39b4429225f2751d5ab0794dda2df59fc/.github/workflows/cd_release_sideload.yml#L111).

    - PFX_Certificate_Thumbprint: "MyMauiApp"
    - PFX_FilePath: "MyCert.pfx"
    @@ -104,7 +104,7 @@ dotnet publish -f net8.0-android -c Release \

    ### iOS

    Example secrets and thier values (important, these should not be plain-text env vars)
    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile).

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
    @@ -129,7 +129,7 @@ dotnet publish -f net8.0-ios -c Release \

    ### MacCatalyst

    Example secrets and thier values (important, these should not be plain-text env vars)
    Example secrets and thier values (important, these should not be plain-text env vars). You can learn how to set your p12 and provisioing profile as secrets [here](https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development#creating-secrets-for-your-certificate-and-provisioning-profile).

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
  3. LanceMcCarthy revised this gist Dec 18, 2023. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    # .NET MAUI Publishing Resources

    So you're done building your .NET MAUI application, congrats! Now it's time to publish them, this can be a tricky topic, even to professionsal who do this reguarly.
    So you're done building your .NET MAUI application, congrats! Now it's time to publish them, This can be a tricky topic to navigate, even to dedicated DevOps engineers who do this regularly because of the number of moving pieces in the puzzle.

    To help, I have combined several resources that are a great place to get started, but to also act as a quick "look up " reference that you can bookmark.
    To help you, I have combined several resources that are a great place to get started. These are not only a good Getting Started experience, but it's also a good thing to bookmark as a quick look-up reference.

    ## Table of Contents

  4. LanceMcCarthy revised this gist Dec 18, 2023. 1 changed file with 81 additions and 0 deletions.
    81 changes: 81 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -148,3 +148,84 @@ dotnet publish -f net8.0-maccatalyst -c Release \
    -p:CodesignEntitlements="Platforms\MacCatalyst\Entitlements.plist"
    ```

    ## Alternate Approach

    If you are on a local device machine and have your certificates available, then you can also have conditional statements in the csproj file that will automatically apply these settings when in Release mode.

    ```xml
    <Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
    <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
    <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
    ... app stuff

    <!-- Display name -->
    <ApplicationTitle>MyApp</ApplicationTitle>

    <!-- ****** Important App Identifiers ****** -->
    <!-- Windows -->
    <ApplicationId Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">com.lancelotsoftware.MyApp</ApplicationId>
    <ApplicationIdGuid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">61FFFFAC6-FFFFF-4830-FFFFF-78DFFF85CC</ApplicationIdGuid>

    <!-- MacCatalyst -->
    <ApplicationId Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">com.lancelotsoftware.MyApp</ApplicationId>
    <ApplicationIdGuid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">61FFFFC6-FFFF-4830-FFFF-78DFFFF85CC</ApplicationIdGuid>

    <!-- iOS -->
    <ApplicationId Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">com.lancelotsoftware.MyApp</ApplicationId>
    <ApplicationIdGuid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">61717AC6-FFFF-4830-FFFF-78DD35E085CC</ApplicationIdGuid>
    <ProvisioningType Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">manual</ProvisioningType>
    <CodesignKey Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">Apple Distribution: Lancelot Software, LLC (XXXXXXXXXX)</CodesignKey>

    <!-- Android -->
    <ApplicationId Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">com.lancelotsoftware.MyApp</ApplicationId>
    <ApplicationIdGuid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">617FFAC6-FFFF-4830-B715-78DFFFF85CC</ApplicationIdGuid>
    <ProvisioningType Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">manual</ProvisioningType>
    <CodesignKey Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">Apple Distribution: Lancelot Software, LLC (XXXXXXXXXX)</CodesignKey>

    ... target platform stuff
    </PropertyGroup>

    <ItemGroup>
    ... icons and assets
    </ItemGroup>

    <ItemGroup>
    ... nuget packages
    </ItemGroup>

    <!-- ******** Android ******** -->

    <PropertyGroup Condition="$(TargetFramework.Contains('-android')) and '$(Configuration)' == 'Release'">
    <AndroidKeyStore>True</AndroidKeyStore>
    <AndroidSigningKeyStore>lance.keystore</AndroidSigningKeyStore>
    <AndroidSigningStorePass>$(android_keystore_password)</AndroidSigningStorePass>
    <AndroidSigningKeyAlias>lance.alias</AndroidSigningKeyAlias>
    <AndroidSigningKeyPass>$(android_keystore_alias_password)</AndroidSigningKeyPass>
    </PropertyGroup>


    <!-- ******** iOS ******** -->

    <PropertyGroup Condition="$(TargetFramework.Contains('-ios')) and '$(Configuration)' == 'Release'">
    <RuntimeIdentifier>ios-arm64</RuntimeIdentifier>
    <CodesignKey>Apple Distribution: Lancelot Software, LLC (XXXXXXXXX)</CodesignKey>
    <CodesignProvision>MyApp_AdHoc_2023.mobileprovision</CodesignProvision>
    or for store
    <CodesignProvision>MyApp_AppStore_2023.mobileprovision</CodesignProvision>
    </PropertyGroup>


    <!-- ******** MacCatalyst ******** -->

    <PropertyGroup Condition="$(TargetFramework.Contains('-maccatalyst')) and '$(Configuration)' == 'Release'">
    <RuntimeIdentifier>maccatalyst-x64</RuntimeIdentifier>
    <CodesignKey>Apple Distribution: Lancelot Software, LLC (XXXXXXXXX)</CodesignKey>
    <CodesignProvision>MyApp_MacStore_2023.provisionprofile</CodesignProvision>
    </PropertyGroup>

    <!-- ******** Windows (use VS2022 Publish tooling or CLI) ******** -->

    </Project>
    ```

  5. LanceMcCarthy revised this gist Dec 18, 2023. 1 changed file with 99 additions and 4 deletions.
    103 changes: 99 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,11 +2,19 @@

    So you're done building your .NET MAUI application, congrats! Now it's time to publish them, this can be a tricky topic, even to professionsal who do this reguarly.

    so, I have combined several resources that are a great place ot get started, but to also act as a quick "look up " reference that you can bookmark.
    To help, I have combined several resources that are a great place to get started, but to also act as a quick "look up " reference that you can bookmark.

    ## Microsoft Documentation
    ## Table of Contents

    First, let's go through some links to the Microsoft docs. The MAUI team has put a lot of effort in making these articles helpful and up to date in explainaing the different parts that come together when packaging and publishing your application. These docs are born out of the efforts of many repo issue conversations and internal experiences on the team.
    - [Documentation](#documentation)
    - [Demos and Tools](#demos-and-tools)
    - [Videos](#videos)
    - [Commands](#commands)


    ## Documentation

    First, let's go through some links to the Microsoft docs. The MAUI team has put *a lot of effort* in making these articles helpful and relevant packaging and publishing your application. These docs are born out of the efforts of many repo issue conversations and internal experiences on the team. they saw the difficulties devs were having and refined the documentation to tailor to those topics.

    There are many more article in this section, but I wanted to combine the ones you want to definitely visit.

    @@ -36,7 +44,7 @@ There are many more article in this section, but I wanted to combine the ones yo
    - [Ad hoc](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-ad-hoc?view=net-maui-8.0)


    ## Demos & Tools
    ## Demos and Tools

    Although I cannot share exact details due to the sensitive nature of code signing certificates and publisher identities, but we can still review the general setup where you can plug in your details.

    @@ -53,3 +61,90 @@ Gerald Versluis has an amazing set of videos about .NET MAUI on YouTube. Several
    - [Publish .NET MAUI iOS project](https://youtu.be/kpZi5xAvpZA?si=h9DuREO8gfbYjNGV)
    - [Publish your .NET MAUI Android project](https://youtu.be/jfSVb_RR7X0?si=2_ZnQqB-YuziI-Ix)
    - [Publish an unpackaged (no MSIX) .NET MAUI Windows project](https://youtu.be/GgU4ulGYQEk?si=JOI_bglEpmlbtM3Q)

    ## Commands

    To help jumpstart your workflow commands, here are some publish commands that use environment secrets.

    ### Windows

    Example secrets and thier values (important, these should not be plain-text env vars)

    - PFX_Certificate_Thumbprint: "MyMauiApp"
    - PFX_FilePath: "MyCert.pfx"
    - PFX_Password: "MyCertPassword"

    ```powershell
    dotnet publish MyApp.csproj -c Release -f:net6.0-windows10.0.19041.0 \
    /p:GenerateAppxPackageOnBuild=true \
    /p:AppxPackageSigningEnabled=true \
    /p:PackageCertificateKeyFile=${{ secret.PFX_FilePath }} \
    /p:PackageCertificatePassword=${{ secret.PFX_Password }} \
    /p:PackageCertificateThumbprint=${{ secret.PFX_Certificate_Thumbprint }}
    ```

    ### Android

    Example secrets and thier values (important, these should not be plain-text env vars)

    - AndroidKeyStore: "john.keystore"
    - AndroidKeyAlias: "john"
    - AndroidKeyPass: "myKeyPassword"
    - AndroidStorePass: "myStorePassword"

    The publish command
    ```powershell
    dotnet publish -f net8.0-android -c Release \
    -p:AndroidKeyStore=true \
    -p:AndroidSigningKeyStore="${{ secrets.AndroidKeyStore }}" \
    -p:AndroidSigningKeyAlias="${{ secrets.AndroidKeyAlias }}" \
    -p:AndroidSigningKeyPass="${{ secrets.AndroidKeyPass }}" \
    -p:AndroidSigningStorePass="${{ secrets.AndroidStorePass }}"
    ```

    ### iOS

    Example secrets and thier values (important, these should not be plain-text env vars)

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
    - MacIpAddress: "192.168.1.100"
    - MacPort: "58181"
    - MacUsername: "JohnDoe"
    - MacUserPassword: "JohnsMacPassword"

    The publish command form a Windows machine, connecting to a Mac host (you can omit the server parameters if building on a Mac)
    ```powershell
    dotnet publish -f net8.0-ios -c Release \
    -p:ArchiveOnBuild=true \
    -p:RuntimeIdentifier=ios-arm64 \
    -p:CodesignKey="${{ secrets.AppleCodesignKey }}" \
    -p:CodesignProvision="${{ secrets.AppleCodesignProvisioningProfile }}" \
    -p:ServerAddress="${{ secrets.MacIpAddress }}" \
    -p:ServerUser="${{ secrets.MacUsername }}" \
    -p:ServerPassword="${{ secrets.MacUserPassword }}" \
    -p:TcpPort="${{ secrets.MacPort }}" \
    -p:_DotNetRootRemoteDirectory="/Users/${{ secrets.MacUsername }}/Library/Caches/Xamarin/XMA/SDKs/dotnet/"
    ```

    ### MacCatalyst

    Example secrets and thier values (important, these should not be plain-text env vars)

    - AppleCodesignProvisioningProfile: "MyMauiApp"
    - AppleCodesignKey: "Apple Distribution: John Doe (ABCDE1234)"
    - MacPackageSignKey: "3rd Party Mac Developer Installer: John Doe (ABCDE1234)"

    The publish command form a Windows machine, connecting to a Mac host (you can omit the server parameters if building on a Mac)
    ```powershell
    dotnet publish -f net8.0-maccatalyst -c Release \
    -p:MtouchLink=SdkOnly \
    -p:CreatePackage=true \
    -p:EnableCodeSigning=true \
    -p:EnablePackageSigning=true \
    -p:PackageSigningKey="${{ secrets.MacPackageSignKey }}" \
    -p:CodesignKey="${{ secrets.AppleCodesignKey }}" \
    -p:CodesignProvision="${{ secrets.AppleCodesignProvisioningProfile }}" \
    -p:CodesignEntitlements="Platforms\MacCatalyst\Entitlements.plist"
    ```

  6. LanceMcCarthy revised this gist Dec 18, 2023. 1 changed file with 6 additions and 10 deletions.
    16 changes: 6 additions & 10 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -47,13 +47,9 @@ The microsoft docs above explain what most of this is, and how you can create th

    ## Videos

    Gerald Versluis has an amazing set of videos about .NET MAUI on YouTube. Several of them have been about publishing your project. I highly recommend checking out his channel, but I'll list a few of my favorites here:

    - []()
    - []()
    - []()
    - []()
    - []()
    - []()
    - []()
    - []()
    Gerald Versluis has an amazing set of videos about .NET MAUI on YouTube. Several of them have been about publishing your project. I highly recommend [checking out his channel](https://www.youtube.com/@jfversluis/videos), there is a **ton** of great MAUI content there. I'll list the publishing-specific topics ones here:

    - [Building .NET MAUI for Windows with GitHub Actions](https://youtu.be/8lvdLa0v8zY?si=F7MS5y7UAu0UbQVR)
    - [Publish .NET MAUI iOS project](https://youtu.be/kpZi5xAvpZA?si=h9DuREO8gfbYjNGV)
    - [Publish your .NET MAUI Android project](https://youtu.be/jfSVb_RR7X0?si=2_ZnQqB-YuziI-Ix)
    - [Publish an unpackaged (no MSIX) .NET MAUI Windows project](https://youtu.be/GgU4ulGYQEk?si=JOI_bglEpmlbtM3Q)
  7. LanceMcCarthy created this gist Dec 18, 2023.
    59 changes: 59 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    # .NET MAUI Publishing Resources

    So you're done building your .NET MAUI application, congrats! Now it's time to publish them, this can be a tricky topic, even to professionsal who do this reguarly.

    so, I have combined several resources that are a great place ot get started, but to also act as a quick "look up " reference that you can bookmark.

    ## Microsoft Documentation

    First, let's go through some links to the Microsoft docs. The MAUI team has put a lot of effort in making these articles helpful and up to date in explainaing the different parts that come together when packaging and publishing your application. These docs are born out of the efforts of many repo issue conversations and internal experiences on the team.

    There are many more article in this section, but I wanted to combine the ones you want to definitely visit.

    [Understanding project Confguration and various flags](https://learn.microsoft.com/en-us/dotnet/maui/deployment/visual-studio-properties?view=net-maui-8.0)

    - Android
    - [Overview](https://learn.microsoft.com/en-us/dotnet/maui/android/deployment/?view=net-maui-8.0)
    - [Google Play](https://learn.microsoft.com/en-us/dotnet/maui/android/deployment/publish-google-play?view=net-maui-8.0)
    - [Ad Hoc](https://learn.microsoft.com/en-us/dotnet/maui/android/deployment/publish-ad-hoc?view=net-maui-8.0)
    - [Using dotnet publish via CLI commands](https://learn.microsoft.com/en-us/dotnet/maui/android/deployment/publish-cli?view=net-maui-8.0)
    - iOS
    - [Overview](https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/?view=net-maui-8.0)
    - [App Store](https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/publish-app-store?view=net-maui-8.0)
    - [Ad Hoc](https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/publish-ad-hoc?view=net-maui-8.0)
    - [In-house](https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/publish-in-house?view=net-maui-8.0)
    - [Using dotnet publish via CLI commands](https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/publish-cli?view=net-maui-8.0)
    - Windows
    - [Overview](https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/overview?view=net-maui-8.0)
    - [Packaged (eg, MSIX)](https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-cli?view=net-maui-8.0)
    - [Unpackaged (eg, exe)](https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-unpackaged-cli?view=net-maui-8.0)
    - [Using dotnet publish via CLI commands](https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-cli?view=net-maui-8.0)
    - MacCatalyst
    - [Overview](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/?view=net-maui-8.0)
    - [App Store](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-app-store?view=net-maui-8.0)
    - [Outside of the App Store (signed)](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-outside-app-store?view=net-maui-8.0)
    - [Outside of App Store (unsigned)](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-unsigned?view=net-maui-8.0)
    - [Ad hoc](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-ad-hoc?view=net-maui-8.0)


    ## Demos & Tools

    Although I cannot share exact details due to the sensitive nature of code signing certificates and publisher identities, but we can still review the general setup where you can plug in your details.

    The microsoft docs above explain what most of this is, and how you can create the prerequisites, the demos are intended to show you how you can set it up in your CI-CD workflows

    - [MAUI Project Archive/Publish for VSCode](https://github.com/banditoth/maui-archiver-vscode) - This tool is an extension for Visual Studio Code and provides a set of essential tools to streamline the process of packaging and publishing a .NET MAUI app.
    - [DevOps Examples]() - This repo has many different projects types and is intended ot show how to write workflows to compile each. [One is a .NET MAUI project](https://github.com/LanceMcCarthy/DevOpsExamples/tree/main/src/MAUI/MauiDemo) and [the accompanying workflow](https://github.com/LanceMcCarthy/DevOpsExamples/blob/main/.github/workflows/main_build-maui.yml) has a separate job for each platform

    ## Videos

    Gerald Versluis has an amazing set of videos about .NET MAUI on YouTube. Several of them have been about publishing your project. I highly recommend checking out his channel, but I'll list a few of my favorites here:

    - []()
    - []()
    - []()
    - []()
    - []()
    - []()
    - []()
    - []()