Maintain Separate Configs for Dev, Beta and Release Build Targets
This is part four of a four part series (š š š) and assumes youāve already set-up continuous integration with our sample project. If you havenāt already, I highly recommend reading part one, Continuous Integration for Cordova Apps, where we setup the build server used in this tutorial.
Change Your Appās Configuration Based on Branch
In parts I - III, we used Visual Studio Team Services (VSTS) to setup build definitions for unit testing, beta testing and over-the-air updates. All three of our build definitions run using continuous integration on a single branch (i.e. the master branch). Consequently, every time we push a code change, all three of these build definitions run.
- Android-Dev: runs Karma+Jasmine unit tests to ensure code quality
- Android-Beta: distributes the app to manual testers via HockeyApp
- Android-Release: distributes app updates to the public via Code Push
Frankly, this is bad. We donāt want to distribute a beta release every time thereās a feature check-in and we sure as hell donāt want to release in-development features to the public. To control what happens at check-in, we need a branching strategy. We need to run a different set of build steps depending on which branch receives the commit.
Two Big Advantages
By creating a unique branch for each release type, we gain two big advantages.
First, we can maintain a different set of config files for each branch ā enabling us to use different API keys or service providers for each release type. For example, imagine that you want to use the āStagingā Code Push deployment key during development, but the āProductionā deployment key when you release to the public. Using this technique, you can dynamically switch the keys during continuous integration.
Second, we can trigger different build steps for each branch. For example, we can run unit tests every time we push to the ādevā branch without actually releasing anything. When weāre ready for user feedback, we can release to beta testers via HockeyApp by pushing to the ābetaā branch.
To realize our dream, we must:
- Update the Source Code
- Create a branch for each build definition
- Create config files for each build definition
- Add gulp tasks to move and rename the config files before build
- Configure VSTS
- Change each build definition to trigger based on branch
- Source the build from the appropriate repository
- Add a custom gulp build step within each build definition
Update the Source Code
Letās start by creating three new branches at the terminal:
Right now, all three branches are a carbon copy of the master branch. Each branch can operate independently, but ideally the code should flow from dev to beta to release. Thus, we start by making all our changes in the dev branch.
Give each branch a custom config.xml
In a ānormalā local development environment, Cordova build depends on a config.xml file in the root directory to define things like icons, splash screens and the App ID. To support different configurations for each branch, Iāve created a special /config folder with XML and JS files for each release type (i.e. dev, beta and release). Letās compare a few lines from dev.xml and beta.xml to see whatās different:
Switch the Code Push Deployment Key
This code snippet from /config/dev.xml shows where we declare the Code Push deployment key.
We donāt want to use the same key in both development and production, so weāll use a different key in /config/release.xml
Give each branch a custom Gulp task
Our release-specific config files are defined in code, but we still need to move them to a place where Cordova can find them at build time during CI. To move the config files dynamically, weāll create a gulp task that VSTS can run immediately before Cordova build. Each gulp task will rename the config files and copy them to the appropriate directory. So, for example, gulp release
will:
- Rename release.xml to config.xml and move it to the project root
- Rename release.js to config.js and move it to /www/js/
The āØmagicāØ happens in gulpfile.js:
You can use the same technique to customize anything in response to a build definition. And as you might have guessed, the technique isnāt limited to XML and JS. You can do all sorts of things:
- Change your app icon and splash screen to display a ābetaā badge only in the beta release
- Use a different API key for services like maps, analytics, data sync, etc. in production
- Show features only in development builds
That wasnāt too bad, now was it? Take a break, catch your breath and regroup by playing a song in your headphones. I recommend āStreet Lights for a Ribcageā by Sleepy Eyes of Death.
Configure VSTS
Our code is setup to dynamically rename and move config.xml using a Gulp task. Now, we need to automate the process using continuous integration in VSTS. For each build definition, weāll add a Gulp build step to move and rename the config files. Then, weāll change the trigger branch and source repository to match the branch.
Using the same instance of VSTS that you configured in Parts I, II and III of this series, login and navigate to the āBUILDā tab where you will edit the āAndroid-Devā build definition.
Add a space-delimited array of Gulp tasks for dev sass test
. In order, these will:
dev
rename and moves /config/dev.xml to /config.xmlsass
compile SASS to CSStest
execute our Karma+Jasmine tests
Under the āTriggersā tab, change continuous integration to trigger when code changes in the dev branch.
Under the āPrepositoryā tab, change the default branch to use dev branch as the source repository.
āAndroid-Betaā and āAndroid-Releaseā will follow a similar pattern. You can see a full list of the values below.
Build Definition | Gulp Tasks | Source Repository | Trigger Filter |
---|---|---|---|
Android-Dev | dev sass test | Dev | Dev |
Android-Beta | beta sass | Beta | Beta |
Android-Release | release sass | Release | Release |
Checking Our Work
Youāve done all the hard work, now pluck the fruit of your labors. š In Terminal:
When you return to the VSTS portal, youāll find the CI builds waiting in the queue. Double-click on any of the builds to see the build output in real-time. Celebrate with a song in your headphones. I recommend āThe Commander Thinks Aloudā by The Long Winters.