Robust Development with git-flow, Bitbucket Pipelines and Bitrise
Tags: engineering, technology
Published: 2019-11-22 10:35:38

---
title: Robust Development with git-flow, Bitbucket Pipelines and Bitrise
published: true
date: 2019-11-20 15:43:47 UTC
tags: Engineering,Technology
canonical_url: https://bugfender.com/blog/robust-development-with-git-flow-bitbucket-pipelines-and-bitrise/
---

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/Feature-image.jpg)

When you start a new project, everything is very easy and agile. You can develop, commit code and publish new versions quickly, without much testing. You probably don’t have a QA team, your test data is similar to your production data and you don’t develop multiple features at the same time.

But as the project grows, it starts to become more and more complex. There’s usually a team of people working on multiple features, your apps need to be properly tested before publication and the production data is probably a lot more expansive than the local instance you use to test your development.

When you reach this point, it’s important to have a robust development process that allows you to deliver new versions without big bugs. And it’s here where git-flow, with its continuous integration systems, comes into play.

The article assumes you have some basic knowledge on how git and git-flow works. If you need more info, you can read this tutorial: [https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow).

## Why Do I Need a Continuous Integration System for My Apps?

If you’re a mobile developer, you might not be using a continuous integration system, but your backend team is probably using one. So if most backend teams use a CI system, why shouldn’t you?

The benefits of a CI system for backend teams also apply to mobile developers. You can automate your app builds to make it easier and faster to get the version ready to test for your team.

In this article we are going to explore Bitrise CI, an easy-to-use CI system whose main focus is mobile apps.

## Starting with Bitrise

In this article we don’t want to go deep on all the features Bitrise has to offer or demonstrate an in-depth tutorial on how to set up everything in Bitrise. They already have very useful documentation on how it works.

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/1.jpg)

From our experience, the product is very easy to use. The first steps are quick and straightforward. You can easily sign up using your Bitbucket or GitHub account and the platform will have access to all your repositories. Once you have them, you can easily integrate Bitrise with your app.

Once you have set up everything and you’ve  been able to build your first app within Bitrise, you can move forward and start planning for a proper workflow that allows you to build a robust development system.

### Environments

To properly test your app, especially if the app communicates with a backend (which doesn’t nowadays?) you should have different environments because you will probably want to test the app against a production database but you also might need a specific branch of the backend. We are going to show you some examples from one of our Bugfender customers:

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image2.png)

As you can see in the image, the company has four different environments and you will probably also need at least the same number. Let’s see each of the environments in detail.

#### **Production**

Nothing to mention here. This is the production server.

#### **Test**

This is a test server. Any commit done in the **develop** branch is automatically deployed and the database is cleaned and filled with fixtures data. So once deployed, this server is in a known state we can use to test the app features.

#### **UAT**

We call this server a user acceptance test (or UAT). This server will also automatically deploy any commit done in **develop** branch, but the database will be a copy of the production database but with sanitized data (we randomize any confidential information).

The main goal of this server is to be able to test the apps with a database similar to the production database. Apps might perform ok with your small test database but they might run into problems when using the big production version.

#### **Dev**

This is a development server. The backend code will be manually deployed via Bitbucket Pipelines. From pipelines any branch on the repo can be deployed. The database will be cleaned and fixtures data will be loaded on each deploy.

The reason for this server is that, if we are using git-flow properly, we can deploy any **feature** branch so we can test the apps against a specific branch before it gets merged into develop.

One of the most important aspects of Bitrise is the option to have multiple workflows that build different things.

### Preparing your app

Before jumping to Bitrise CI, first you need to get your apps ready to work properly with your various environments. In your iOS or Android app you need to create a  build variant for each deployment environment.

In Android Studio, you can create multiple variants of your app modifying your `build.gradle` and adding them to the **productFlavors** entry. Here you can see how it looks for our example app:

```
     productFlavors {
        local {
            buildConfigField "String", "API_HOST", "\"http://app.es.myworkup.local\""

            applicationIdSuffix ".local"
            resValue "string", "global_title_app_name", "mwup-loc"
        }

        ngrok {
            buildConfigField "String", "API_HOST", "\"https://myworkup.ngrok.io\""

            applicationIdSuffix ".ngrok"
            resValue "string", "global_title_app_name", "mwup-ngrok"
        }

        dev {
            buildConfigField "String", "API_HOST", "\"https://app.dev.myworkup.net\""

            applicationIdSuffix ".dev"
            resValue "string", "global_title_app_name", "mwup-dev"
        }

        uat {
            buildConfigField "String", "API_HOST", "\"https://app.uat.myworkup.net\""

            applicationIdSuffix ".uat"
            resValue "string", "global_title_app_name", "mwup-uat"
        }

        qa_test {
            buildConfigField "String", "API_HOST", "\"https://app.test.myworkup.net\""

            applicationIdSuffix ".uat"
            resValue "string", "global_title_app_name", "mwup-test"
        }

        store {
            buildConfigField "String", "API_HOST", "\"https://app.myworkup.net\""

            resValue "string", "global_title_app_name", "myworkup"
        }
    }
```

Here you have a screenshot of how it looks in Android Studio, with all the variants:

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image6.png)

On iOS you need to create multiple configurations for your project. For each configuration you will need to define your server.

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image10.png)

**Important** : a very important thing to remember is that you need to change your **bundle ID** and your app name, so you can have all the app variants installed at the same time. Otherwise you will only be able to have one app installed.

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image7.png)

### Creating Bitrise workflows

Now that we have multiple app variants, we need to build them using Bitrise. The good thing about Bitrise is that it allows you to create different workflows for each app. In our case we have three:

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image9.png)

- **release ->** Builds the app using the production variant and is signed with the proper certificates to publish the app to the stores.
- **dev ->** Builds multiple apps, one for each variant we have defined.
- **ngrok ->** A special build that creates an app that uses [ngrok](https://ngrok.com/), so we can test a local api within the app.

#### Triggers

In our case we have automated builds, so every time a commit is pushed to the repo, the app gets built automatically based on the following trigger rules:

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image5.png)

As you can see, there are no automatic builds for **feature** branches, but you can always start a manual build for a specific branch. So when we need to build an app to test some specific features we do it manually.

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image3.png)

With this setup, the whole team always have access to the latest app versions and they can test them on multiple scenarios.

As a final step, we have integrated Bitrise with Slack, so quickly the whole team can install the new apps once they are built:

![](https://d2b8vdvorf6w8g.cloudfront.net/wp-content/uploads/2019/11/image4.png)

### Store release

In our case, we have decided not to publish the apps automatically to the store from Bitrise, but you can even automate that. We prefer to test the release app before sending it to the stores and then upload it manually. It takes only a few minutes and we like to be more in control of this process than automate it.

## Bugfender and test apps

If you build all this robust flow, the best thing you can do is integrate Bugfender into your apps in order to get information when people start testing the apps and they find bugs. 

If you have a QA team, they will probably be reporting bugs to you and if you have Bugfender you will be able to see all the app logs of the QA team. 

If you want to integrate Bugfender, we recommend you to **create an app for each variant** , so you can easily locate the logs of each bug.

## Conclusion

For big apps it’s important to have a proper flow that allows the whole team to easily test new features from the app or the backend. Using what we have explained in the article you can build a robust deployment system that should fit the needs of any team, no matter how big, and encourage the testing of new features as soon as possible.