#Github pull reqest builder for Jenkins import json import os import re import urllib2 import urllib import base64 import requests import sys import traceback import platform import subprocess import codecs from shutil import copy #set Jenkins build description using submitDescription to mock browser behavior #TODO: need to set parent build description def set_description(desc, url): req_data = urllib.urlencode({'description': desc}) req = urllib2.Request(url + 'submitDescription', req_data) #print(os.environ['BUILD_URL']) req.add_header('Content-Type', 'application/x-www-form-urlencoded') base64string = base64.encodestring(os.environ['JENKINS_ADMIN']+ ":" + os.environ['JENKINS_ADMIN_PW']).replace('\n', '') req.add_header("Authorization", "Basic " + base64string) try: urllib2.urlopen(req) except: traceback.print_exc() def check_current_3rd_libs(): #get current_libs config config_file_path = "external/config.json" if not os.path.isfile(config_file_path): raise Exception("Could not find 'external/config.json'") with open(config_file_path) as data_file: data = json.load(data_file) current_3rd_libs_version = data["current_libs_version"] filename = current_3rd_libs_version + '.zip' node_name = os.environ['NODE_NAME'] backup_file = '../../../cocos-2dx-external/node/' + node_name + '/' + filename current_file = filename if os.path.isfile(backup_file): copy(backup_file, current_file) os.system('python download-deps.py -r no') #backup file copy(current_file, backup_file) def main(): #get payload from os env payload_str = os.environ['payload'] payload_str = payload_str.decode('utf-8','ignore') #parse to json obj payload = json.loads(payload_str) #get pull number pr_num = payload['number'] print 'pr_num:' + str(pr_num) #build for pull request action 'open' and 'synchronize', skip 'close' action = payload['action'] print 'action: ' + action #pr = payload['pull_request'] url = payload['html_url'] print "url:" + url pr_desc = '

pr#' + str(pr_num) + ' is '+ action +'

' #get statuses url statuses_url = payload['statuses_url'] #get pr target branch branch = payload['branch'] #set commit status to pending #target_url = os.environ['BUILD_URL'] jenkins_url = os.environ['JENKINS_URL'] job_name = os.environ['JOB_NAME'].split('/')[0] build_number = os.environ['BUILD_NUMBER'] target_url = jenkins_url + 'job/' + job_name + '/' + build_number + '/' set_description(pr_desc, target_url) data = {"state":"pending", "target_url":target_url} access_token = os.environ['GITHUB_ACCESS_TOKEN'] Headers = {"Authorization":"token " + access_token} try: requests.post(statuses_url, data=json.dumps(data), headers=Headers) except: traceback.print_exc() #reset path to workspace root os.system("cd " + os.environ['WORKSPACE']); os.system("git checkout v3") os.system("git branch -D pull" + str(pr_num)) #clean workspace print "Before checkout: git clean -xdf -f" os.system("git clean -xdf -f") #fetch pull request to local repo git_fetch_pr = "git fetch origin pull/" + str(pr_num) + "/merge" ret = os.system(git_fetch_pr) if(ret != 0): return(2) #checkout git_checkout = "git checkout -b " + "pull" + str(pr_num) + " FETCH_HEAD" os.system(git_checkout) # After checkout a new branch, clean workspace again print "After checkout: git clean -xdf -f" os.system("git clean -xdf -f") #update submodule git_update_submodule = "git submodule update --init --force" ret = os.system(git_update_submodule) if(ret != 0): return(2) #copy check_current_3rd_libs check_current_3rd_libs() # Generate binding glue codes if(branch == 'v3'): ret = os.system("python tools/jenkins-scripts/gen_jsb.py") elif(branch == 'v2'): os.chdir('tools/tojs') if(platform.system() == 'Windows'): os.environ['NDK_ROOT'] = os.environ['NDK_ROOT_R8E'] ret = os.system("genbindings-win32.bat") os.environ['NDK_ROOT'] = os.environ['NDK_ROOT_R9B'] else: ret = os.system("./genbindings.sh") os.chdir('../..') if(ret != 0): return(1) #make temp dir print "current dir is: " + os.environ['WORKSPACE'] os.system("cd " + os.environ['WORKSPACE']); os.mkdir("android_build_objs") #add symbol link PROJECTS=["cpp-empty-test", "cpp-tests"] print platform.system() if(platform.system() == 'Darwin'): for item in PROJECTS: cmd = "ln -s " + os.environ['WORKSPACE']+"/android_build_objs/ " + os.environ['WORKSPACE']+"/tests/"+item+"/proj.android/obj" os.system(cmd) elif(platform.system() == 'Windows'): for item in PROJECTS: p = item.replace("/", os.sep) cmd = "mklink /J "+os.environ['WORKSPACE']+os.sep+"tests"+os.sep +p+os.sep+"proj.android"+os.sep+"obj " + os.environ['WORKSPACE']+os.sep+"android_build_objs" print cmd os.system(cmd) #build #TODO: add android-linux build #TODO: add mac build node_name = os.environ['NODE_NAME'] if(branch == 'v3'): if(node_name == 'android_mac') or (node_name == 'android_win7'): #modify tests/cpp-empty-test/Classes/AppDelegate.cpp to support Console modify_file = 'tests/cpp-empty-test/Classes/AppDelegate.cpp' data = codecs.open(modify_file, encoding='UTF-8').read() data = re.sub("director->setDisplayStats\(true\);", "director->setDisplayStats(true); director->getConsole()->listenOnTCP(5678);", data) codecs.open(modify_file, 'wb', encoding='UTF-8').write(data) #modify tests/cpp-empty-test/proj.android/AndroidManifest.xml to support Console modify_file = 'tests/cpp-empty-test/proj.android/AndroidManifest.xml' data = codecs.open(modify_file, encoding='UTF-8').read() data = re.sub('', ' ', data) codecs.open(modify_file, 'wb', encoding='UTF-8').write(data) print "Start build android..." ret = os.system("python build/android-build.py -n -j10 all") # create and save apk if(ret == 0): sample_dir = 'tests/cpp-empty-test/proj.android/' os.system('android update project -p cocos/2d/platform/android/java/ -t android-13') os.system('android update project -p ' + sample_dir + ' -t android-13') os.system('ant debug -f ' + sample_dir + 'build.xml') local_apk = sample_dir + 'bin/CppEmptyTest-debug.apk' remote_apk = 'apks/cpp_empty_test/cpp_empty_test_' + str(pr_num) + '.apk' os.system('tools/jenkins-scripts/upload_apk.sh ' + local_apk + ' ' + remote_apk) elif(node_name == 'win32_win7'): ret = subprocess.call('"%VS110COMNTOOLS%..\IDE\devenv.com" "build\cocos2d-win32.vc2012.sln" /Build "Debug|Win32"', shell=True) elif(node_name == 'ios_mac'): ret = os.system("tools/jenkins-scripts/ios-build.sh") elif(node_name == 'linux_centos'): os.chdir("build/") ret = os.system("cmake ../") ret = os.system("make -j10") os.chdir("../") elif(branch == 'v2'): SAMPLES_DIRS = ['Cpp/HelloCpp', 'Cpp/SimpleGame', 'Cpp/TestCpp', 'Javascript/TestJavascript', 'Lua/HelloLua', 'Lua/TestLua'] SAMPLES_NAMES = ['HelloCpp', 'SimpleGame', 'TestCpp', 'TestJavascript', 'HelloLua', 'TestLua'] if(node_name == 'android_mac'): for item in SAMPLES_DIRS: proj_dir = "samples/" + item + "/proj.android" os.system('ln -s ../../../../android_build_objs obj') os.system(proj_dir + "/build_native.sh") if (ret != 0): break elif(node_name == 'win32_win7'): ret = subprocess.call('"%VS110COMNTOOLS%..\IDE\devenv.com" "cocos2d-win32.vc2012.sln" /Build "Debug|Win32"', shell=True) elif(node_name == 'ios_mac'): for i, item in enumerate(SAMPLES_DIRS): cmd = "xcodebuild -project samples/" + item + "/proj.ios/" + SAMPLES_NAMES[i] + ".xcodeproj -scheme " + SAMPLES_NAMES[i] + ' -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)"' cmd_clean = cmd + ' clean' cmd_build = cmd + ' build' ret = os.system(cmd_clean) if(ret != 0): break ret = os.system(cmd_build) if(ret != 0): break elif(node_name == 'linux_centos'): data = codecs.open('cocos2dx/proj.linux/cocos2dx.mk', encoding='UTF-8').read() data = re.sub('-lglfw','-L$(GLFW_279_LIB) -lglfw', data) codecs.open('cocos2dx/proj.linux/cocos2dx.mk', 'wb', encoding='UTF-8').write(data) ret = os.system('make -j10') else: ret = 0 #get build result print "build finished and return " + str(ret) exit_code = 1 if ret == 0: exit_code = 0 else: exit_code = 1 #clean workspace os.system("cd " + os.environ['WORKSPACE']) os.system("git reset --hard") os.system("git clean -xdf -f") os.system("git checkout v3") os.system("git branch -D pull" + str(pr_num)) return(exit_code) # -------------- main -------------- if __name__ == '__main__': sys_ret = 0 try: sys_ret = main() except: traceback.print_exc() sys_ret = 1 finally: sys.exit(sys_ret)