Azure & Branch Management

Ford Otosan
Ford Otosan
Published in
3 min readMar 1, 2023
source

After a period of mess, we decided to improve our branch management. We identified the team’s needs, researched best practices, and got to work.

We have two main branches called ‘master’ and ‘development’:

  • master’ holds the latest version that we’ve released to the market.
  • development’ holds the most up-to-date version with all new features and bug fixes that have been tested.

In addition, we have 3 branch folders named ‘feature’, ‘bugfix’, and ‘rc’.

  • Under the ‘feature’ folder, we create a new branch for each new feature ‘task’ in the sprint. When we push the changes, Azure Pipeline sends a new release to the ‘feature application’ we created on AppCenter, and we test the new feature in this application. If there are no issues, we move the changes to ‘development’.
  • Under the ‘bugfix’ folder, we create a new branch for each new ‘bug’ in the sprint. When we push the changes, Azure Pipeline sends a new release to the ‘bugfix application’ we created on AppCenter, and we test the fix in this application. If the issue is resolved, we move the changes to ‘development’.
  • After developing new features and fixing bugs, now we need to release a new version for our users. At this stage, we create a new release candidate from the ‘development’ branch. When we push the branch, Azure Pipeline sends a new release to the ‘rc application’ we created on AppCenter. We test the latest version in the live environment. If the tests are successful, we send the changes to ‘master’.
trigger:
branches:
include:
- feature/*

steps:
# - build
# - publish artifact

# Disribution Tasks
- task: AppCenterDistribute@3
displayName: 'Android AppCenter distribution'
inputs:
appSlug: 'Your_Company/YourApp-FEATURE'
appFile: '$(Build.ArtifactStagingDirectory)/app/build/outputs/apk/debug/debug.apk'
distributionGroupId: 'xx-xx-xx' #testers
condition: succeededOrFailed()

We have created different ‘yaml’ files for each branch.

trigger:
branches:
include:
- rc/*

steps:
# - build
# - publish artifact

# Disribution Tasks
- task: AppCenterDistribute@3
displayName: 'Android AppCenter distribution'
inputs:
appSlug: 'Your_Company/YourApp-RC'
appFile: '$(Build.ArtifactStagingDirectory)/app/build/outputs/apk/debug/debug.apk'
distributionGroupId: 'xx-xx-xx' #testers
condition: succeededOrFailed()

Everything looked fine, but we had one problem. Whenever we switched branches or merged code, we had to check and update the ‘yaml’ file every time to make sure that the changes were going to the correct application on AppCenter.

Then we added ‘yaml’ files for the ‘build’ and ‘deploy’ jobs.

##azure_deploy_feature.yml

steps:
- script: echo deploy feature I am deploying to $(Environment)! #defined on branch variables yaml
displayName: 'Run Deployment'
- download: current
artifact: apk
patterns: '**/*.apk'
- task: AppCenterDistribute@3
displayName: 'Android AppCenter distribution'
inputs:
appSlug: 'Your_Company/YourApp-FEATURE' #change for each branch
appFile: '$(Pipeline.Workspace)/apk/app/build/outputs/apk/debug/debug.apk'
distributionGroupId: 'xxx-xxx-xxx' #testers
condition: succeededOrFailed()

Here is our main ‘yaml’ file after the changes.

##azure-pipelines.yml

trigger:
branches:
include:
- master
- development
- feature/*
- bugfix/*
- rc/*

stages:
- stage: Master
displayName: Deploy master stage
condition: eq(variables['Build.SourceBranch'],
'refs/heads/master')
jobs:
- job: BuildMasterJob
steps:
- template: azure-jobs/build_release.yml
- job: DeploymentJobMaster
variables:
- template: azure-variables/azure_variables_master.yml
steps:
- template: azure-jobs/azure_deploy_master.yml

- stage: Development
displayName: Deploy development stage
condition: eq(variables['Build.SourceBranch'],
'refs/heads/development')
jobs:
- job: BuildDevJob
steps:
- template: azure-jobs/build_debug.yml
- job: DeploymentJobDevelopment
variables:
- template: azure-variables/azure_variables_dev.yml
steps:
- template: azure-jobs/azure_deploy_dev.yml

- stage: Feature
displayName: Deploy feature stage
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/')
jobs:
- job: BuildFeatureJob
steps:
- template: azure-jobs/build_debug.yml
- job: DeploymentJobFeature
variables:
- template: azure-variables/azure_variables_feature.yml
steps:
- template: azure-jobs/azure_deploy_feature.yml

- stage: Bugfix
displayName: Deploy bugfix stage
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/bugfix/')
jobs:
- job: BuildBugfixJob
steps:
- template: azure-jobs/build_debug.yml
- job: DeploymentJobBugfix
variables:
- template: azure-variables/azure_variables_bugfix.yml
steps:
- template: azure-jobs/azure_deploy_bugfix.yml

- stage: RC
displayName: Deploy rc stage
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/rc/')
jobs:
- job: BuildRCJob
steps:
- template: azure-jobs/build_release.yml
- job: DeploymentJobRC
variables:
- template: azure-variables/azure_variables_rc.yml
steps:
- template: azure-jobs/azure_deploy_rc.yml

Now everything is OK 👍🥳
Here is an example from Azure Pipeline:

https://upload.wikimedia.org/wikipedia/commons/c/c1/RU_Roundabout_6_Cars.gif

Ford Otosan — Connected Products & Engineering Tribe
Mobile Chapter Lead
Kaan DOĞRUER

--

--