Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuous Integration with Jenkins for React Native (iOS + Android) project

It is possible to implement Continuous Integration for a React Native app using Jenkins? I haven't found a guide to do this. If there are also other solution, what is the best one? Also, a Mac OS machine is mandatory for iOS project?

like image 278
Adrian Zghibarta Avatar asked Dec 06 '16 07:12

Adrian Zghibarta


2 Answers

The first thing is to get a command line build working for both Android and iOS. You can peak at the Xcode or Android Studio logs and copy some of the commands.

I put a build.sh script in the ios and android folders that I can call from a Jenkins job to build respective targets. You could have a build.sh in your project root that calls both.

Todo: I want to figure out how to run eslint airbnb in a Jenkins job and generate a report?

Here is my iOS build.sh script that works with Xcode 9:

#!/bin/sh
############################################
# File: build.sh
# -----------------------
# Author: [email protected]
#
# Command line build:
#   1) clean
#   2) build
#   3) archive
#   4) export IPA
#
# http://shashikantjagtap.net/xcodebuild-deploy-ios-app-command-line/
# https://help.apple.com/itc/apploader/e3#/apdATD1E53-D1E1A1303-D1E53A1126
#

 isInPath=$(which xcodebuild)
 if [ ! -x "${isInPath}" ] ; then
    echo "*** Error xcodebuild not found in path"
    exit 1
 fi

isInPath=$(which xcrun)
 if [ ! -x "${isInPath}" ] ; then
    echo "*** Error xcrun not found in path"
    exit 1
 fi


echo "### Start: Cleaning ###############################################################"
rm -rf build
xcodebuild -project MyApp.xcodeproj -scheme MyApp -destination generic/platform=iOS clean     
echo "### Done: Cleaning ###############################################################"

# Analyze
# xcodebuild -project MyApp.xcodeproj -scheme MyApp -sdk iphoneos clean analyze

echo "### Start: Building ###############################################################"
# xcodebuild -project MyApp.xcodeproj -target MyApp -showBuildSettings
# xcodebuild -project MyApp.xcodeproj -scheme MyApp -destination generic/platform=iOS build    

# Run pod install once before building workspace
pod install 

# Now using a Podfile so have to build workspace not build project
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -destination generic/platform=iOS build     
echo "### Done: Building ###############################################################"


CFBundleShortVersionString=`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ./MyApp/Info.plist`
CFBundleVersion=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" ./MyApp/Info.plist`
echo "CFBundleShortVersionString: ${CFBundleShortVersionString}"
echo "CFBundleVersion: ${CFBundleVersion}"

ipaFileName=MyApp.ipa
renameIpaFileName="field-scout-${CFBundleShortVersionString}.${CFBundleVersion}.ipa"

echo "### Start: Archiving ###############################################################"
# xcodebuild -project MyApp.xcodeproj -scheme MyApp -sdk iphoneos -configuration AppStoreDistribution archive -archivePath $PWD/build/MyApp.xcarchive

# Now using a Podfile so have to build workspace not build project
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -sdk iphoneos -configuration AppStoreDistribution archive -archivePath $PWD/build/MyApp.xcarchive
echo "### Done: Archiving ###############################################################"

echo "### Start: Exporting ###############################################################"
xcodebuild -exportArchive -archivePath $PWD/build/MyApp.xcarchive -exportOptionsPlist MyApp/ExportOptions.plist -exportPath $PWD/build
ls -al build
echo "### Done: Exporting ###############################################################"

appArchiveFile=build/${ipaFileName}
if [ ! -f "${appArchiveFile}" ]; then
    echo "*** Error file not found: ${appArchiveFile}"
    exit 1    
fi

# Extract and verify archive contents
echo "### Unzip: ${ipaFileName}  ###############################################################"
( cd build; unzip -q ${ipaFileName} )
( cd build/Payload; xcrun codesign -dv MyApp.app/ )

outputFile=build/Payload/MyApp.app
if [ ! -d "${outputFile}" ]; then
    echo "*** Error file not found: ${outputFile}"
    exit 1    
fi
rm -rf ./build/Payload
rm -rf ./build/Symbols


# altool is used to verify iOS IPA files
altool_path=/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/Current/Support

isInPath=$(which altool)
 if [ ! -x "${isInPath}" ] ; then
    echo "*** Error altool not found in path"
    echo "Expected altool path:\n ${altool_path}"
    exit 1
 fi

# altool validate will trigger a user dialog first time it is run.
# On a jenkins slave you will need to execute manually in a console once, to allow keychain access.
# $ altool --validate-app -f file -u username [-p password] [--output-format xml]
# $ altool --upload-app -f file -u username [-p password] [--output-format xml]
altool --validate-app -f build/${ipaFileName} -u [email protected] -p @keychain:"Application Loader: [email protected]"
altool --validate-app -f build/${ipaFileName} -u [email protected] -p @keychain:"Application Loader: [email protected]" --output-format xml > build/validate.xml
altoolValidate=$?
if [ ${altoolValidate} -ne 0 ]; then
    echo "*** Error IPA failed to validate: build/${ipaFileName}"
    echo "See: build/validate.xml"
    exit 1    
fi

echo "Rename build/${ipaFileName} to build/${renameIpaFileName}" 
mv ./build/${ipaFileName} ./build/${renameIpaFileName} 

echo ##############################
echo        Done 
echo ##############################
echo Ready to upload archive to iTunes:
echo "  ${appArchiveFile}"
echo
uploadExample="$( echo altool --upload-app -f build/${renameIpaFileName} -u [email protected] -p @keychain:"Application Loader: [email protected]" )"
echo "Upload Example:\n ${uploadExample}"
echo
like image 56
Ed of the Mountain Avatar answered Oct 13 '22 00:10

Ed of the Mountain


Yes, it is totally possible. You only have to execute all actions from the command line instead of XCode or the IDE of your choice. In the case of iOS, have a look at the react-native bundle command to create the JS bundle and xcodebuild and xcrun for compiling the native code. In Android it is a bit easier, since you have the gradle assembleRelease task. Before that you have to run npm install to get all your dependencies, but that should roughly be it.

As for iOS development, unfortunately there is no way around it, you do need an OS X machine.

like image 33
martinarroyo Avatar answered Oct 13 '22 00:10

martinarroyo