# Processes all apps Lastenrad Bayern, sharee.bike and Mein konrad
# i,e,
# - builds apps
# - publishes apps to MS App Center

parameters:
- name: codeBase
  displayName: Codebase
  type: string
  default: git://sharee.bike Buchungsplattform/Code@main
  values:
  - git://sharee.bike Buchungsplattform/Code@main
  - git://sharee.bike Buchungsplattform/Code@develop

trigger:
- main
- develop

variables:
  # General purpose variables.
  buildConfiguration: 'Release'
  outputDirectory: '$(build.binariesDirectory)/$(buildConfiguration)'
  solutionName : 'TINK.sln'

  # TeilRad GbmH related variables.
  ownerNameTeilRad : 'TeilRad'
  keyStoreFile : 'TeilRad.keystore'
  ownerTeilRadFullName : '$(ownerNameTeilRad)-GmbH'

  # HauffWare related variables.
  ownerNameHauffWare : 'HauffWare'
  keyStoreFileHauffWare : 'hauffware.keystore'
  ownerHauffWareFullName : '$(ownerNameHauffWare)'

  # Lastenrad Bayern related variales.
  appNameLastenradBayern : 'LastenradBayern'

  appProjectDroidLastenradBayern : '$(appNameLastenradBayern).Android.csproj'
  appArtefactNameDroidLastenradBayern : 'com.$(ownerNameTeilRad).$(appNameLastenradBayern)-Signed.aab'
  msAppCenterAppSlugLastenradBayernDroid : '$(appNameLastenradBayern)-1'
  msAppCenterDistributionGroupIdLastenradBayernDroid : '088eb829-9030-424f-917f-3117dfff8a4b' 

  solutionNameIosLastenradBayern : 'LastenradBayern.sln'
  appArtefactNameIosLastenradBayern : '$(appNameLastenradBayern).iOS.ipa'
  msAppCenterAppSlugLastenradBayernIos : '$(appNameLastenradBayern)'
  msAppCenterDistributionGroupIdLastenradBayernIos : 'b4d4cd32-1a79-40fa-a170-797e9a62a813'

  # Sharee.bike related variables.
  appNameShareeBike : 'sharee.bike'
  appNameShareeBikeLegacy : 'TINK'

  appProjectDroidShareeBike : '$(appNameShareeBikeLegacy).Android.csproj'
  appArtefactNameDroidShareeBike : 'com.$(ownerNameHauffWare).sharee-Signed.aab'
  msAppCenterAppSlugShareeBikeDroid : '$(appNameShareeBike)-1'
  msAppCenterDistributionGroupIdShareeBikeDroid : '1f9f7deb-cd88-460a-bd64-29488121bb5f'

  solutionNameIosShareeBike : 'ShareeBike.sln'
  appArtefactNameIosShareeBike : '$(appNameShareeBikeLegacy).iOS.ipa'
  msAppCenterAppSlugShareeBikeIos : '$(appNameShareeBike)'
  msAppCenterDistributionGroupIdShareeBikeIos : 'd47dbf12-d7ec-4ef4-85f2-2bd6c249a2d9'

  # Mein konrad related variables.
  appNameMeinKonrad : 'Meinkonrad'

  appProjectDroidMeinKonrad : '$(appNameMeinKonrad).Android.csproj'
  appArtefactNameDroidMeinKonrad : 'com.$(ownerNameTeilRad).$(appNameMeinKonrad)-Signed.aab'
  msAppCenterAppSlugMeinKonrad : 'Mein-konrad-1'
  msAppCenterDistributionGroupIdMeinKonradDroid : 'e048d2f8-5b54-4a65-8c57-dd2df05269eb'

  solutionNameIosMeinKonrad : 'MeinKonrad.sln'
  appArtefactNameIosMeinKonrad : '$(appNameMeinKonrad).iOS.ipa'
  msAppCenterAppSlugMeinKonradIos : 'Mein-konrad'
  msAppCenterDistributionGroupIdMeinKonradIos : ' 40cf103b-2d13-477a-a75a-424045dfd00d'

stages:
  - stage: RunUnitTestsStage
    displayName: "Run unittests"

    # Test require widows
    pool:
      vmImage: 'windows-latest'

    jobs:
      - job: RunUnittests
        displayName: "Run Unit Tests"

        steps:
        # Get code from internal repo.
        # https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#specify-multiple-repositories
        - checkout: ${{ parameters.codeBase}}

        - task: DotNetCoreCLI@2
          displayName: "Build TestLockItShared Unit Tests" 
          inputs:
            command: 'build'
            projects: '**/TestLockItShared.csproj'
            configuration: '$(buildConfiguration)'

        - task: DotNetCoreCLI@2
          displayName: "Build TestLockItBLE Unit Tests" 
          inputs:
            command: 'build'
            projects: '**/TestLockItBLE.csproj'
            configuration: '$(buildConfiguration)'

        - task: DotNetCoreCLI@2
          displayName: "Build TestShareeLib Unit Tests" 
          inputs:
            command: 'build'
            projects: '**/TestShareeLib.csproj'
            configuration: '$(buildConfiguration)'

        - task: DotNetCoreCLI@2
          displayName: "Build TestShareeSharedGuiLib Unit Tests" 
          inputs:
            command: 'build'
            projects: '**/TestShareeSharedGuiLib.csproj'
            configuration: '$(buildConfiguration)'

        - task: DotNetCoreCLI@2
          displayName: "Build TestSharee Unit Tests" 
          inputs:
            command: 'build'
            projects: '**/TestSharee.csproj'
            configuration: '$(buildConfiguration)'

      # Infos about test filters see
      # https://docs.microsoft.com/en-us/previous-versions/jj155796(v=vs.140)?redirectedfrom=MSDN
        - task: VSTest@2
          displayName: "Run tests TestLockItShared"
          inputs:
            failOnMinTestsNotRun: true
            minimumExpectedTests: 6
            testSelector: 'testAssemblies'
            testAssemblyVer2: |
              **\TestLockItShared.dll
              !**\obj\**
            searchFolder: '$(System.DefaultWorkingDirectory)'
            testFiltercriteria: 'TestCategory!=Explicit&TestCategory!=RequiresCOPRI&TestCategory!=RequiresCOPRI.Live&TestCategory!=RequiresCOPRI.Devel'

        - task: VSTest@2
          displayName: "Run tests TestLockItBLE"
          inputs:
            failOnMinTestsNotRun: true
            minimumExpectedTests: 19
            testSelector: 'testAssemblies'
            testAssemblyVer2: |
              **\TestLockItBLE.dll
              !**\obj\**
            searchFolder: '$(System.DefaultWorkingDirectory)'
            testFiltercriteria: 'TestCategory!=Explicit&TestCategory!=RequiresCOPRI&TestCategory!=RequiresCOPRI.Live&TestCategory!=RequiresCOPRI.Devel'

        # Infos about test filters see
        # https://docs.microsoft.com/en-us/previous-versions/jj155796(v=vs.140)?redirectedfrom=MSDN
        - task: VSTest@2
          inputs:
            testSelector: 'testAssemblies'
            testAssemblyVer2: |
              **\TestShareeLib.dll
              !**\obj\**
            searchFolder: '$(System.DefaultWorkingDirectory)'
            testFiltercriteria: 'TestCategory!=Explicit&TestCategory!=RequiresCOPRI&TestCategory!=RequiresCOPRI.Live&TestCategory!=RequiresCOPRI.Devel'

        - task: VSTest@2
          displayName: "Run tests TestShareeSharedGuiLib"
          inputs:
            failOnMinTestsNotRun: true
            minimumExpectedTests: 11
            testSelector: 'testAssemblies'
            testAssemblyVer2: |
              **\TestShareeSharedGuiLib.dll
              !**\obj\**
            searchFolder: '$(System.DefaultWorkingDirectory)'
            testFiltercriteria: 'TestCategory!=Explicit&TestCategory!=RequiresCOPRI&TestCategory!=RequiresCOPRI.Live&TestCategory!=RequiresCOPRI.Devel'

        - task: VSTest@2
          displayName: "Run tests Sharee"
          inputs:
            failOnMinTestsNotRun: false # there are not yet tests in project.
            minimumExpectedTests: 1
            testSelector: 'testAssemblies'
            testAssemblyVer2: |
              **\TestSharee.dll
              !**\obj\**
            searchFolder: '$(System.DefaultWorkingDirectory)'
            testFiltercriteria: 'TestCategory!=Explicit&TestCategory!=RequiresCOPRI&TestCategory!=RequiresCOPRI.Live&TestCategory!=RequiresCOPRI.Devel'

  - stage: BuildAppsDroidStage
    displayName: "Build the Droid apps."
    dependsOn: RunUnitTestsStage 
    
    # Droid versions can be build either on MacOS or Windows
    pool:
      vmImage: 'windows-latest'

    jobs:
    - job: BuildAppDroid
      displayName: "Build droid version of apps."

      steps:
      # Get code from internal repo.
      # https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#specify-multiple-repositories
      - checkout: ${{ parameters.codeBase}}
      
      - task: NuGetToolInstaller@1
      
      - task: NuGetCommand@2
        inputs:
          restoreSolution: '$(solutionName)'

      # Set merchant-id.
      - task: PowerShell@2
        displayName: "Set secret merchant-id for Lastenrad Bayern."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameLastenradBayern)' -merchantId $(merchantIdLastenradBayern)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      - task: PowerShell@2
        displayName: "Set secret merchant-id for sharee.bike."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameShareeBikeLegacy)' -merchantId $(merchantIdShareeBike)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      - task: PowerShell@2
        displayName: "Set secret merchant-id for Mein konrad."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameMeinKonrad)' -merchantId $(merchantIdMeinkonrad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Set google maps api key
      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys for Lastenrad Bayern."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          # Parameter droidApiKey value should be GMapsDroidApiKey2TeilRad not GMapsDroidApiKeyTeilRad but the restricted version of key leads to a grayed google maps
          arguments: "-appName '$(appNameLastenradBayern)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys for sharee.bike."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          # Parameter droidApiKey value should be GMapsDroidApiKey2TeilRad not GMapsDroidApiKeyTeilRad but the restricted version of key leads to a grayed google maps
          arguments: "-appName '$(appNameShareeBikeLegacy)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys for Mein konrad."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          # Parameter droidApiKey value should be GMapsDroidApiKey2TeilRad not GMapsDroidApiKeyTeilRad but the restricted version of key leads to a grayed google maps
          arguments: "-appName '$(appNameMeinKonrad)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Download keystore file for singning.
      - task: DownloadSecureFile@1
        displayName: "Download TeilRad GmbH secret keystore file."
        name: TeilRadKeystoreFile
        inputs:
          secureFile: '$(keyStoreFile)'

      - task: DownloadSecureFile@1
        displayName: "Download HauffWare secret keystore file."
        name: HauffWareKeystoreFile
        inputs:
          secureFile: '$(keyStoreFileHauffWare)'

      # Build the apps
      - task: XamarinAndroid@1
        displayName: "Build Lastenrad Bayern."
        inputs:
          projectFile: '**/$(appProjectDroidLastenradBayern)'
          outputDirectory: '$(outputDirectory)'
          configuration: '$(buildConfiguration)'
          # Password keystorePasswordTeilRad and alias keystoreNameTeilRad can be found in KeePassXC database PasswörterApp.kdbx, entry with title "Android Keystore TeilRad GmbH (App-Signing)"
          msbuildArguments: '-restore -t:SignAndroidPackage -p:AndroidPackageFormat=aab -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(TeilRadKeystoreFile.secureFilePath) -p:AndroidSigningStorePass=$(keystorePasswordTeilRad) -p:AndroidSigningKeyAlias=$(keystoreNameTeilRad) -p:AndroidSigningKeyPass=$(keystorePasswordTeilRad)'

      - task: XamarinAndroid@1
        displayName: "Build sharee.bike."
        inputs:
          projectFile: '**/$(appProjectDroidShareeBike)'
          outputDirectory: '$(outputDirectory)'
          configuration: '$(buildConfiguration)'
          # Password keystorePasswordHauffWare and alias keystoreNameHauffWare can be found in KeePassXC database PasswörterApp.kdbx, entry with title "Android Keystore HauffWare (App-Signing)"
          msbuildArguments: '-restore -t:SignAndroidPackage -p:AndroidPackageFormat=aab -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(HauffWareKeystoreFile.secureFilePath) -p:AndroidSigningStorePass=$(keystorePasswordHauffWare) -p:AndroidSigningKeyAlias=$(keystoreNameHauffWare) -p:AndroidSigningKeyPass=$(keystorePasswordHauffWare)'

      - task: XamarinAndroid@1
        displayName: "Build Mein konrad."
        inputs:
          projectFile: '**/$(appProjectDroidMeinKonrad)'
          outputDirectory: '$(outputDirectory)'
          configuration: '$(buildConfiguration)'
          # Password keystorePasswordTeilRad and alias keystoreNameTeilRad can be found in KeePassXC database PasswörterApp.kdbx, entry with title "Android Keystore TeilRad GmbH (App-Signing)"
          msbuildArguments: '-restore -t:SignAndroidPackage -p:AndroidPackageFormat=aab -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(TeilRadKeystoreFile.secureFilePath) -p:AndroidSigningStorePass=$(keystorePasswordTeilRad) -p:AndroidSigningKeyAlias=$(keystoreNameTeilRad) -p:AndroidSigningKeyPass=$(keystorePasswordTeilRad)'

      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish Lastenrad Bayern aab as artifact to azure library."
        inputs:
          targetPath: '$(outputDirectory)/$(appArtefactNameDroidLastenradBayern)'
          artifactName: LastenradBayernAndroidAab
          
      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish sharee.bike aab as artifact to azure library."
        inputs:
          targetPath: '$(outputDirectory)/$(appArtefactNameDroidShareeBike)'
          artifactName: ShareeBikeAndroidAab

      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish Mein konrad aab as artifact to azure library."
        inputs:
          targetPath: '$(outputDirectory)/$(appArtefactNameDroidMeinKonrad)'
          artifactName: MeinKonradAndroidAab

  - stage: BuildLastenradBayernIosStage
    displayName: "Build Lastenrad Bayern iOS."
    dependsOn: RunUnitTestsStage 

    # Build iOS version requires MacOS
    pool:
      vmImage: 'macos-12'

    jobs:

    - job: BuildLastenradBayernIos
      displayName: "Build Lastenrad Bayern iOs"

      steps:
      # To manually select a Xamarin SDK version on the Microsoft-hosted macOS agent,
      # configure this task with the *Mono* version that is associated with the
      # Xamarin SDK version that you need, and set the "enabled" property to true.
      # See https://go.microsoft.com/fwlink/?linkid=871629
      - script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_12_0
        displayName: 'Select the Xamarin SDK version'
        enabled: false

      # Get code from Open Source repo.
      # https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#specify-multiple-repositories
      - checkout: ${{ parameters.codeBase}}

      - task: NuGetToolInstaller@1

      - task: NuGetCommand@2
        inputs:
          restoreSolution: '**/$(solutionNameIosLastenradBayern)'

      # Install signing certificate to keychain
      # Certificate resides in "Code Signing Certificate for Distribution TeilRad GmbH (LXJD6URCHR)"
      - task: InstallAppleCertificate@2
        inputs:
          certSecureFile: 'AppleDistributionCertificate_TeilRadGmbH_LXJD6URCHR_20221008.p12'
          certPwd: '$(AppleDistributionCertificate_TeilRadGmbh_Password)'
          keychain: 'temp'

      # Install provisioning profile
      - task: InstallAppleProvisioningProfile@1
        inputs:
          provisioningProfileLocation: 'secureFiles'
          provProfileSecureFile: 'ProvisioningProfileLastenradBayernAppStore3.mobileprovision'

      # Set merchant-id.
      - task: PowerShell@2
        displayName: "Set secret merchant-id."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameLastenradBayern)' -merchantId $(merchantIdLastenradBayern)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Set google maps api key
      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          arguments: "-appName '$(appNameLastenradBayern)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Build the app
      - task: XamariniOS@2
        inputs:
          solutionFile: '**/$(solutionNameIosLastenradBayern)'
          configuration: '$(buildConfiguration)'
          packageApp: true
          buildForSimulator: false
          runNugetRestore: false
          signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'
          signingProvisioningProfileID: '$(APPLE_PROV_PROFILE_UUID)'

      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish ipa as artifact."
        inputs:
          targetPath: '$(appNameLastenradBayern)/TINK.iOS/bin/iPhone/$(buildConfiguration)/$(appArtefactNameIosLastenradBayern)'
          artifactName: LastenradBayernIpa

  - stage: BuildShareeBikeIosStage
    displayName: "Build sharee.bike iOS app"
    dependsOn: RunUnitTestsStage 

    # Build iOS version requires MacOS
    pool:
      vmImage: 'macos-12'

    jobs:

    - job: BuildShareeBikeIos
      displayName: "Build sharee.bike iOs"

      steps:
      # To manually select a Xamarin SDK version on the Microsoft-hosted macOS agent,
      # configure this task with the *Mono* version that is associated with the
      # Xamarin SDK version that you need, and set the "enabled" property to true.
      # See https://go.microsoft.com/fwlink/?linkid=871629
      - script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_12_0
        displayName: 'Select the Xamarin SDK version'
        enabled: false

      # Get code from Open Source repo.
      # https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#specify-multiple-repositories
      - checkout: ${{ parameters.codeBase}}

      - task: NuGetToolInstaller@1

      - task: NuGetCommand@2
        inputs:
          restoreSolution: '**/$(solutionNameIosShareeBike)'

      # Install signing certificate to keychain
      # Certificate resides in "App-Mittagessen", entry "Code Signing Certificate for Distribution TeilRad GmbH (LXJD6URCHR)"
      - task: InstallAppleCertificate@2
        inputs:
          certSecureFile: 'AppleDistributionCertificate_TeilRadGmbH_LXJD6URCHR_20221008.p12'
          certPwd: '$(AppleDistributionCertificate_TeilRadGmbh_Password)'
          keychain: 'temp'

      # Install provisioning profile
      - task: InstallAppleProvisioningProfile@1
        inputs:
          provisioningProfileLocation: 'secureFiles'
          provProfileSecureFile: 'ProvisioningProfileTeilRadShareeBikeAppStore3.mobileprovision'

      # Set merchant-id.
      - task: PowerShell@2
        displayName: "Set secret merchant-id."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameShareeBikeLegacy)' -merchantId $(merchantIdShareeBike)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Set google maps api key
      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          arguments: "-appName '$(appNameShareeBikeLegacy)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Build the app
      - task: XamariniOS@2
        inputs:
          solutionFile: '**/$(solutionNameIosShareeBike)'
          configuration: '$(buildConfiguration)'
          packageApp: true
          buildForSimulator: false
          runNugetRestore: false
          signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'
          signingProvisioningProfileID: '$(APPLE_PROV_PROFILE_UUID)'

      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish sharee.bike ipa as artifact."
        inputs:
          targetPath: '$(appNameShareeBikeLegacy)/TINK.iOS/bin/iPhone/$(buildConfiguration)/$(appArtefactNameIosShareeBike)'
          artifactName: ShareeBikeIpa

  - stage: BuildMeinKonradIosStage
    displayName: "Build Mein konrad iOS app"
    dependsOn: RunUnitTestsStage 

    # Build iOS version requires MacOS
    pool:
      vmImage: 'macos-12'

    jobs:

    - job: appNameMeinKonradBuildMeinKonradIos
      displayName: "Build Mein konrad iOs"

      steps:
      # To manually select a Xamarin SDK version on the Microsoft-hosted macOS agent,
      # configure this task with the *Mono* version that is associated with the
      # Xamarin SDK version that you need, and set the "enabled" property to true.
      # See https://go.microsoft.com/fwlink/?linkid=871629
      - script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_12_0
        displayName: 'Select the Xamarin SDK version'
        enabled: false

      # Get code from Open Source repo.
      # https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#specify-multiple-repositories
      - checkout: ${{ parameters.codeBase}}

      - task: NuGetToolInstaller@1

      - task: NuGetCommand@2
        inputs:
          restoreSolution: '**/$(solutionNameIosMeinKonrad)'

      # Install signing certificate to keychain
      # Certificate resides in "App-Mittagessen", entry "Code Signing Certificate for iPhone Distribution Stadtwerke Konstanz GmbH (2SZR625MSV)"
      - task: InstallAppleCertificate@2
        inputs:
          certSecureFile: 'Code Signing Certificate for iPhone Distribution Stadtwerke Konstanz GmbH 2SZR625MSV.p12'
          certPwd: '$(AppleDevelopmentCertificatePassword)'
          keychain: 'temp'

      # Install provisioning profile
      - task: InstallAppleProvisioningProfile@1
        inputs:
          provisioningProfileLocation: 'secureFiles'
          provProfileSecureFile: 'Meinkonrad_to_App_Store_3.mobileprovision'

      # Set merchant-id.
      - task: PowerShell@2
        displayName: "Set secret merchant-id."
        inputs:
          targetType: filePath
          filePath: 'Set-MerchantId.ps1'
          # Merchant id is defined by COPRI
          arguments: "-appName '$(appNameMeinKonrad)' -merchantId $(merchantIdMeinKonrad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Set google maps api key
      - task: PowerShell@2
        displayName: "Set secret Google Maps api-keys."
        inputs:
          targetType: filePath
          filePath: 'Set-GMapsApiKey.ps1'
          arguments: "-appName '$(appNameMeinKonrad)' -droidApiKey $(GMapsDroidApiKeyTeilRad) -iOsApiKey $(GMapsIosApiKey2TeilRad)"
          pwsh: true
          workingDirectory: '$(build.SourcesDirectory)'

      # Build the app
      - task: XamariniOS@2
        inputs:
          solutionFile: '**/$(solutionNameIosMeinKonrad)'
          configuration: '$(buildConfiguration)'
          packageApp: true
          buildForSimulator: false
          runNugetRestore: false
          signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'
          signingProvisioningProfileID: '$(APPLE_PROV_PROFILE_UUID)'

      # Publish siged apk as pipeline artifact
      - task: PublishPipelineArtifact@1
        displayName: "Publish Mein Konrad ipa as artifact to azure library."
        inputs:
          # Path '$(outputDirectory)/$(appArtefactNameIosMeinKonrad)' is not valid
          targetPath: '$(appNameMeinKonrad)/TINK.iOS/bin/iPhone/$(buildConfiguration)/$(appArtefactNameIosMeinKonrad)'
          artifactName: MeinKonradIpa

  - stage: BetaVersion
    # Distribute only of all app could be build successfully.
    dependsOn: 
      - BuildAppsDroidStage 
      - BuildLastenradBayernIosStage
      - BuildShareeBikeIosStage
      - BuildMeinKonradIosStage
    displayName: "Publish all apps to MS App Center"

    # Distribution to MS App center can be on MacOS or Windows.
    pool:
      vmImage: 'windows-latest'

    jobs:
    - job: AndroidBeta
      displayName: "Publish all apps to MS App Center"
      steps:

        # Download apk from pipeline artifacs
        - task: DownloadPipelineArtifact@2
          displayName: "Download Lastenrad Bayern Droid artifact form azure library."
          inputs: 
            artifact: LastenradBayernAndroidAab

        - task: DownloadPipelineArtifact@2
          displayName: "Download Lastenrad Bayern iOS artifact form azure library."
          inputs: 
            artifact: LastenradBayernIpa

        - task: DownloadPipelineArtifact@2
          displayName: "Download sharee.bike Droid artifact form azure library."
          inputs: 
            artifact: ShareeBikeAndroidAab

        - task: DownloadPipelineArtifact@2
          displayName: "Download sharee.bike iOS artifact form azure library."
          inputs: 
            artifact: ShareeBikeIpa

        - task: DownloadPipelineArtifact@2
          displayName: "Download Mein konrad Droid artifact form azure library."
          inputs: 
            artifact: MeinKonradAndroidAab

        - task: DownloadPipelineArtifact@2
          displayName: "Download Mein konrad iOS artifact form azure library."
          inputs: 
            artifact: MeinKonradIpa

        # Checkout release notes: They are required for publishing to app center.
        - checkout: ${{ parameters.codeBase}}

        # Publish singed apk to app center.
        - task: AppCenterDistribute@3
          displayName: "Publish Lastenrad Bayern Droid to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerTeilRadFullName)/$(msAppCenterAppSlugLastenradBayernDroid)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameDroidLastenradBayern)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdLastenradBayernDroid)'

        - task: AppCenterDistribute@3
          displayName: "Publish Lastenrad Bayern iOS to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerTeilRadFullName)/$(msAppCenterAppSlugLastenradBayernIos)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameIosLastenradBayern)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdLastenradBayernIos)'

        - task: PublishPipelineArtifact@1
          inputs:
            targetPath: '$(appNameLastenradBayern)/TINK.iOS/Entitlements.plist'
            artifactName: EntitlementsLastenradBayern

        - task: AppCenterDistribute@3
          displayName: "Publish sharee.bike Droid to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerHauffWareFullName)/$(msAppCenterAppSlugShareeBikeDroid)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameDroidShareeBike)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdShareeBikeDroid)'

        - task: AppCenterDistribute@3
          displayName: "Publish sharee.bike iOS to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerTeilRadFullName)/$(msAppCenterAppSlugShareeBikeIos)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameIosShareeBike)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdShareeBikeIos)'
        - task: PublishPipelineArtifact@1
          inputs:
            targetPath: '$(appNameShareeBikeLegacy)/TINK.iOS/Entitlements.plist'
            artifactName: EntitlementsShareeBike

        - task: AppCenterDistribute@3
          displayName: "Publish Mein konrad Droid to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerTeilRadFullName)/$(msAppCenterAppSlugMeinKonrad)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameDroidMeinKonrad)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdMeinKonradDroid)'

        - task: AppCenterDistribute@3
          displayName: "Publish Mein konrad iOS to MS App Center."
          inputs:
            serverEndpoint: 'App Center'
            appSlug: '$(ownerTeilRadFullName)/$(msAppCenterAppSlugMeinKonradIos)'
            appFile: '$(Pipeline.Workspace)/$(appArtefactNameIosMeinKonrad)'
            releaseNotesOption: 'file'
            releaseNotesFile: 'ReleaseNotes.txt'
            destinationType: 'groups'
            distributionGroupId: '$(msAppCenterDistributionGroupIdMeinKonradIos)'
        - task: PublishPipelineArtifact@1
          inputs:
            targetPath: '$(appNameMeinKonrad)/TINK.iOS/Entitlements.plist'
            artifactName: EntitlementsMeinKonrad