unity之Jenkins自动化出包shell脚本

2021-01-28 01:13

阅读:565

标签:mic   round   find   back   手游   提示   bat   icons   lse   

jenkins工具自动化出包,此功能不是我做的。

用到的shell脚本分享一下,以备将来研究之用。

 

Jenkins中构建:

技术图片

 

 

 命令为:

1 #!C:/Program Files/Git/bin/bash
2 python -u D:/buildApk_New/USA/sgmyPackge/package.py $Versions E:/WorkTool/Unity2017.4/Unity/Editor/Unity.exe $VersionIncrease $BuildFlavor $BigPackage

 

shell脚本如下:

1. utils.py

技术图片技术图片
  1 import hashlib
  2 import subprocess
  3 import platform
  4 import shutil
  5 import os
  6 
  7 _FILE_SLIM = (100 * 1024 * 1024)  # 100MB
  8 cur_os = platform.system()
  9 
 10 def subprocess_return(cmd):
 11     print(cmd)
 12     status = subprocess.call(cmd,shell = True)
 13     return status
 14 
 15 def subprocess_call(cmd):
 16     print (cmd)
 17     status = subprocess.call(cmd,shell = True)
 18     if status != 0:
 19         exit(status)
 20 
 21 def CheckUnity():
 22     cmd = "ps -ef|grep MacOS/Unity |grep -v CheckUnity |grep -v grep "
 23     if cur_os == "Windows":
 24         cmd = "tasklist | findstr Unity"
 25     status = subprocess.call(cmd,shell = True)
 26     if status == 0 :
 27         print ("Unity is running!!")
 28     return status
 29 
 30 def killUnity():
 31     cmd = "killall -9 Unity"
 32     if cur_os == "Windows":
 33         cmd = "taskkill /f /im Unity.exe"
 34     status = subprocess.call(cmd,shell = True)
 35     if status == 0 :
 36         print ("no running Unity")
 37     return status
 38 
 39 def file_md5(filename):
 40      calltimes = 0
 41      hmd5 = hashlib.md5()
 42      fp = open(filename,"rb")
 43      f_size = os.stat(filename).st_size
 44      if f_size>_FILE_SLIM:
 45          while(f_size>_FILE_SLIM):
 46              hmd5.update(fp.read(_FILE_SLIM))
 47              f_size/=_FILE_SLIM
 48              calltimes += 1   #delete
 49          if(f_size>0) and (f_size_FILE_SLIM):
 50              hmd5.update(fp.read())
 51      else:
 52          hmd5.update(fp.read())
 53 
 54      return (hmd5.hexdigest(),calltimes)
 55 
 56 def copyc(path, out):
 57     for files in os.listdir(path):
 58         name = os.path.join(path, files)
 59         back_name = os.path.join(out, files)
 60         if os.path.isfile(name):
 61             shutil.copy(name, back_name)
 62         else:
 63             if not os.path.isdir(back_name):
 64                 os.makedirs(back_name)
 65             copyc(name, back_name)
 66 
 67 def copyd(path,out):
 68     for files in os.listdir(path):
 69         name = os.path.join(path,files)
 70         back_name = os.path.join(out,files)
 71         if os.path.exists(back_name):
 72             pass
 73         else:
 74             if os.path.isfile(name):
 75                 shutil.copy(name, back_name)
 76             else:
 77                 if not os.path.isdir(back_name):
 78                     os.makedirs(back_name)
 79                 copyd(name, back_name)
 80 def buildpackage_unity(unity_bin, rootpath, printpath):
 81     ###unity build by command line
 82 
 83     cmd = "%s -batchmode  84     -quit -projectPath  85     %s/UnityClient  86     -executeMethod ProjectBuilder.BuildPlayerForASProject  87     Path=%s" % (unity_bin, rootpath, printpath)
 88 
 89     status = subprocess_return(cmd)
 90     return status
 91 
 92 def buildBigPackage(unity_bin,rootpath):
 93 
 94     cmd = "%s -batchmode  95     -quit -projectPath  96     %s/UnityClient  97     -executeMethod ReduceLocalAssetBundleTool.ReduseLocalAssets " % (unity_bin, rootpath)
 98 
 99     status = subprocess_return(cmd)
100     return status
101 
102 def buildBigPackageRe(unity_bin,rootpath):
103 
104     cmd = "%s -batchmode 105     -quit -projectPath 106     %s/UnityClient 107     -executeMethod ReduceLocalAssetBundleTool.RevertReduseLocalAssets " % (unity_bin, rootpath)
108 
109     status = subprocess_return(cmd)
110     return status    
111 def showlastline(filepath, num):
112     text = []
113     f = open(filepath, rb)
114 
115     lines = f.readlines()
116     count = len(lines)
117     if count > 100:
118         num = 100
119     else:
120         num = count
121 
122     for i in range(1, (num+1)):
123         if lines:
124             n = -i
125             lastline = lines[n].strip()
126             text.append(lastline)
127 
128     f.close()
129     while text:
130         #print (text.pop())
131         pass
132 
133 def showlog_buildfailed(unitylogfile):
134     print ("\n\nbuild failed!!!!\n\n\n###Editor.log############################################################################")
135     if os.path.exists(unitylogfile):
136         os.remove(unitylogfile)
137     file = open(unitylogfile,"w")
138     file.close()
139     showlastline(unitylogfile,100)
140     exit(1)
141     pass
142 
143 def CheckXcode():
144     if cur_os == "Darwin" :
145         cmd = "ps -ef|grep Xcode |grep -v grep "
146     status = subprocess.call(cmd,shell = True)
147     if status == 0 :
148         print ("Xcode is running!!")
149     return status
150 
151 def CheckiTunes():
152     if cur_os == "Darwin" :
153         cmd = "ps -ef|grep iTunes |grep -v grep "
154     status = subprocess.call(cmd,shell = True)
155     if status == 0 :
156         print ("iTunes is running!!")
157     return status
158 
159 def killXcode():
160     if cur_os == "Darwin":
161         cmd = "killall -9 Xcode"
162     status = subprocess.call(cmd,shell = True)
163     if status == 0 :
164         print ("no running Xcode")
165     return status
166 
167 def killiTunes():
168     if cur_os == "Darwin":
169         cmd = "killall -9 iTunes"
170     status = subprocess.call(cmd,shell = True)
171     if status == 0 :
172         print ("no running iTunes")
173     return status
174 
175 def svn_cleanup(path):
176     cmd = svn cleanup %s %(path)
177     subprocess_call(cmd)
178 
179 def svn_up(path):
180     cmd = "svn up %s --non-interactive" %(path)
181     subprocess_call(cmd)
182 
183 def svn_add(path):
184     cmd = "svn add %s --force" %(path)
185     subprocess_call(cmd)
186 
187 def svn_ci(path,desc):
188     cmd = "svn ci %s -m %s" %(path,desc)
189     subprocess_call(cmd)
190 
191 def rw_vconfig_autoincrement(path,autoIncreament):
192     f = open(path,r)
193     configStr = f.read()
194     versionCodeStr = configStr.split("\n")[0].replace("versionCode=","")
195     versionNameStr = configStr.split("\n")[1].replace("versionName=","")
196     versionCode = int(versionCodeStr)
197     versionName = float(versionNameStr)
198     versionCode_add = versionCode +1
199     versionCodeName_add = round(versionName + 0.1, 1)
200     changedConfigStr = "versionCode=%s\nversionName=%s" % (versionCode_add, versionCodeName_add)
201     f.close()
202     if autoIncreament == "true":
203         f = open(path, w)
204         f.write(changedConfigStr)
205         f.close()
206     return versionCode,versionName
207 
208 # def os_popen_show(cmd):
209 #     print (cmd)
210 #     rs = os.popen(cmd).readlines()
211 #     matched = len(rs)
212 #     count = 0
213 #     while count 
214 #         print (rs[count].replace(‘\n‘,‘‘))
215 #         count = count + 1
216 #     return matched
utils.py

2. package.py

技术图片技术图片
  1 ###
  2 ###python3
  3 ###请在该py文件中配置手动配置svnPath变量的值及输出apk上传的本地svn路径,productName及Unity中PlyerSetting中ProductName
  4 ###Unity日志输出路径为Unity项目下面Editor.log
  5 ###
  6 
  7 import shutil
  8 import os
  9 import time
 10 import math
 11 import sys
 12 import json
 13 import utils
 14 import a360syb
 15 
 16 
 17 print("-----------------starting build package--------------------")
 18 time1 = time.time()
 19 
 20 
 21 print()
 22 print()
 23 """
 24 第一个参数为Untiy的路径
 25 第二个参数为Unity项目的路径  如:E:\\Git\\UnityClient-vn
 26 """
 27 
 28 rootpath = "E:\\Versions\\"+sys.argv[1]+"\\UnityClient"
 29 unity_bin = sys.argv[2]
 30 auIncreVer = sys.argv[3]
 31 packageFlavor = sys.argv[4]
 32 bigPackage = sys.argv[5]
 33 
 34 productName = "AU2 Mobile-EN"#
 35 showName = "AU2Dance Idol";
 36 svnPath = "D:\\ApkVersions\\SGMY"
 37 targetGradle = "E:\\buildApk_New\\SGMY\\SuperIdolMobile\\"
 38 targetproject = targetGradle +"app"
 39 Unitylogfile = rootpath+"\\Editor.log"
 40 asprojectfile = rootpath+"\\UnityClient\\androidstudio"
 41 resRelativePath = "\\src\\main\\res"
 42 libsRelativePath = "\\libs"
 43 soRelativePath = "\\src\\main\\jniLibs"
 44 assetsRelativePath = "\\src\\main\\assets"
 45                                     #TODO
 46 iconName = "app_icon.png"
 47 versionConfig = "E:\\buildApk_New\\SGMY\\sgmyPackge\\versionConfig"
 48 
 49 #unity判断什么的
 50 while utils.CheckUnity() == 0:
 51     print("Unity进程正在运行")
 52     utils.killUnity()
 53     time.sleep(2)
 54 
 55 print("------- building as project from Unity--------")
 56 print()
 57 
 58 status=0
 59 if bigPackage == "false":
 60     status = utils.buildBigPackage(unity_bin,rootpath)
 61 if status != 0:
 62     utils.showlog_buildfailed(Unitylogfile)
 63 
 64 if os.path.exists(asprojectfile):
 65     shutil.rmtree(asprojectfile)
 66 
 67 status = utils.buildpackage_unity(unity_bin,rootpath,asprojectfile)
 68 if status != 0:
 69     utils.showlog_buildfailed(Unitylogfile)
 70 if not os.path.exists(asprojectfile):
 71     print("未能正确打出As工程")
 72     exit(1)
 73 print()
 74 print("------- build as project finish--------")
 75 
 76 """
 77 创建Unity打出的as工程内部资源和目标资源的路径
 78 """
 79 asprojectfile_libs = asprojectfile+"\\"+productName+libsRelativePath
 80 targetProjectfile_libs = targetproject+libsRelativePath
 81 asprojectfile_res = asprojectfile+"\\"+productName+resRelativePath
 82 targetProjectfile_res = targetproject+resRelativePath
 83 asprojectfile_assets = asprojectfile+"\\"+productName+assetsRelativePath
 84 targetProjectfile_assets = targetproject+assetsRelativePath
 85 asprojectfile_so = asprojectfile+"\\"+productName+soRelativePath
 86 targetProjectfile_so = targetproject+soRelativePath
 87 
 88 print("---------compareing libs--------------")
 89 print()
 90 
 91 
 92 if bigPackage == "false":
 93     status = utils.buildBigPackageRe(unity_bin,rootpath)
 94 if status != 0:
 95     utils.showlog_buildfailed(Unitylogfile)
 96 """
 97 比对Libs文件夹,只比对。如果不匹配就提示
 98 """
 99 asLibsDict = {}
100 targetLibsDict = {}
101 for root,dirs,files in os.walk(asprojectfile_libs):
102     for name in dirs:
103         print("AAAAA",os.path.join(root,name))
104     for name in files:
105         asLibsDict[name] = utils.file_md5(os.path.join(root,name))[0]
106 #print (asLibsDict)
107 
108 for root,dirs,files in os.walk(targetProjectfile_libs):
109     for name in dirs:
110         pass
111         # print("A",os.path.join(root,name))
112     for name in files:
113         targetLibsDict[name] = utils.file_md5(os.path.join(root,name))[0]
114 defalutTip = "NONE"
115 for key,value in asLibsDict.items():
116     tv = targetLibsDict.get(key,defalutTip)
117     if tv == defalutTip:
118         tv = "在targetLib中没有 " + key + " 文件,如需要请手动配置"
119         print(tv)
120     else :
121         if tv == value:
122             pass
123         else :
124             tv = "在targetLib中 "+key+" 文件与unity打出as工程中文件MD5值不一样,如需要请手动配置"
125             print(tv)
126 
127 print()
128 print("---------compare libs finish--------------")
129 
130 print("---------compareing icon and appName--------------")
131 print()
132 
133 """
134 res下面的内容,1比对icon,2比对appName
135 """
136 asIconsDict = {}
137 targetIconsDict = {}
138 for root,dirs,files in os.walk(asprojectfile_res):
139     for name in dirs:
140         pass
141     for name in files:
142         fullpath = os.path.join(root, name)
143         arr = fullpath.split("\\")
144         if  iconName ==  arr[len(arr) - 1]:
145             dirName = arr[len(arr) - 2]
146             dirName = dirName.replace("drawable","mipmap",1)
147             asIconsDict[dirName] = (utils.file_md5(os.path.join(root, name))[0],fullpath)
148         else :
149             pass
150 #print(asIconsDict)
151 #遍历目标文件的res文件
152 for root,dirs,files in os.walk(targetProjectfile_res):
153     for name in dirs:
154         pass
155         #print("A",os.path.join(root,name))
156     for name in files:
157         fullpath = os.path.join(root, name)
158         arr = fullpath.split("\\")
159         if  iconName ==  arr[len(arr) - 1]:
160             # print(arr[len(arr) - 2])
161             dirName = arr[len(arr) - 2]
162             targetIconsDict[dirName] = (utils.file_md5(os.path.join(root, name))[0],fullpath)
163         else :
164             pass
165 #print(targetIconsDict)
166 
167 #ValueError: too many values to unpack(expected 3)  没有加items()
168 defalutTip = "NONE"
169 for key,value in asIconsDict.items():
170     ti = targetIconsDict.get(key,defalutTip)
171     # as文件中有一个文件夹,目标工程中没有这个文件夹,提示,并拷贝
172     if ti == defalutTip:
173         aspath = value[1]
174         asarr = aspath.split("\\")
175         folderName = asarr[len(asarr)-2]
176         folderName = folderName.replace("drawable","mipmap",1)
177         # 第一种情况  没有mipmap-?hdp1文件
178         if not os.path.exists(targetProjectfile_res +"\\" +folderName):
179             os.mkdir(targetProjectfile_res +"\\" +folderName)
180         # 第二种情况  mipmap-?hdpi文件中没有改文件
181         print(value[1])
182         print(targetProjectfile_res +"\\" +folderName+"\\"+asarr[len(asarr)-1])
183         shutil.copyfile(value[1],targetProjectfile_res +"\\" +folderName+"\\"+asarr[len(asarr)-1] )
184         print("target文件夹中没有"+value[1]+"已经拷贝")
185     #有的话判断icon的MD5,看是不是同一张图片
186     else :
187         #如果是同一张图片,忽略
188         if value[0] == ti[0]:
189             pass
190         #如果不是同一张图片,提示并覆盖
191         else :
192             shutil.copyfile(value[1], ti[1])
193             ti = key,"中icon文件与不一致,已替换"
194             print(ti)
195 
196 print()
197 print("---------compare icon and appName finish--------------")
198 
199 print("----------collating jinLibs and assets file-------------")
200 print()
201 
202 """
203 jniLibs下面的文件
204 """
205 for root, dirs, files in os.walk(asprojectfile_so):
206     for name in dirs:
207         if not os.path.exists(targetProjectfile_libs+"\\"+name):
208             os.mkdir(targetProjectfile_libs+"\\"+name)
209     for name in files:
210         fullpath = os.path.join(root, name)
211         libarr = fullpath.split("\\")
212         if utils.file_md5(os.path.join(root, name))[0] != utils.file_md5(targetProjectfile_so + "\\" + libarr[len(libarr) - 2] + "\\" + name)[0]:
213             shutil.copyfile(os.path.join(root, name),
214                             targetProjectfile_so + "\\" + libarr[len(libarr) - 2] + "\\" + name)
215 
216 
217 """
218 assets下面的文件
219 """
220 ###
221 ###新马assets下面的保护文件 www, plugin_config.xml package_config.json globalizationLang.json
222 ###
223 #如果没有这个文件夹会报错
224 # shutil.rmtree(targetProjectfile_assets)  # 递归删除文件夹
225 if not os.path.exists(targetProjectfile_assets):
226     os.makedirs(targetProjectfile_assets)
227 else :
228     for root, dirs, files in os.walk(targetProjectfile_assets):
229         for name in dirs:
230             filePath = os.path.join(root, name)
231             if not name == "www" :
232                 if not "\\assets\\www\\" in filePath:
233                     dirPath = os.path.join(root, name)
234                     shutil.rmtree(dirPath)
235         for name in files:
236             if not name == "plugin_config.xml" and not name == "package_config.json" and not name == "globalizationLang.json":
237                 filePath = os.path.join(root, name)
238                 if not "\\assets\\www\\" in filePath:
239                     os.remove(filePath)
240 
241 
242 utils.copyd(asprojectfile_assets,targetProjectfile_assets)
243 
244 print()
245 print("-----------collate jinLibs and assets file finish--------------")
246 
247 
248 print("-----------building apk-----------")
249 print()
250 
251 """
252 编译出apk
253 """
254 #gradlew assembleRelease
255 
256 verList = utils.rw_vconfig_autoincrement(versionConfig,auIncreVer)
257 os.chdir(targetGradle)
258 
259 if packageFlavor == "googleAll":
260     buildApkCmd = "gradlew assemblegoogle -PversionCode=%s -PversionName=%s" % (verList[0], verList[1])
261 elif packageFlavor == "googleRelease":
262     buildApkCmd = "gradlew assemblegoogleRelease -PversionCode=%s -PversionName=%s" % (verList[0], verList[1])
263 elif packageFlavor == "guanwangAll":
264     buildApkCmd = "gradlew assembleguanwang -PversionCode=%s -PversionName=%s" % (verList[0], verList[1])
265 elif packageFlavor == "guanwangRelease":
266     buildApkCmd = "gradlew assembleguanwangRelease -PversionCode=%s -PversionName=%s" % (verList[0], verList[1])
267 buildApkCmd = buildApkCmd + " --info"
268 statusEnd = utils.subprocess_return(buildApkCmd)
269 print(statusEnd)
270 if statusEnd != 0:
271     utils.showlog_buildfailed(Unitylogfile)
272 
273 print()
274 print("-----------build apk over-----------")
275 
276 print("------------begin 360 jiagu--------------")
277 print()
278 
279 print()
280 print("------------360 jiagu finish--------------")
281 
282 
283 
284 
285 
286 # shutil.copyfile(defaltOutputApk,outputName)
287 #加固
288 print("---------360jiagu start------------")
289 ###打出来4个包
290 #|--google
291 #|-----debug
292 #|-----release
293 #|--guanwang
294 #|-----debug
295 #|-----release
296 defaltOutputApk = targetproject+"\\build\\outputs\\apk\\"
297 nowTime = time.strftime("%m-%d_%H-%M", time.localtime())
298 outputName = svnPath+"\\"+nowTime+"_"+showName
299 
300 print()
301 if packageFlavor == "googleAll":
302     apk1 = defaltOutputApk + "google\\debug\\app-google-debug.apk"
303     apk2 = defaltOutputApk + "google\\release\\app-google-release.apk"
304     defaltOutputApk = [apk1,apk2]
305     out1 = (outputName + "google-debug.apk").replace(" ","")
306     out2 = (outputName + "google-release.apk").replace(" ","")
307     outputName = [out1,out2];
308 elif packageFlavor == "googleRelease":
309     defaltOutputApk = defaltOutputApk + "google\\release\\app-google-release.apk"
310     outputName = (outputName + "google-release.apk").replace(" ", "")
311 elif packageFlavor == "guanwangAll":
312     apk1 = defaltOutputApk + "guanwang\\debug\\app-guanwang-debug.apk"
313     apk2 = defaltOutputApk + "guanwang\\release\\app-guanwang-release.apk"
314     defaltOutputApk = [apk1, apk2]
315     out1 = (outputName + "guanwang-debug.apk").replace(" ", "")
316     out2 = (outputName + "guanwang-release.apk").replace(" ", "")
317     outputName = [out1, out2];
318 elif packageFlavor == "guanwangRelease":
319     defaltOutputApk = defaltOutputApk + "guanwang\\release\\app-guanwang-release.apk"
320     outputName = (outputName + "guanwang-release.apk").replace(" ", "")
321 
322 
323 
324 print(outputName)
325 
326 if not type(defaltOutputApk) is list:
327     a360syb.begin(defaltOutputApk,outputName)
328 else:
329     for i in range(len(defaltOutputApk)) :
330         a360syb.begin(defaltOutputApk[i], outputName[i])
331 
332 
333 print()


评论


亲,登录后才可以留言!