diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 34fe9f23..ddf48055 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -87,14 +87,9 @@ stages: - template: build/stage-release-appcenter.yml parameters: applicationEnvironment: Staging - deploymentEnvironment: AppCenter - appCenterWindowsSlug: $(AppCenterWindowsSlug) - appCenteriOSSlug: $(AppCenteriOSSlug) - appCenterAndroidSlug: $(AppCenterAndroidSlug) - androidKeyStoreFile: $(InternalKeystore) androidVariableGroup: 'ApplicationTemplate.Distribution.Internal.Android' - appCenterServiceConnectionName: $(AppCenterServiceConnection) - appCenterDistributionGroup: $(AppCenterDistributionGroup) + serviceConnectionKeyFileName: $(FirebaseAppDistributionServiceConnection) + pathToAab: '$(Pipeline.Workspace)/$(artifactName)/*Signed.aab' - template: build/stage-release-appstore.yml parameters: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f9ea040..2df0e643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Prefix your items with `(Template)` if the change is about the template and not ## 3.6.X - Added conventional commit validation stage `stage-commit-validation.yml` +- Replacing Appcenter with Firebase app distribution for android. ## 3.5.X - Bump Uno packages to 5.2.121 to fix a crash on iOS. diff --git a/build/stage-release-appcenter.yml b/build/stage-release-appcenter.yml index 69496323..89999998 100644 --- a/build/stage-release-appcenter.yml +++ b/build/stage-release-appcenter.yml @@ -1,110 +1,87 @@ -parameters: +parameters: applicationEnvironment: '' # e.g. "Staging", "Production" - deploymentEnvironment: '' # e.g. "GooglePlay", "AppStore", "AppCenter" - appCenterWindowsSlug: '' - appCenteriOSSlug: '' - appCenterAndroidSlug: '' - androidKeyStoreFile: '' androidVariableGroup: '' - appCenterServiceConnectionName: '' - appCenterDistributionGroup: '' + serviceConnectionKeyFileName: "" + pathToAab: "" jobs: -- deployment: AppCenter_Android +- deployment: Firebase_Android pool: vmImage: $(windowsHostedAgentImage) variables: - - name: artifactName - value: $(AndroidArtifactName)_${{ parameters.applicationEnvironment }} - - name: releaseNotesArtifactName - value: ReleaseNotes_${{ parameters.applicationEnvironment }} - group: ${{ parameters.androidVariableGroup }} - environment: ${{ parameters.deploymentEnvironment }} strategy: runOnce: deploy: - steps: - - download: current - displayName: "Download Artifact" - artifact: $(artifactName) + steps: + # Step 1: Install Firebase tools + - script: "npm install -g firebase-tools" + displayName: "Install Firebase Tools" - - download: current - displayName: "Download Release Notes" - artifact: $(releaseNotesArtifactName) + # Step 2: Download the service connection key file + - task: DownloadSecureFile@1 + inputs: + secureFile: ${{ parameters.serviceConnectionKeyFileName }} + name: DistributionServiceConnection + displayName: "Download Firebase Service Connection" - - task: AppCenterDistribute@3 - displayName: Deploy Android to AppCenter - inputs: - serverEndpoint: ${{ parameters.appCenterServiceConnectionName }} - distributionGroupId: ${{ parameters.appCenterDistributionGroup }} - appSlug: ${{ parameters.appCenterAndroidSlug }} - appFile: '$(Pipeline.Workspace)/$(artifactName)/*Signed.aab' - releaseNotesOption: file - releaseNotesFile: "$(Pipeline.Workspace)/$(releaseNotesArtifactName)/ReleaseNotes-Excerpt.md" - isSilent: true + # Step 3: Deploy to Firebase App Distribution + - script: | + echo "Deploying to Firebase App Distribution..." + echo "App ID: $(ApplicationIdentifier)" + echo "Path to AAB: ${{ parameters.pathToAab }}" + firebase appdistribution:distribute ${{ parameters.pathToAab }} \ + --app $(ApplicationIdentifier) + env: + GOOGLE_APPLICATION_CREDENTIALS: $(DistributionServiceConnection.secureFilePath) + displayName: "Deploy to Firebase" - - task: DeleteFiles@1 - displayName: "Remove Downloaded Artifacts (Build)" - condition: always() - inputs: - SourceFolder: $(Pipeline.Workspace)/$(artifactName) - RemoveSourceFolder: true - Contents: '**' - - - task: DeleteFiles@1 - displayName: "Remove Downloaded Artifacts (Release Notes)" - condition: always() - inputs: - SourceFolder: $(Pipeline.Workspace)/$(releaseNotesArtifactName) - RemoveSourceFolder: true - Contents: '**' +# - deployment: AppCenter_iOS +# pool: +# vmImage: $(macOSHostedAgentImage) +# variables: +# - name: artifactName +# value: $(iOSArtifactName)_${{ parameters.applicationEnvironment }} +# - name: releaseNotesArtifactName +# value: ReleaseNotes_${{ parameters.applicationEnvironment }} +# environment: ${{ parameters.deploymentEnvironment }} +# strategy: +# runOnce: +# deploy: +# steps: +# - download: current +# displayName: "Download Artifact" +# artifact: $(artifactName) -- deployment: AppCenter_iOS - pool: - vmImage: $(macOSHostedAgentImage) - variables: - - name: artifactName - value: $(iOSArtifactName)_${{ parameters.applicationEnvironment }} - - name: releaseNotesArtifactName - value: ReleaseNotes_${{ parameters.applicationEnvironment }} - environment: ${{ parameters.deploymentEnvironment }} - strategy: - runOnce: - deploy: - steps: - - download: current - displayName: "Download Artifact" - artifact: $(artifactName) - - - download: current - displayName: "Download Release Notes" - artifact: $(releaseNotesArtifactName) +# - download: current +# displayName: "Download Release Notes" +# artifact: $(releaseNotesArtifactName) - - task: AppCenterDistribute@3 - displayName: Deploy iOS to AppCenter - inputs: - serverEndpoint: ${{ parameters.appCenterServiceConnectionName }} - appSlug: ${{ parameters.appCenteriOSSlug }} - appFile: $(Pipeline.Workspace)/$(artifactName)/*.ipa - symbolsDsymFiles: $(Pipeline.Workspace)/$(artifactName)/*.dSYM - symbolsIncludeParentDirectory: true - distributionGroupId: ${{ parameters.appCenterDistributionGroup }} - releaseNotesOption: file - releaseNotesFile: "$(Pipeline.Workspace)/$(releaseNotesArtifactName)/ReleaseNotes-Excerpt.md" - isSilent: true +# - task: AppCenterDistribute@3 +# displayName: Deploy iOS to AppCenter +# inputs: +# serverEndpoint: ${{ parameters.appCenterServiceConnectionName }} +# appSlug: ${{ parameters.appCenteriOSSlug }} +# appFile: $(Pipeline.Workspace)/$(artifactName)/*.ipa +# symbolsDsymFiles: $(Pipeline.Workspace)/$(artifactName)/*.dSYM +# symbolsIncludeParentDirectory: true +# distributionGroupId: ${{ parameters.appCenterDistributionGroup }} +# releaseNotesOption: file +# releaseNotesFile: "$(Pipeline.Workspace)/$(releaseNotesArtifactName)/ReleaseNotes-Excerpt.md" +# isSilent: true - - task: DeleteFiles@1 - displayName: "Remove Downloaded Artifacts (Build)" - condition: always() - inputs: - SourceFolder: $(Pipeline.Workspace)/$(artifactName) - RemoveSourceFolder: true - Contents: '**' +# - task: DeleteFiles@1 +# displayName: "Remove Downloaded Artifacts (Build)" +# condition: always() +# inputs: +# SourceFolder: $(Pipeline.Workspace)/$(artifactName) +# RemoveSourceFolder: true +# Contents: '**' - - task: DeleteFiles@1 - displayName: "Remove Downloaded Artifacts (Release Notes)" - condition: always() - inputs: - SourceFolder: $(Pipeline.Workspace)/$(releaseNotesArtifactName) - RemoveSourceFolder: true - Contents: '**' +# - task: DeleteFiles@1 +# displayName: "Remove Downloaded Artifacts (Release Notes)" +# condition: always() +# inputs: +# SourceFolder: $(Pipeline.Workspace)/$(releaseNotesArtifactName) +# RemoveSourceFolder: true +# Contents: '**' diff --git a/build/stage-release-firebase.yml b/build/stage-release-firebase.yml new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/build/stage-release-firebase.yml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/build/variables.yml b/build/variables.yml index b71d01b4..03b82f32 100644 --- a/build/variables.yml +++ b/build/variables.yml @@ -42,6 +42,7 @@ AppCenterServiceConnection: AppCenter-nventive-framework AppStoreServiceConnection: AppStore-nventive AppCenterCanaryServiceConnection: AppCenter-nventive-framework + FirebaseAppDistributionServiceConnection: com.nventive.applicationtemplate.firebaseappdistribution.json # AppCenter slugs # The "app slug" corresponds to the identifiers of the app in AppCenter; to find it, navigate to the app in a browser and; diff --git a/doc/AzurePipelines.md b/doc/AzurePipelines.md index 356efde3..825048ac 100644 --- a/doc/AzurePipelines.md +++ b/doc/AzurePipelines.md @@ -1,4 +1,4 @@ -# Azure Pipelines +# Azure Pipelines ## Pipeline Code This project uses CI/CD pipelines that are implemented as yaml code. @@ -18,7 +18,7 @@ These pipelines rely on a few variable groups and secrets in order to fully work At high level, the CI/CD pipelines do the following: - **Build** the app in **staging**. - - **Deploy** the staging app (to AppCenter and/or TestFlight and GooglePlay). + - **Deploy** the staging app (to Firebase app distribution and/or TestFlight and GooglePlay). - **Build** the app in **production**. - **Deploy** the production app (to TestFlight and GooglePlay). @@ -69,7 +69,10 @@ This is where the exact build steps are defined. These vary depending on the pla The release stages are even more straigtforward than the build ones. One thing to note is that, for the same reason as it is done at the end of the build steps, a clean-up step is included in every stage. ### AppCenter Release Stage ([stage-release-appcenter.yml](../build/stage-release-appcenter.yml)) -This stage is in charge of pushing the application to AppCenter. It's divided into 2 jobs, one for each platform. +This stage is in charge of pushing the application to AppCenter. Only for iOS + +### Firebase app distribution Release Stage ([stage-release-firebase.yml](../build/stage-release-firebase.yml)) +This stage is in charge of pushing the application to Firebase app distribution. Only for android. ### Apple AppStore Release Stage ([stage-release-appstore.yml](../build/stage-release-appstore.yml)) This stage is in charge of pushing the iOS version to the Apple AppStore. Given that the build stage signs the application, this is as simple as using the proper task and pushing the **IPA** file. This should only be run for configurations that properly sign the application. @@ -102,4 +105,4 @@ This pipelines creates a branch on which it commits a version of the latest code ### Canary Deployment This pipelines triggers automatically when a new branch is created and pushed by the previous pipeline. It takes the new code, builds it, and deploys so that it can be manually tested. -This pipeline uses the same build and release stages as the main CI/CD pipeline of the app. \ No newline at end of file +This pipeline uses the same build and release stages as the main CI/CD pipeline of the app. diff --git a/src/ApplicationTemplate.sln b/src/ApplicationTemplate.sln index fcc4a9db..7ca61398 100644 --- a/src/ApplicationTemplate.sln +++ b/src/ApplicationTemplate.sln @@ -66,6 +66,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6E8378CB ..\build\stage-build.yml = ..\build\stage-build.yml ..\build\stage-release-appcenter.yml = ..\build\stage-release-appcenter.yml ..\build\stage-release-appstore.yml = ..\build\stage-release-appstore.yml + ..\build\stage-release-firebase..yml = ..\build\stage-release-firebase..yml ..\build\stage-release-googleplay.yml = ..\build\stage-release-googleplay.yml ..\build\steps-build-android.yml = ..\build\steps-build-android.yml ..\build\steps-build-ios.yml = ..\build\steps-build-ios.yml