diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 34fe9f23..046e60e8 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -80,6 +80,16 @@ stages: iosVariableGroup: 'ApplicationTemplate.Distribution.Internal.iOS' BannerVersionNameText: "STAGING" +- stage: Firebase_App_Distribution + condition: and(succeeded(), eq(variables['IsLightBuild'], 'false')) + dependsOn: Build_Staging + jobs: + - template: build/stage-release-firebase.yml + parameters: + applicationEnvironment: Staging + serviceConnectionKeyFileName: $(FirebaseAppDistributionServiceConnection) + pathToAab: '$(Pipeline.Workspace)/$(artifactName)/*Signed.aab' + - stage: AppCenter_TestFlight_Staging condition: and(succeeded(), eq(variables['IsLightBuild'], 'false')) dependsOn: Build_Staging 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..a14ad3a8 100644 --- a/build/stage-release-appcenter.yml +++ b/build/stage-release-appcenter.yml @@ -1,4 +1,4 @@ -parameters: +parameters: applicationEnvironment: '' # e.g. "Staging", "Production" deploymentEnvironment: '' # e.g. "GooglePlay", "AppStore", "AppCenter" appCenterWindowsSlug: '' @@ -10,54 +10,54 @@ parameters: appCenterDistributionGroup: '' jobs: -- deployment: AppCenter_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) +# - deployment: AppCenter_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) - - download: current - displayName: "Download Release Notes" - artifact: $(releaseNotesArtifactName) +# - download: current +# displayName: "Download Release Notes" +# artifact: $(releaseNotesArtifactName) - - 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 +# - 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 - - 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: '**' - deployment: AppCenter_iOS pool: diff --git a/build/stage-release-firebase.yml b/build/stage-release-firebase.yml new file mode 100644 index 00000000..f5b51d75 --- /dev/null +++ b/build/stage-release-firebase.yml @@ -0,0 +1,32 @@ +parameters: + serviceConnectionKeyFileName: "" + pathToAab: "" + applicationEnvironment: "" # e.g. "Staging", "Production" +jobs: + variables: + - name: artifactName + value: $(AndroidArtifactName)_${{ parameters.applicationEnvironment }} + + job: ReleaseFirebase + displayName: Release to Firebase app distribution + steps: + # Step 1: Install Firebase tools + - script: "npm install -g firebase-tools" + displayName: "Install Firebase Tools" + + # Step 2: Download the service connection key file + - task: DownloadSecureFile@1 + inputs: + secureFile: ${{ parameters.serviceConnectionKeyFileName }} + name: DistributionServiceConnection + displayName: "Download Firebase Service connection" + + # Step 3: Deploy to Firebase App Distribution + - script: | + firebase appdistribution:distribute ${{ parameters.pathToAab }} \ + --app $(ApplicationIdentifier) + # --release-notes-file {add release notes file here} \ + # --groups {add group name here} + env: + GOOGLE_APPLICATION_CREDENTIALS: $(DistributionServiceConnection.secureFilePath) + displayName: "Deploy to Firebase" 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