End-to-end CI/CD pipeline Setup with Azure DevOps for Mobile App: Common Pipeline—Part 5
Please follow these steps to set up a common pipeline for both iOS and Android, along with the sonar cloud quality gate.
Prerequisite
You must have already gone through PART 1, PART 2, PART 3, and PART 4 of this series. Along with Sonar Cloud with GitHub.
Create a common Pipeline:
Since we already know how to create a pipeline and release it in Part 4, Here we will just look at a new common YAML file.
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
trigger:
- master
pool:
vmImage: macOS-11
jobs:
- job: TestViaJob # name of the job (A-Z, a-z, 0–9, and underscore)
timeoutInMinutes: 300
steps:
- checkout: self
persistCredentials: true
clean: true
- task: NodeTool@0
displayName: ‘Install Node’
inputs:
versionSpec: ‘v16.6.2’ # you can use your desired version here
- script: yarn install
displayName: Install Dependencies
- task: SonarSource.sonarcloud.14d9cde6-c1da-4d55-aa01–2965cd301255.SonarCloudPrepare@1
displayName: ‘Prepare analysis on SonarCloud’
inputs:
SonarCloud: SonarClodPOCServiceCon
organization: ‘*************’
scannerMode: CLI
configMode: manual
cliProjectKey: ‘*************’
cliProjectName: PM.SonarCloudPOC
extraProperties: |
sonar.exclusions=**/android/**/*.* , **/ios/**/*.* , **/node_modules/**/*.* , **/__tests__/*.tsx , **/coverage/**/*.js,**/setupTests.ts,**/babel.config.js, **/metro.config.js,
sonar.coverage.exclusions = **/android/**/*.* , **/ios/**/*.* , **/node_modules/**/*.*
sonar.javascript.file.suffixes= .jsx , .js
sonar.typescript.file.suffixes= .tsx , .ts
sonar.java.binaries=-
sonar.c.file.suffixes=-
sonar.cpp.file.suffixes=-
sonar.objc.file.suffixes=-
sonar.html.file.suffixes=-
sonar.css.file.suffixes=-
sonar.java.file.suffixes=-
sonar.sources=.
sonar.language=js , jsx, ts , tsx
sonar.tests=./__tests__
sonar.javascript.lcov.reportPaths=./coverage/lcov.info
sonar.testExecutionReportPaths=./test-report.xml
sonar.sourceEncoding=UTF-8
enabled: true
- task: SonarSource.sonarcloud.ce096e50–6155–4de8–8800–4221aaeed4a1.SonarCloudAnalyze@1
displayName: ‘Run Code Analysis’
enabled: true
- task: SonarSource.sonarcloud.38b27399-a642–40af-bb7d-9971f69712e8.SonarCloudPublish@1
displayName: ‘Publish Quality Gate Result’
enabled: true
- task: SimondeLang.sonarcloud-buildbreaker.sonar-buildbreaker.sonarcloud-buildbreaker@2
displayName: ‘Break build on quality gate failure’
inputs:
SonarCloud: SonarClodPOCServiceCon
organization: ‘*************’
enabled: true
- task: Gradle@2
displayName: ‘gradlew build’
inputs:
gradleWrapperFile: android/gradlew
workingDirectory: android
publishJUnitResults: false
- task: AndroidSigning@3
displayName: ‘Signing and aligning APK file(s) **/*.apk’
inputs:
apksignerKeystoreFile: ‘*************’
apksignerKeystorePassword: sonar123
apksignerKeystoreAlias: sonar0
apksignerKeyPassword: sonar123
zipalign: false
- task: CopyFiles@2
displayName: ‘Copy Files to: $(build.artifactstagingdirectory)’
inputs:
SourceFolder: ‘$(system.defaultworkingdirectory)’
Contents: ‘**/*.apk’
TargetFolder: ‘$(build.artifactstagingdirectory)’
condition: succeededOrFailed()
- task: PublishBuildArtifacts@1
displayName: ‘Publish Artifact: drop’
inputs:
PathtoPublish: ‘$(build.artifactstagingdirectory)’
condition: succeededOrFailed()
- task: CocoaPods@0
displayName: ‘Install CocoaPods’
inputs:
workingDirectory: ‘ios’
- task: InstallAppleCertificate@2
displayName: ‘Install an Apple certificate’
inputs:
certSecureFile: ‘iosAzureDevOPSCICD_distribution.p12’
certPwd: ‘$(P12password)’
- task: InstallAppleProvisioningProfile@1
displayName: ‘Install an Apple provisioning profile’
inputs:
provProfileSecureFile: AzueDevOpsCICDTest.mobileprovision
- task: Xcode@5
displayName: ‘Xcode build’
inputs:
actions: ‘build’
configuration: ‘$(Configuration)’
xcWorkspacePath: ‘ios/QualityGateTest.xcworkspace’
scheme: ‘QualityGateTest’
packageApp: true
signingOption: ‘manual’
signingIdentity: ‘$(APPLE_CERTIFICATE_SIGNING_IDENTITY)’
provisioningProfileUuid: ‘$(APPLE_PROV_PROFILE_UUID)’
destinationPlatformOption: ‘iOS’
destinationSimulators: ‘iPhone 12’
- task: CopyFiles@2
displayName: ‘Copy Files to: $(build.artifactstagingdirectory)’
inputs:
SourceFolder: ‘$(system.defaultworkingdirectory)’
Contents: ‘**/*.ipa’
TargetFolder: ‘$(build.artifactstagingdirectory)’
condition: succeededOrFailed()
- task: PublishBuildArtifacts@1
displayName: ‘Publish Artifact: drop’
inputs:
PathtoPublish: ‘$(build.artifactStagingDirectory)’
condition: succeededOrFailed()
There are a few new lines added for the common YAML file highlighted in bold; let’s see them one by one.
1) Jobs: Jobs are added at the top level of the YAML file to increase a pipeline timeout from the default of 60 minutes.
2) Node tool: The new Mac machine provided by the Azure pipeline did not have a default node. So we are installing it from the pipeline, it will install the node module regardless of whether it is present or not.
3) Yarn install: Installing a node module in a VM via pipeline
4) Install Cocoa pods: Installing pods in a VM via pipeline
Note:
a) The node installation is a very important step. If the node is not installed on the VM, it will not create an Artifact and will give some error like the one mentioned below for iOS and Android.
b) Jobs were added to the pipeline to tackle the timeout issue, but we need to be careful about indentation while changing the pipeline.
Enjoy !!!!!.
This is a standard way to create a CICD for a multi-environment mobile app in native, React Native, or Flutter.
However, I have worked at the advanced level of CICD and using in our application, as mentioned below
- Creating a dynamic single pipeline for all the environments (SIT, UAT, and PROD) without creating three different pipelines.
- Using WebHook to automatically send the Release Notes to the Microsoft Teams channel.
- Using Azure's Microsoft Graph API to upload ADHoc IPA and APK for testers to use for testing in the browser stack or other platform.
- Upload the IPA and APK automatically to the browser stack and run the test.
- Generate the test result.
Connect with me on my email ID, SandeepRajbhar1985@gmail.com for more detail on the above topic and to discuss how advanced we can go and what else we can do to make CICD better along with Automation.