sukh
sukh

Reputation: 358

Xcode build dynamically set version based off JSON config file

N.B. This is a React Native project.

With Android and Gradle, I'm able to parse a JSON file and read the values to dynamically apply the version to the app during build time.

The JSON file looks something like this:

{
  "name": "AwesomeApp",
  "displayName": "Awesome",
  "version": {
    "major": 3,
    "minor": 2,
    "patch": 1
  }
}

At its simplest form, the Gradle file has this:

def jsonFile = file('../../app.json')
def parsedJson = new groovy.json.JsonSlurper().parseText(jsonFile.text)
def versionMajor = parsedJson.version.major
def versionMinor = parsedJson.version.minor
def versionPatch = parsedJson.version.patch
def appVersionCode = versionMajor * 10000 + versionMinor * 100 + versionPatch
def appVersionName = "${versionMajor}.${versionMinor}.${versionPatch}"

And then within the build this is where I can set it to use the dynamically set version:

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.1'

    defaultConfig {
        applicationId "com.awesome.app"
        ...
        versionCode appVersionCode
        versionName appVersionName
        ...
    }
}

How can I achieve the same with iOS and Xcode? I understand we need to modify the CFBundleShortVersionString and Build Phases seem to be the best way to do dynamically setting of a version however these seem all incremental / part of a CI tool of some kinda rather than reading an explicitly set JSON file.

Any help would be appreciated.

(N.B. If I have missed anything obvious which would cause a down vote let me know and I can modify the question accordingly - mass click negative doesn't really help the poster whose asking a valid question -> sorry this was based off a previous question I asked before).

Upvotes: 2

Views: 1652

Answers (1)

sukh
sukh

Reputation: 358

Ended up doing this via Node script which I called within the Run Script in Xcode Build Phases:

Build Phases Script:

AppVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}")
APP_VERSION="$AppVersion" node ${PROJECT_DIR}/../iOSVersioning.js

iOSVersioning.js:

const { exec } = require('child_process');
const APP_VERSION = process.env.APP_VERSION;
const version = require('../app.json').version;
const versionName = `${version.major}.${version.minor}.${version.patch}`;

if (APP_VERSION == versionName) {
    process.exit();
}

exec(
  `/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${versionName}" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"`,
  (err, stdout, stderr) => {
    if (err) {
      console.log('Failed to apply the app version.');
      process.exit(1);
    }

    console.log(`Applied app verion: ${versionName}`);
  }
);

Upvotes: 4

Related Questions