A JBoss Project
Red Hat

Aerogear Guides Tutorials to help get you off and running.

Digger developer guide

Overview

The AeroGear Digger project leverages Jenkinsfiles to build applications. A Jenkinsfile will need to exist in a repo for it to be built succesfully.

This guide covers the basic anatomy of a Jenkinsfile, plugins that can be used to help with building and signing applications and migrating an existing application to using a Jenkinsfile.

This guide contains some information specific to using Digger with RHMAP. This information can be ignored when using Digger as a standalone service.

Further information (if required) on using Jenkinsfiles is available in the Jenkins pipeline documentation

Anatomy of a Jenkinsfile

A typical Jenkinsfile will contain a number of sections. These sections define the steps required to build an Application specific to it’s type.

Aerogear Digger provides sample Jenkinsfiles for building the following 3 types of Applications

  • Native Android

  • Native iOS

  • Cordova (for Android and iOS)

Further details are provided below on the structure and functions of the provided Jenkinsfiles. To try out these files in a deployed digger installation skip to the Building Applications section

General Jenkinsfile structure

# Define/Assign variables e.g (1)
def platform = "android"

node(platform) { (2)
  stage('Checkout') { (3)
    checkout scm (4)
  }

  stage('Prepare'){ (5)
    ...
  }

  stage('Build') { (6)
    ...
  }

  stage('Sign') { (7)
    ...
  }

  stage('Archive') { (8)
    ...
  }
}
1 Assign variables to use during the build steps. The example shown above is the platform variable. The only argument for the platform variable is a string that should match a label given to a Jenkins node. In Digger this value should be ios or android. any other value will result in the build not being assigned to a node and timing out.
2 The node function defines the node that the build should run on. This is populated by the platform parameter. By providing a variable here the same Jenkinsfile can be used in the case of Cordova where the builds may need to be executed on and 'android' or 'ios' node.
3 Add a stage to the build. Multiple stages can be added to break up builds logically. The stage function takes one argument which is the name of the stage.
4 Checkout the source code of the repo. This is done using the provided checkout function. scm is another helper which uses the SCM details from the Jenkins job configuration. When using Digger with RHMAP the SCM details will be configured automatically at build time.
5 Platform specific pre-requisite steps are executed during the prepare stage. e.g. add platform for cordova.
6 Build the applications. This is done using a build tool such as Gradle for Android or Xcode for iOS. The steps involved here are covered further in Using Jenkinsfiles in an app.
7 Sign the application using application specific steps if required
8 Archive the resulting artifacts of the build. When building Android and iOS apps there will be resulting build artifacts which can be stored. The archiveArtifacts function allows this to be done by providing the path to the artifacts as parameters.

Using Jenkinsfiles in an app

The below section outlines in further detail the steps taken via the Jenkinsfile to build an Application. Please refer to these sections if the provided Jenkinsfiles require altering or adjusting to work for building applications in your environment.

Checkout source code

To checkout a projects source code the checkout step can be used.

node("android"){
  ...
  stage("Checkout"){
    checkout scm
  }
  ...
}

Prepare the Environment/Application

Adding a configuration file (RHMAP only)

When building apps in RHMAP a properties file should be added to the app to allow it to make backend requests. In Android this is a properties file named fhconfig.properties, in iOS this is a plist file named fhconfig.plist. The contents of these files is provided in the Jenkinsfile through params.FH_CONFIG_CONTENT. Below are examples of populating the configuration file for Android and iOS.

fhconfig Android properties file
node(platform) {
  ...
  stage("Prepare"){
    writeFile file: 'app/src/main/assets/fhconfig.properties', text: params.FH_CONFIG_CONTENT
  }
  ...
}
fhconfig iOS plist file
node(platform) {
  stage("Prepare") {
    writeFile: file: 'app/fhconfig.plist', text: params.FH_CONFIG_CONTENT
  }
}

Cordova preparation

For Cordova applications it is required to carry out steps to add and prepare the platform in the environment the application is building. Below are the steps required to complete this successfully. Note the multiple uses of the platform variable here. These steps are reused for building both "android" and "ios" depending on the platform value set.

node(platform) {
  stage("Prepare") {
    sh "cordova platform rm ${platform}"
    sh "cordova platform add ${platform}"
    sh "cordova prepare ${platform}"
  }
}

Building the Application

Building Applications with Xcode

To build Xcode projects you can use the xcodeBuild function in your Jenkinsfile, this requires the XC_VERSION environment variable to be defined. To sign the app the xcodeBuild function can then be used. See the parameters section for further details on values passed.

node('ios'){
  ...
  stage('Build') {
    withEnv(['XC_VERSION=8.3']) {
      xcodeBuild(
        cleanBeforeBuild: true,
        src: 'helloworld-ios-swift',
        schema: 'helloworld-ios-app',
        workspace: 'helloworld-ios-app',
        buildDir: 'build',
        sdk: 'iphoneos',
        version: '0.1-alpha',
        shortVersion: '0.1',
        bundleId: 'com.feedhenry.helloworld-ios-app',
        infoPlistPath: 'helloworld-ios-app/helloworld-ios-app-Info.plist',
        flags: '-fstack-protector -fstack-protector-all ENABLE_BITCODE=NO',
        autoSign: false
      )
    }
  }

  stage('CodeSign') {
    codeSign(
      profileId: "${params.BUILD_CREDENTIAL_ID}",
      clean: true,
      verify: true,
      ipaName: 'myapp',
      appPath: 'helloworld-ios-swift/build/Debug-iphoneos/helloworld-ios-app.app'
    )
  }
  ...
}

Building Cordova Applications

To build Cordova Applications the Jenkinsfile carries out seperate steps depending on whether the Application is being built for debug or release. Again note the use of the platform environment variable. Also BUILD_CONFIG is used in this case to decide the use of the cordova build command.

node(platform){
  ...
  stage('Build'){
      if (BUILD_CONFIG == 'debug') {
            sh "cordova build ${platform} --debug"
      } else {
            sh "cordova build ${platform} --release"
      }
  }

}

Building Android Applications

See the steps shown below showing the use gradle to build an Android Application for Debug or Release.

node("android"){
  ...
  stage("Build"){
    sh 'chmod +x ./gradlew'
    if (params.BUILD_CONFIG == 'release') {
      sh './gradlew clean assembleRelease' // builds app/build/outputs/apk/app-release.apk file
    } else {
      sh './gradlew clean assembleDebug' // builds app/build/outputs/apk/app-debug.apk
    }
  }
  ...
}

Using specific versions of Android SDK and Gradle

Android SDK and Gradle versions are defined in the Android project.

To change Android SDK version change the version information in app’s app/build.gradle file:

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig {
        ...
        minSdkVersion 16
        targetSdkVersion 25
        ...
    }
...
}

See Android platform documents for explanation of these properties.

To change Gradle version, change the distributionUrl property in gradle/wrapper/gradle-wrapper.properties in the app’s source tree.

distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

Signing the Application

Signing Android build

When an Android apk is created it can be signed using the provided signAndroidApks function. See the parameters section for additional information of values passed.

node("android"){
  ...
  stage("Sign"){
    if (params.BUILD_CONFIG == 'release') {
        signAndroidApks (
          keyStoreId: "${params.BUILD_CREDENTIAL_ID}",
          keyAlias: "${params.BUILD_CREDENTIAL_ALIAS}",
          apksToSign: "**/*-unsigned.apk",
          // uncomment the following line to output the signed APK to a
          separate directory as described above
          // signedApkMapping: [ $class: UnsignedApkBuilderDirMapping ],
        )
    } else {
      println('Debug Build - Using default developer signing key')
    }
  }
  ...
}

Function Parameters

signAndroidApks Parameters

The signAndroidApks function takes the following parameters.

Table 1. signAndroidApks options
Parameter Description

keyStoreId

Keystore ID. This will be provided through the BUILD_CREDENTIAL_ID parameter if the app is built through RHMAP.

keyAlias

Alias of the private key/certificate chain. This will be provided through the BUILD_CREDENTIAL_ALIAS parameter if the app is built through RHMAP.

apksToSign

A file name or glob pattern specifying the APK files to store.

signedApkMapping

Output the signed APK to a separate directory than the unsigned APK. Omit if storing in the same directory.

androidHome

Override Android home directory.

The function takes the following parameters.

Building with xCode Parameters

Table 2. xcodeBuild options
Parameter Description

cleanBeforeBuild

This will delete the build directories before invoking the build. This will force the rebuilding of all dependencies and can make large projects take a lot longer

target

The target to build. If left empty, this will build all targets in the project. If you wish to build your binary and the unit test module, it is best to do this as two separate steps each with their own target.

sdk

You only need to supply this value if you want to specify the SDK to build against. If empty, the SDK will be determined by XCode.

workspace

Workspace to build from.

buildDir

The value to use for CONFIGURATION_BUILD_DIR setting (BUILD_DIR in >= 2.0.0).

version

Version of the app.

shortVersion

Short representation of the apps version.

autoSign

Whether to sign the app automatically or not.

infoPlistPath

Path to the apps plist file.

flags

Flags to add to the command that is executed.

CodeSign Parameters

Table 3. codeSign options
Parameter Description

profileId

ID of the developer profile. This will be provided through the BUILD_CREDENTIAL_ID parameter if the app is built through RHMAP.

clean

Removes the previous signature (if any) before signing the artifact.

verify

Whether or not to verify the signature of the app after signing.

ipaName

Name of the created ipa file.

appPath

Path to the app to sign.

Customising Jenkinsfile

A developer may wish to customise their Jenkinsfile to build an application. For instance they may want to install a specific version of nodejs or build with a specific version of a dependency as an alternative to the default version which is installed globally. An example snippet of each use case is outlined below:

Specifying a specific nodejs version

A developer needs to install dependencies on a Node v6.9.5 runtime

node("android"){
  ...
  stage("Prepare"){
      sh '. $NVM_DIR/nvm.sh && nvm install 6.9.5 && nvm alias default 6.9.5'
      writeFile file: 'www/fhconfig.json', text: params.FH_CONFIG_CONTENT
      sh 'npm install --production'
      ...
  }
  ...
}

Installing and using a specific dependency version

A developer’s Cordova application needs to be built with Cordova version 6.3.1

node("android"){
  ...

  stage("Prepare"){
      ...
      sh "npm install cordova@6.3.1"
      sh "node_modules/cordova/bin/cordova platform rm ${platform}"
      sh "node_modules/cordova/bin/cordova platform add ${platform}"
      sh "node_modules/cordova/bin/cordova prepare ${platform}"
      ...
  }
  ...
}

Fastlane Support

AeroGear Digger provides support for using fastlane (version 2.60.1) when building applications. This required resources (mentioned in the steps below) are provided in aerogear-digger repo on github.

  1. Copy the specific platform (ios/android) fastlane folder to the root directory of you application

  2. Copy/Update Jenkinsfile

    If you have an existing Jenkinsfile use the Prepare and Build steps in the provided Jenkinsfile as examples of how to use the fastlane tool in an existing Jenkinsfile

    If do not have an existing Jenkinsfile, copy the Jenkinsfile from the specific platform fastlane folder to the root directory of you application.

  3. Trigger a build in your AeroGear Digger instance.

Building Applications

Building iOS Applications

To build iOS Application using Aerogear Digger take the following steps below.

  1. Add a Jenkinsfile to the Application

Add a relevant (depending on the type of the application) Jenkinsfile to the root directoy of your application. Aerogear Digger provides sample Jenkinsfiles for building the following 3 types of Applications

  • Native Android

  • Native iOS

  • Cordova (for Android and iOS)

The files are provided with a .groovy extension. Rename the file to Jenkinsfile when adding it to the application.

  1. Create iOS Credentials

    Create a zipfile with your dev certificate and private key (in p12 file format) and a provisioning profile.

  2. Create new Jenkins Credentials

    Create a new Jenkins credentials using the apple developer profile type using the following steps

    1. Login in as admin user

    2. → Click on Credentials (left menu)

    3. → Click on System (left menu)

    4. → Click on global credentials

    5. → Click on Add Credentials

    6. Choose Kind: Apple Developer Profile

    7. Upload the zip file created in Step 1

    8. Enter password (Note: you may need to resize your browser to view the password entry correctly)

    9. Add description (optional)

    10. Press OK

  3. Create a new Pipeline job in Jenkins

  4. Create a new pipeline job using the following steps.

    1. Click on New Item

    2. Enter a Name for the Build Pipeline

    3. Choose Pipeline

    4. Click on OK

    Create Build Pipeline
  5. Configure the newly created pipeline

    1. → Select the newly create pipeline from the main screen.

    2. → Click on Configure (left menu)

    3. The image below points to the relevant items for the following sections

      Configure Build Pipeline
    4. → Select This project is parameterised (see image)

    5. Create the required parameters

      The table below shows the parameters that are required to build using the default Jenkinsfile provided by Aerogear Digger.

      Variable name Description Values

      BUILD_CREDENTIAL_ID

      The Jenkins Credentials id that was created in step 2

      BUILD_CONFIG

      Type of build

      "debug" or "release"

      FH_CONFIG_CONTENT

      * Relevant only for builds triggered from RHMAP.

      Add Parameters
    6. Click on Defenition dropdown

      Pipeline from Script
    7. Choose Pipeline script from SCM

    8. Choose SCM → Git

    9. Enter Repository URL → the url of the git repository

    10. Add Credentials

    11. Review Branches to build

  6. Trigger the build

    1. Return to the build screen

    2. → Click on Build with Parameters

    3. Update parameters (if required)

    4. → Click on Build

redhatlogo-wite