app-auto-release.py 8.5 KB

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