app-auto-release.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. # -*- coding:utf-8 -*-
  2. # 请使用Python 2.7版本运行;
  3. from __future__ import unicode_literals
  4. import os
  5. import re # 正则表达式;
  6. import sys
  7. #reload(sys)
  8. #sys.setdefaultencoding('utf-8')
  9. import time
  10. import datetime
  11. import shutil
  12. from basessh2 import baseSSH2
  13. import subprocess
  14. import xlrd
  15. import xlwt
  16. from xlwt import XFStyle, Pattern
  17. import win_subprocess # 此版本对应宽字节,subprocess为acssi;
  18. import shutil
  19. def copyfile(src_file, dest_file):
  20. shutil.copy(src_file, dest_file)
  21. def copyfolder(src_folder, dest_folder):
  22. if src_folder.endswith(".apk"):
  23. copyfile(src_folder, dest_folder)
  24. else:
  25. src_files = os.listdir(src_folder)
  26. # 目标路径是否存在,不存在创建;
  27. if not os.path.exists(dest_folder):
  28. os.mkdirs(dest_folder)
  29. for name in src_files:
  30. copyfile(src_folder+"\\"+name, dest_folder+"\\"+name)
  31. # 不使用重定向;
  32. def cmdExecute2(cmd):
  33. # 定义文件名称;
  34. file_name = str(time.time())
  35. # 输出到文件中;
  36. cmd = cmd + ' >> ' + file_name
  37. print u'执行cmd:', cmd
  38. proc = subprocess.Popen(cmd, shell=True)
  39. # 等待完成;
  40. proc.wait()
  41. # 读取文件内容;
  42. data = ''
  43. with open(file_name, mode="rb") as f:
  44. data = f.read()
  45. os.remove(file_name)
  46. print u"cmd结果:", data
  47. return data
  48. def cmdExecute(cmd):
  49. print u'执行cmd:', cmd
  50. proc = win_subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  51. # 等待完成;
  52. stdout, stderr = proc.communicate()
  53. if proc.returncode == 0:
  54. print u'执行成功'
  55. # 返回执行结果;
  56. # print u"cmdExecute结果:%s" % stdout
  57. return stdout
  58. class ExcelParser:
  59. def __init__(self, excelPath):
  60. self.__xlspath = excelPath
  61. self.xlsData = []
  62. def readExcel(self, excelPath=None):
  63. if excelPath is not None:
  64. if type(excelPath) == str:
  65. self.__xlspath = excelPath.decode('utf-8')
  66. '文件是否存在'
  67. if not os.path.exists(self.__xlspath):
  68. return False
  69. '打开excel文件'
  70. wb = xlrd.open_workbook(filename=self.__xlspath)
  71. if wb is None:
  72. return False
  73. '获取所有sheet'
  74. sheet = None
  75. for item in wb.sheet_names():
  76. sheet = wb.sheet_by_name(item)
  77. self.paserExcel(sheet)
  78. def paserExcel(self, sheet):
  79. if sheet.name == "release":
  80. for i in range(1, sheet.nrows):
  81. rowDict = {}
  82. '获取每行内容:url\版本号\debug svn revision\src svn revision\是否释放'
  83. rowData = tuple(sheet.row_values(i))
  84. if rowData.__len__() == 5:
  85. if rowData[0].__len__() > 0:
  86. # 需要去除空格;
  87. rowDict['url'] = rowData[0].strip()
  88. rowDict['apk_version'] = str(rowData[1]).strip()
  89. rowDict['apk_revision'] = str(rowData[2]).strip('.0')
  90. rowDict['src_revision'] = str(rowData[3]).strip('.0')
  91. rowDict['sqa_result'] = rowData[4].strip('.0')
  92. self.xlsData.append(rowDict)
  93. # endif
  94. # endif
  95. # endfor
  96. else:
  97. print u"未找到对应的sheet名称:release"
  98. # 远程服务器SVN操作;
  99. class remoteSVN:
  100. def __init__(self, host, user, pwd):
  101. self.__user = user
  102. self.__pwd = pwd
  103. self.__host = host
  104. self.__ssh2 = baseSSH2()
  105. self.__ssh2.init_ssh2(user, pwd, host)
  106. # 获取指定版本信息;
  107. def getRevisionInfo(self, revision, url):
  108. cmd = 'svn info -r %s %s' % (revision, url)
  109. return self.__ssh2.execute_cmd(cmd)
  110. # 获取指定版本log;
  111. def getRevisionLog(self, revision, url):
  112. cmd = 'svn log -r %s %s' % (revision, url)
  113. return self.__ssh2.execute_cmd(cmd)
  114. # 更新指定目录;
  115. def update(self, dir, revision=''):
  116. if revision.__len__() > 0:
  117. cmd = 'svn up -r %s %s' % (revision, dir)
  118. else:
  119. cmd = 'svn up %s' % (dir)
  120. return self.__ssh2.execute_cmd(cmd)
  121. # 提交指定目录;
  122. def commit(self):
  123. pass
  124. # 本地SVN操作,必须安装命令行;
  125. class localSVN:
  126. def __init__(self):
  127. print 'local svn'
  128. def revisionInfo(self, revision, url):
  129. cmd = 'svn info -r %s %s' % (revision, url)
  130. return cmdExecute(cmd)
  131. def revisionLog(self, revision, url):
  132. cmd = 'svn log -r %s %s' % (revision, url)
  133. return cmdExecute(cmd)
  134. def checkout(self, dir, url, revision=''):
  135. # dir中文必须是unicode的转gbk;
  136. if revision.__len__() > 0:
  137. cmd = 'svn co -r %s %s %s' % (revision, url, dir)
  138. else:
  139. cmd = 'svn co %s %s' % (url, dir)
  140. return cmdExecute(cmd)
  141. def export(self, dir, url, revision=''):
  142. # dir中文必须是unicode的转gbk;
  143. if revision.__len__() > 0:
  144. cmd = 'svn export -r %s %s %s' % (revision, url, dir)
  145. else:
  146. cmd = 'svn export %s %s' % (url, dir)
  147. return cmdExecute(cmd)
  148. def update(self, dir, revision=''): # revision只有根目录才有效,即有.svn的目录才有效;
  149. dir = dir.replace('\\', '/')
  150. # dir中文必须是unicode的转gbk;
  151. if revision.__len__() > 0:
  152. cmd = 'svn up %s -r %s' % (dir, revision)
  153. else:
  154. cmd = 'svn up %s' % (dir)
  155. return cmdExecute(cmd)
  156. def revert(self, dir, revision=''):
  157. # dir中文必须是unicode的转gbk;
  158. if revision.__len__() > 0:
  159. cmd = 'svn revert -r %s %s' % (revision, dir)
  160. else:
  161. cmd = 'svn revert %s' % (dir)
  162. return cmdExecute(cmd)
  163. def add(self, file):
  164. # file中文必须是unicode的转gbk;
  165. cmd = 'svn add %s' % (file)
  166. return cmdExecute(cmd)
  167. def commit(self, file, desc):
  168. # file/desc中文必须是unicode的转gbk;
  169. cmd = "svn commit -m %s %s" % (desc, file)
  170. return cmdExecute(cmd)
  171. def status(self, file):
  172. cmd = "svn status %s"%(file)
  173. msg = cmdExecute(cmd)
  174. msg = msg.decode('gbk') #要将unicode转gbk
  175. if msg.startswith("?"): # 不在控制;
  176. return 0
  177. elif msg.startswith("A"): # 预加入;
  178. return 1
  179. elif msg.startswith("M"): # 已修改;
  180. return 2
  181. elif msg.startswith("C"): # 冲突;
  182. return 3
  183. elif msg.startswith("K"): # 被锁定;
  184. return 4
  185. if __name__ == "__main__":
  186. print "start main"
  187. lsvn = localSVN()
  188. # 注意:中文字符串,必须加u表示unicode;
  189. debug_dir = u"F:\\Moka-Code\\APK自动编译相关\\debug"
  190. release_dir = u"F:\\Moka-Code\\APK自动编译相关\\release"
  191. excelPath = u"F:\\Moka-Code\\APK自动编译相关\\apk-release.xlsx"
  192. # url地址;
  193. debug_url = u"https://odm-design-center-hz.tclking.com/svn/scbc_apps/trunk/app/apk/01debug/general"
  194. release_url = u"https://odm-design-center-hz.tclking.com/svn/scbc_apps/trunk/app/apk/02release/general"
  195. '无则下载有则更新'
  196. if os.path.exists(debug_dir + "\\.svn"):
  197. lsvn.update(debug_dir)
  198. else:
  199. lsvn.checkout(debug_dir, debug_url)
  200. '无则下载有则更新'
  201. if os.path.exists(release_dir + "\\.svn"):
  202. lsvn.update(release_dir)
  203. else:
  204. lsvn.checkout(release_dir, release_url)
  205. '读取excel表记录'
  206. excel = ExcelParser(excelPath)
  207. excel.readExcel()
  208. print excel.xlsData
  209. for item in excel.xlsData:
  210. if item['sqa_result'] == u"PASS":
  211. '获取apk名称'
  212. apk_name = item['url'][debug_url.__len__() + 1:]
  213. '更新到释放的版本'
  214. lsvn.update(debug_dir + "\\" + apk_name, item['apk_revision'])
  215. '复制到release目录'
  216. copyfolder(debug_dir + "\\" + apk_name, release_dir + "\\" + apk_name)
  217. '获取日志'
  218. log = lsvn.revisionLog(item['apk_revision'], item['url']).decode('gbk')
  219. listInfo = log.split("\r\n")
  220. message = listInfo[3]
  221. '获取状态'
  222. ret = lsvn.status(release_dir + "\\" + apk_name)
  223. if ret == 0:
  224. '添加并提交'
  225. lsvn.add(release_dir + "\\" + apk_name)
  226. lsvn.commit(release_dir + "\\" + apk_name, message)
  227. elif ret == 1 or ret == 2:
  228. lsvn.commit(release_dir + "\\" + apk_name, message)
  229. else:
  230. print "不受控,无法提交"
  231. # endif
  232. # endfor