MAUI (Distribution) #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: MAUI (Distribution) | |
| on: | |
| workflow_dispatch: | |
| permissions: | |
| id-token: write # needed for OIDC token use | |
| contents: write # needed for publishing a release | |
| discussions: write | |
| defaults: | |
| run: | |
| shell: pwsh | |
| env: | |
| CSPROJ_PATH: "src/MAUI/MauiDemo.csproj" | |
| NUGETCONFIG_PATH: "src/NuGet.Config" | |
| TELERIK_USERNAME: ${{secrets.MyTelerikAccountUsername}} | |
| TELERIK_PASSWORD: ${{secrets.MyTelerikAccountPassword}} | |
| BUILD_CONFIG: Release | |
| DOTNET_VERSION: "9.0.x" | |
| WINUI_TFM: "net9.0-windows10.0.22621.0" | |
| ANDROID_TFM: "net9.0-android" | |
| IOS_TFM: "net9.0-ios" | |
| MACCATALYST_TFM: "net9.0-maccatalyst" | |
| MACOS_ARTIFACTS_PATH: "artifacts_macos" | |
| IOS_ARTIFACTS_PATH: "artifacts_ios" | |
| ANDROID_ARTIFACTS_PATH: "artifacts_android" | |
| WINDOWS_ARTIFACTS_PATH: "artifacts_windows" | |
| jobs: | |
| # ***************************************** # | |
| # >>>>>>> Generate Common Resources <<<<<<< # | |
| # ***************************************** # | |
| shared-resources: | |
| name: Create Shared Resources | |
| runs-on: windows-2022 | |
| outputs: | |
| app_version: ${{steps.version-creator.outputs.app_version}} | |
| steps: | |
| # Generates a version number using year.monthday.run_number.0 (e.g., 2024.824.1.0) | |
| - name: Generate version number using date and run number | |
| id: version-creator | |
| run: | | |
| $buildDay = Get-Date -Format "yyyy.Mdd" | |
| $runNumber = "$env:GITHUB_RUN_NUMBER" | |
| $ver = $buildDay + "." + $runNumber + ".0" | |
| echo "app_version=$ver" >> $env:GITHUB_OUTPUT | |
| # ********************************************* # | |
| # >>>>>>> Windows Microsoft Store build <<<<<<< # | |
| # ********************************************* # | |
| maui-windows-msstore: | |
| name: Build Windows MS Store | |
| needs: shared-resources | |
| runs-on: windows-2022 | |
| if: ${{ needs.shared-resources.outputs.app_version != ''}} | |
| env: | |
| RID: win10-x64 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{env.DOTNET_VERSION}} | |
| # Needed only for WinUI builds | |
| - name: Add msbuild to PATH | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Install MAUI workloads | |
| run: dotnet workload install maui --source https://api.nuget.org/v3/index.json | |
| - name: Restore NuGet packages | |
| run: dotnet restore ${{env.CSPROJ_PATH}} --configfile ${{env.NUGETCONFIG_PATH}} | |
| # Update the manifest for Microsoft Store using the store's app and publisher identity | |
| - name: Update manifest for Microsoft Store build | |
| run: | | |
| [xml]$manifest = get-content 'src\MAUI\Platforms\Windows\Package.appxmanifest' | |
| $manifest.Package.Identity.Version = "${{needs.shared-resources.outputs.app_version}}" | |
| $manifest.Package.Identity.Name = "61469LanceLotSoftware.MauiDemo" | |
| $manifest.Package.Identity.Publisher = "CN=51B5A8B2-5D86-4826-BBE2-C92E963A4C02" | |
| $manifest.Package.Properties.DisplayName = "MauiDemo" | |
| $manifest.Package.Properties.PublisherDisplayName = "Lancelot Software" | |
| $manifest.Package.Applications.Application.VisualElements.DisplayName = "Maui Demo" | |
| $manifest.save("src\MAUI\Platforms\Windows\Package.appxmanifest") | |
| # Compile and publish the WinUI x64 project for the Microsoft Store (no code signing for store builds, Microsoft signs it) | |
| - name: Build WinUI win10-x64 | |
| run: dotnet publish ${{env.CSPROJ_PATH}} -f "${{env.WINUI_TFM}}" -p:RuntimeIdentifierOverride="win10-x64" -p:PublishTrimmed=False -p:GenerateAppxPackageOnBuild=true -p:AppxPackageSigningEnabled=false -p:EnableMsixTooling=true --self-contained=true | |
| # Find the msix file | |
| - name: Locate msix | |
| id: find-msix-file | |
| run: | | |
| $msixPath = Get-ChildItem -Filter MauiDemo*.msix -Recurse | %{$_.FullName} | |
| echo "PACKAGE_PATH=$msixPath" >> $env:GITHUB_OUTPUT | |
| # Attaching the asset to workflow run | |
| - name: Attach artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: "MauiDemo_v${{needs.shared-resources.outputs.app_version}}_MsftStoreOnly.msix" | |
| path: ${{steps.find-msix-file.outputs.PACKAGE_PATH}} | |
| if-no-files-found: error | |
| retention-days: 30 | |
| # ************************************** # | |
| # >>>>>>> Windows Sideload build <<<<<<< # | |
| # ************************************** # | |
| maui-windows-sideload: | |
| name: Build Windows Sideload | |
| needs: shared-resources | |
| runs-on: windows-2022 | |
| if: ${{ needs.shared-resources.outputs.app_version != ''}} | |
| strategy: | |
| matrix: | |
| RID: [win10-x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{env.DOTNET_VERSION}} | |
| # Needed only for WinUI builds | |
| - name: Add msbuild to PATH | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Install MAUI workloads | |
| run: dotnet workload install maui --source https://api.nuget.org/v3/index.json | |
| - name: Restore NuGet packages | |
| run: dotnet restore ${{env.CSPROJ_PATH}} --configfile ${{env.NUGETCONFIG_PATH}} | |
| # Update the app manifest using the sideload publisher identity (this MUST match the certificate's details) | |
| - name: Update manifest for side load build | |
| run: | | |
| [xml]$manifest = get-content 'src\MAUI\Platforms\Windows\Package.appxmanifest' | |
| $manifest.Package.Identity.Version = "${{needs.shared-resources.outputs.app_version}}" | |
| $manifest.Package.Identity.Name = "LanceMcCarthy.MauiDemo" | |
| $manifest.Package.Identity.Publisher = 'CN=" Lance McCarthy", O=" Lance McCarthy", L=Revere, S=Massachusetts, C=US' | |
| $manifest.Package.Properties.DisplayName = "MauiDemo" | |
| $manifest.Package.Properties.PublisherDisplayName = "Lance McCarthy" | |
| $manifest.Package.Applications.Application.VisualElements.DisplayName = "Maui Demo" | |
| $manifest.save("src\MAUI\Platforms\Windows\Package.appxmanifest") | |
| - name: Build WinUI ${{matrix.RID}} | |
| run: dotnet publish ${{env.CSPROJ_PATH}} -f ${{env.WINUI_TFM}} -p:RuntimeIdentifierOverride=${{matrix.RID}} -p:PublishTrimmed=False -p:GenerateAppxPackageOnBuild=true -p:AppxPackageSigningEnabled=false -p:EnableMsixTooling=true --self-contained=true | |
| - name: Locate msix | |
| id: find-msix-file | |
| run: | | |
| $msixPath = Get-ChildItem -Filter MauiDemo*.msix -Recurse | %{$_.FullName} | |
| echo "PACKAGE_PATH=$msixPath" >> $env:GITHUB_OUTPUT | |
| # No secrets needed, uses the GitHub OIDC token's subject identifier "repo:LanceMcCarthy/DevOpsExamples:ref:refs/heads/main" | |
| # Entra ID App Registration > Certificates and Secrets > Federated Credentials | |
| - name: Azure login using OIDC via GitHub | |
| uses: azure/login@v2 | |
| id: azlogin | |
| with: | |
| client-id: "32daa13b-f4bb-4809-8ef6-58cb39051acd" | |
| tenant-id: "bd47e796-3473-4b8a-9101-1f4c0c7af31a" | |
| subscription-id: "48ab4839-62af-4ab3-afe6-043ea4d7c137" | |
| # CODESIGN (uses Lance's certificate for now) | |
| - name: Sign files with Trusted Signing | |
| uses: azure/[email protected] | |
| with: | |
| endpoint: https://eus.codesigning.azure.net/ | |
| trusted-signing-account-name: PrimaryCodeSign | |
| certificate-profile-name: lancemccarthylivepublic | |
| timestamp-rfc3161: http://timestamp.acs.microsoft.com | |
| timestamp-digest: SHA256 | |
| file-digest: SHA256 | |
| files: ${{steps.find-msix-file.outputs.PACKAGE_PATH}} | |
| exclude-azure-cli-credential: false | |
| exclude-environment-credential: true | |
| exclude-workload-identity-credential: true | |
| exclude-managed-identity-credential: true | |
| exclude-shared-token-cache-credential: true | |
| exclude-visual-studio-credential: true | |
| exclude-visual-studio-code-credential: true | |
| exclude-azure-powershell-credential: true | |
| exclude-azure-developer-cli-credential: true | |
| exclude-interactive-browser-credential: true | |
| - name: Attach artifacts to workflow run | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: "MauiDemo_v${{needs.shared-resources.outputs.app_version}}_${{matrix.RID}}.msix" | |
| path: ${{steps.find-msix-file.outputs.PACKAGE_PATH}} | |
| if-no-files-found: error | |
| retention-days: 30 | |
| # ********************************* # | |
| # >>>>>>> MacCatalyst Build <<<<<<< # | |
| # ********************************* # | |
| maui-macos: | |
| name: Build MacCatalyst | |
| needs: shared-resources | |
| runs-on: macos-latest | |
| if: ${{ needs.shared-resources.outputs.app_version != ''}} | |
| strategy: | |
| matrix: | |
| RID: [maccatalyst-arm64, maccatalyst-x64] | |
| # Consider matrix for test flight and sideload | |
| env: | |
| CODESIGN_KEY: "Apple Distribution: Lancelot Software (XXXXXXXXXX)" | |
| CODESIGN_PROV_PROFILE: "MauiDemo_maccatalyst_appstore" | |
| CODESIGN_PROFILE_TYPE: "MAC_APP_STORE" | |
| CODESIGN_ENTITLEMENTS: "Platforms/MacCatalyst/Entitlements.plist" | |
| APP_ID: "com.LancelotSoftware.MauiDemo" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: 16.1 | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{env.DOTNET_VERSION}} | |
| - name: Install MAUI workloads | |
| run: dotnet workload install maui --source https://api.nuget.org/v3/index.json | |
| - name: Restore NuGet packages | |
| run: dotnet restore ${{env.CSPROJ_PATH}} -r ${{matrix.RID}} --configfile ${{env.NUGETCONFIG_PATH}} | |
| # ------- Placeholder debug build ------- # | |
| - name: Build MAUI MacCatalyst project | |
| run: dotnet build ${{env.CSPROJ_PATH}} -c Debug -f ${{env.MACCATALYST_TFM}} -p:RuntimeIdentifier=${{matrix.RID}} -p:PublishTrimmed=true -p:MtouchLink=SdkOnly | |
| # ------- When you have an Apple account and certificates, you can replace the previous step, with these steps for a Release build. ------- # | |
| # # Docs https://github.com/Apple-Actions/import-codesign-certs | |
| # - name: Import Code-Signing Certificates | |
| # uses: Apple-Actions/import-codesign-certs@v3 | |
| # with: | |
| # p12-file-base64: "${{secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64}}" | |
| # p12-password: "${{secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD}}" | |
| # # Docs https://github.com/Apple-Actions/download-provisioning-profiles | |
| # - uses: Apple-Actions/download-provisioning-profiles@v3 | |
| # id: provisioning | |
| # with: | |
| # profile-type: ${{env.CODESIGN_PROFILE_TYPE}} | |
| # bundle-id: "${{env.APP_ID}}" | |
| # issuer-id: "${{secrets.APPSTORE_API_ISSUER_ID}}" | |
| # api-key-id: "${{secrets.APPSTORE_API_KEY_ID}}" | |
| # api-private-key: "${{secrets.APPSTORE_API_PRIVATE_KEY}}" | |
| # # Docs https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-app-store?view=net-maui-8.0 | |
| # # Carefully follow the intructions about entitlements.plist and info.plist | |
| # - name: Build MAUI MacCatalyst project | |
| # run: | | |
| # dotnet publish ${{env.CSPROJ_PATH}} -c Release -f ${{env.MACCATALYST_TFM}} -p:RuntimeIdentifier=${{env.RID}} -p:EnableCodeSigning=true -p:EnablePackageSigning=true -p:PublishTrimmed=true -p:MtouchLink=SdkOnly -p:ApplicationId="${{env.APP_ID}}" -p:CodesignProvision="${{env.CODESIGN_PROV_PROFILE}}" -p:CodesignKey=${{env.CODESIGN_KEY}} -p:CodesignEntitlements=${{env.CODESIGN_ENTITLEMENTS}} | |
| # # Docs https://github.com/Apple-Actions/upload-testflight-build | |
| # - name: 'Upload app to TestFlight' | |
| # uses: apple-actions/upload-testflight-build@v1 | |
| # with: | |
| # app-path: "${{github.workspace}}/**/*.pkg" | |
| # issuer-id: ${{secrets.APPSTORE_API_ISSUER_ID}} | |
| # api-key-id: "${{secrets.APPSTORE_API_KEY_ID}}" | |
| # api-private-key: "${{secrets.APPSTORE_API_PRIVATE_KEY}}" | |
| - name: Publish MacCatalyst build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: "MacCatalyst artifacts" | |
| path: "*.pkg" | |
| if-no-files-found: warn | |
| retention-days: 30 | |
| # ************************* # | |
| # >>>>>>> iOS Build <<<<<<< # | |
| # ************************* # | |
| # maui-ios: | |
| # name: Build iOS | |
| # needs: shared-resources | |
| # runs-on: macos-latest | |
| # if: ${{ needs.shared-resources.outputs.app_version != ''}} | |
| # env: | |
| # RID: ios-arm64 | |
| # CODESIGN_KEY: "Apple Distribution: Lancelot Software (XXXXXXXXXX)" | |
| # CODESIGN_PROV_PROFILE: "MauiDemo_ios_appstore" | |
| # CODESIGN_PROFILE_TYPE: "IOS_APP_STORE" | |
| # APP_ID: "com.LancelotSoftware.mauidemo" | |
| # steps: | |
| # - name: Checkout | |
| # uses: actions/checkout@v4 | |
| # with: | |
| # fetch-depth: 0 | |
| # - uses: maxim-lobanov/setup-xcode@v1 | |
| # with: | |
| # xcode-version: 16.1 | |
| # - name: Setup .NET Core SDK | |
| # uses: actions/setup-dotnet@v4 | |
| # with: | |
| # dotnet-version: ${{env.DOTNET_VERSION}} | |
| # - name: Install MAUI workloads | |
| # run: dotnet workload install maui --source https://api.nuget.org/v3/index.json | |
| # - name: Restore NuGet packages | |
| # run: dotnet restore ${{env.CSPROJ_PATH}} -r ${{env.RID}} --configfile ${{env.NUGETCONFIG_PATH}} | |
| # # Docs https://github.com/Apple-Actions/import-codesign-certs | |
| # - name: Import Code-Signing Certificates | |
| # uses: Apple-Actions/import-codesign-certs@v3 | |
| # with: | |
| # p12-file-base64: "${{secrets.APPLE_DISTRIBUTION_CERT_BASE64}}" | |
| # p12-password: "${{secrets.APPLE_DISTRIBUTION_CERT_PASSWORD}}" | |
| # # Docs https://github.com/Apple-Actions/download-provisioning-profiles | |
| # - uses: Apple-Actions/download-provisioning-profiles@v3 | |
| # id: provisioning | |
| # with: | |
| # profile-type: ${{env.CODESIGN_PROFILE_TYPE}} | |
| # bundle-id: "${{env.APP_ID}}" | |
| # issuer-id: "${{secrets.APPSTORE_API_ISSUER_ID}}" | |
| # api-key-id: "${{secrets.APPSTORE_API_KEY_ID}}" | |
| # api-private-key: "${{secrets.APPSTORE_API_PRIVATE_KEY}}" | |
| # # Docs https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/publish-cli?view=net-maui-8.0 | |
| # - name: Build MAUI iOS project | |
| # run: | | |
| # dotnet publish ${{env.CSPROJ_PATH}} -f ${{env.IOS_TFM}} -p:RuntimeIdentifier=${{env.RID}} -p:PublishTrimmed=true -p:MtouchLink=SdkOnly -p:ApplicationId=${{env.APP_ID}} -p:CodesignProvision="${{env.CODESIGN_PROV_PROFILE}}" -p:CodesignKey=${{env.CODESIGN_KEY}} | |
| # # Docs https://github.com/Apple-Actions/upload-testflight-build | |
| # - name: 'Upload app to TestFlight' | |
| # uses: apple-actions/upload-testflight-build@v1 | |
| # with: | |
| # app-path: "${{github.workspace}}/**/*.ipa" | |
| # issuer-id: ${{secrets.APPSTORE_API_ISSUER_ID}} | |
| # api-key-id: "${{secrets.APPSTORE_API_KEY_ID}}" | |
| # api-private-key: "${{secrets.APPSTORE_API_PRIVATE_KEY}}" | |
| # - name: Publish iOS build artifacts | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # name: "iOS artifacts" | |
| # path: "*.app" | |
| # if-no-files-found: warn | |
| # retention-days: 30 | |
| # ***************************** # | |
| # >>>>>>> Android build <<<<<<< # | |
| # ***************************** # | |
| # maui-android: | |
| # name: Build Android | |
| # needs: shared-resources | |
| # runs-on: windows-2022 | |
| # if: ${{ needs.shared-resources.outputs.app_version != ''}} | |
| # env: | |
| # RID: android-arm64 | |
| # steps: | |
| # - name: Checkout | |
| # uses: actions/checkout@v4 | |
| # with: | |
| # fetch-depth: 0 | |
| # - name: Setup .NET Core SDK | |
| # uses: actions/setup-dotnet@v4 | |
| # with: | |
| # dotnet-version: ${{env.DOTNET_VERSION}} | |
| # - uses: actions/setup-java@v4 | |
| # with: | |
| # distribution: 'microsoft' | |
| # java-version: '11' | |
| # - name: Install MAUI workloads | |
| # run: dotnet workload install maui --source https://api.nuget.org/v3/index.json | |
| # - name: Restore NuGet packages | |
| # run: dotnet restore ${{env.CSPROJ_PATH}} --configfile ${{env.NUGETCONFIG_PATH}} | |
| # # When you have a Google Play account and certificates, we can switch to this release setup | |
| # # Decode keystore base64 secret into a local file | |
| # - name: Decode the Keystore into File | |
| # run: | | |
| # $file_bytes = [System.Convert]::FromBase64String("${{secrets.ANDROID_SIGNING_KEYSTORE_BASE64}}") | |
| # [IO.File]::WriteAllBytes("${{github.workspace}}/${{secrets.ANDROID_SIGNING_KEYSTORE_FILENAME}}", $file_bytes) | |
| # # Docs https://learn.microsoft.com/en-us/dotnet/maui/android/deployment/publish-cli?view=net-maui-8.0 | |
| # - name: Build MAUI Android project | |
| # run: dotnet publish ${{env.CSPROJ_PATH}} -c ${{env.BUILD_CONFIGURATION}} -f ${{env.ANDROID_TFM}} -p:AndroidKeyStore=true -p:AndroidSigningKeyStore="${{github.workspace}}/${{secrets.ANDROID_SIGNING_KEYSTORE_FILENAME}}" -p:AndroidSigningStorePass="${{secrets.ANDROID_SIGNING_STORE_PASS}}" -p:AndroidSigningKeyAlias="${{secrets.ANDROID_SIGNING_KEY_ALIAS}}" -p:AndroidSigningKeyPass="${{secrets.ANDROID_SIGNING_KEY_PASS}}" | |
| # # Upload the artifact the Action's result | |
| # # To publish to the store, see https://github.com/marketplace/actions/upload-android-release-to-play-store | |
| # - name: Upload Android AAB artifacts (better than APKs) | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # name: "Android Artifacts" | |
| # path: "${{github.workspace}}/**/*Signed.aab" | |
| # if-no-files-found: warn | |
| # retention-days: 10 | |
| # ****************************** # | |
| # >>>>>>> GitHub Release <<<<<<< # | |
| # ****************************** # | |
| # create_release: | |
| # name: Create a new release | |
| # if: ${{success()}} | |
| # needs: [shared-resources, maui-macos, maui-windows-sideload, maui-windows-msstore] #, maui-ios, maui-android | |
| # runs-on: ubuntu-latest | |
| # defaults: | |
| # run: | |
| # shell: bash | |
| # steps: | |
| # - name: Download Artifacts | |
| # uses: actions/download-artifact@v4 | |
| # with: | |
| # pattern: MauiDemo* | |
| # - name: Confirm downloaded files | |
| # run: ls -R | |
| # - name: Install zip tools | |
| # run: | | |
| # sudo apt-get update | |
| # sudo apt-get install zip | |
| # - name: Archive each release asset | |
| # run: | | |
| # for file in *; do | |
| # if [ -f "$file" ]; then | |
| # echo "zipping up $file ..." | |
| # zip -r "$file.zip" "$file" | |
| # fi | |
| # done | |
| # - name: Delete original files | |
| # run: find . -type f -not -name '*.zip' -delete | |
| # - name: Confirm processed files | |
| # run: ls | |
| # - name: Create list of zip files | |
| # id: prepare-files-list | |
| # run: | | |
| # files=("*.zip") | |
| # echo "release_files=$files" >> $env:GITHUB_OUTPUT | |
| # - name: Release | |
| # uses: softprops/action-gh-release@v2 | |
| # with: | |
| # name: "${{needs.shared-resources.outputs.app_version}}" | |
| # tag_name: "${{needs.shared-resources.outputs.app_version}}" | |
| # fail_on_unmatched_files: true | |
| # files: ${steps.prepare-files-list.outputs.release_files} |