Following the topic of Continuous Integration (CI) that I started here, in this post we are going to see how we can build our app, and run unit tests remotely with a pipeline in Azure.
If you want to go straight to the Continuous Deployment (CD) part, check this other post.
In Azure, pipelines are built using .yml files, where part of the setup is configured and the steps of the pipeline are defined.
In Azure, and in most of the CI/CD services you can find, we need to indicate what is going to trigger the pipeline, where do we want to execute it in terms of operating system and what are going to be the steps for the pipeline to follow.
We are going to see each section individually and then finish with a complete example.
With triggers, there is a lot of customization that you can achieve.
You can for example run builds on a schedule like so, thanks to Cron. In this example, the pipeline is going to be triggered at 10 PM every day with the contents of
schedules: - cron: '0 22 * * *' displayName: 'Nightly build' branches: include: - develop
For most of us, what you would probably want is to run the pipeline when you merge a pull request to the
developbranch or when you want to release a new version to production after a merge to main/master.
For that, we just need the following line at the top of our file. In this case, we want to run the pipeline every time a change is made in the
trigger: - develop
The pool is what is going to tell Azure where do you want to execute your pipeline. For Android, we could use the Linux based machines, but if you are building an iOS app, then you would have to choose a macOS option.
pool: vmImage: 'ubuntu-latest'
For Android, here is where we run the Gradle tasks or the bash scripts that our pipeline is going to execute sequentially.
The first thing to do is checkout the Git repository. As the pipeline is inside the repo, we can just do it like so. You can read more about the options of this command here.
steps: - checkout: self persistCredentials: true clean: true
After that, we can start running Gradle tasks. In the following example, I’m building all the variants of the Android app and then running unit tests on each of them.
- task: Gradle@2 displayName: 'Build app and run unit tests' inputs: gradleWrapperFile: 'gradlew' options: '--stacktrace' tasks: 'clean assemble testPreDebug testProRelease' publishJUnitResults: true javaHomeOption: 'JDKVersion' sonarQubeRunAnalysis: false sqGradlePluginVersionChoice: 'build'
Each step is going to be shown when the pipeline is executed, the
displayName variable is going to define the name of the step to be shown.
Afterward, in the
inputs variable is where we execute Gradle like we would do locally. You can do it using normal bash script but instead of using the task
Gradle@2, you would use the
CmdLine@2 task, and then in the inputs field, you could run a script like so.
# For a bash script - task: CmdLine@2 displayName: 'Run a script' inputs: script: | # Some bash commands separated by a line jump # For single line bash commands - task: Bash@3 displayName: 'Run bash command' inputs: targetType: 'inline' script: | # A bash command
To keep your keys or other data secret and use it when you run a pipeline, you can store them in variables. This can be done in the Azure web when you are editing a pipeline, it’s pretty straightforward.
Then to use them, you just need to use this syntax
Complete sample pipeline
The following sample runs on changes in the
develop branch on a Linux machine and executes these steps.
- Checkout the repo
- Set the username to whom the commit will belong
- Checkout branch and fetch any changes
- Set the Java JDK to use
- Write the
local.propertiesfile with pipeline variables.
- Assemble the app and run unit tests
# Android # Build your Android project with Gradle. # Add steps that test, sign, and distribute the APK, save build artifacts, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/android trigger: - develop pool: vmImage: 'ubuntu-latest' steps: - checkout: self persistCredentials: true clean: true - script: | git config --global user.name "MyUsername" git config --global user.email "firstname.lastname@example.org" git config --global push.followTags true - task: CmdLine@2 displayName: 'Checkout branch' inputs: script: | export branchName=$(echo $(Build.SourceBranch) | cut -c12-) git fetch git checkout $branchName git reset --hard origin/$branchName - task: Bash@3 displayName: 'Use JDK11 by default' inputs: targetType: 'inline' script: | echo "##vso[task.setvariable variable=JAVA_HOME]$JAVA_HOME_11_X64" - task: Bash@3 displayName: 'Config local.properties' inputs: targetType: 'inline' script: | echo KEY=$(KEY) > ./local.properties - task: Gradle@2 displayName: 'Build app and run unit tests' inputs: gradleWrapperFile: 'gradlew' options: '--stacktrace' tasks: 'clean assemble testPreDebug testProRelease' publishJUnitResults: true javaHomeOption: 'JDKVersion' sonarQubeRunAnalysis: false sqGradlePluginVersionChoice: 'build'
After digging into the code, there’s some preparation that needs to be done before running the pipeline, which is giving permissions to the users to access the repository where our Android project is hosted.
For this pipeline, we need permissions to read the repository, so that we read the Git branch that we want to test.
In order to give this permission to the user that is going to be running the pipeline, we need to go to our pipeline, and in then in the three dots there is a Manage Security option, where we must change the read permission to allow.
To see which user is going to be running the pipeline, you can go to your pipeline settings, where you are going to see a Variables tab. There is a variable called
system.collectionId, which you can then use to search for the user in the Manage Security section that we talked about before, so that you know who to give the permissions to.
Featured image by An Tran on Unsplash
If you want to read more content like this without ads and support me, don’t forget to check my profile, or give Medium a chance by becoming a member to access unlimited stories from me and other writers. It’s only $5 a month and if you use this link I get a small commission.