cmd_remotebuild.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #!/usr/bin/python -tt
  2. # vim: ai ts=4 sts=4 et sw=4
  3. #
  4. # Copyright (c) 2011 Intel, Inc.
  5. #
  6. # This program is free software; you can redistribute it and/or modify it
  7. # under the terms of the GNU General Public License as published by the Free
  8. # Software Foundation; version 2 of the License
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. # for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License along
  16. # with this program; if not, write to the Free Software Foundation, Inc., 59
  17. # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. """Implementation of subcmd: build
  19. """
  20. import os
  21. import glob
  22. from gitbuildsys import utils
  23. from gitbuildsys.errors import Usage, ObsError, GbsError
  24. from gitbuildsys.conf import configmgr, encode_passwd
  25. from gitbuildsys.oscapi import OSC, OSCError
  26. from gitbuildsys.cmd_export import export_sources, get_packaging_dir
  27. from gitbuildsys.cmd_build import get_profile
  28. from gitbuildsys.log import LOGGER as log
  29. from gitbuildsys.log import DEBUG
  30. import gbp.rpm
  31. from gbp.rpm.git import GitRepositoryError, RpmGitRepository
  32. from gbp.errors import GbpError
  33. OSCRC_TEMPLATE = """[general]
  34. apiurl = %(apiurl)s
  35. plaintext_passwd=0
  36. use_keyring=0
  37. http_debug = %(http_debug)s
  38. debug = %(debug)s
  39. gnome_keyring=0
  40. [%(apiurl)s]
  41. user=%(user)s
  42. passx=%(passwdx)s
  43. """
  44. def main(args):
  45. """gbs remotebuild entry point."""
  46. obsconf = get_profile(args).obs
  47. if not obsconf or not obsconf.url:
  48. raise GbsError('no obs api found, please add it to gbs conf '
  49. 'and try again')
  50. apiurl = obsconf.url
  51. if not apiurl.user:
  52. raise GbsError('empty user is not allowed for remotebuild, please '\
  53. 'add user/passwd to gbs conf, and try again')
  54. if args.commit and args.include_all:
  55. raise Usage('--commit can\'t be specified together with '
  56. '--include-all')
  57. obs_repo = args.repository
  58. obs_arch = args.arch
  59. if args.buildlog and None in (obs_repo, obs_arch):
  60. raise GbsError('please specify arch(-A) and repository(-R)')
  61. try:
  62. repo = RpmGitRepository(args.gitdir)
  63. except GitRepositoryError, err:
  64. raise GbsError(str(err))
  65. workdir = repo.path
  66. utils.read_localconf(workdir)
  67. if not (args.buildlog or args.status):
  68. utils.git_status_checker(repo, args)
  69. packaging_dir = get_packaging_dir(args)
  70. if args.commit:
  71. commit = args.commit
  72. elif args.include_all:
  73. commit = 'WC.UNTRACKED'
  74. else:
  75. commit = 'HEAD'
  76. relative_spec = utils.guess_spec(workdir, packaging_dir,
  77. args.spec, commit)[0]
  78. if args.include_all:
  79. # include_all means to use work copy,
  80. # otherwise use the reversion in git history
  81. spec_to_parse = os.path.join(workdir, relative_spec)
  82. else:
  83. content = utils.show_file_from_rev(workdir, relative_spec, commit)
  84. if content is None:
  85. raise GbsError('failed to checkout %s from commit: %s' %
  86. (relative_spec, commit))
  87. tmp_spec = utils.Temp(content=content)
  88. spec_to_parse = tmp_spec.path
  89. # get 'name' and 'version' from spec file
  90. try:
  91. spec = gbp.rpm.SpecFile(spec_to_parse)
  92. except GbpError, err:
  93. raise GbsError('%s' % err)
  94. if not spec.name:
  95. raise GbsError("can't get correct name.")
  96. package = spec.name
  97. base_prj = None
  98. if args.base_obsprj:
  99. base_prj = args.base_obsprj
  100. elif obsconf.base:
  101. base_prj = obsconf.base
  102. if args.target_obsprj is None:
  103. if obsconf.target:
  104. target_prj = obsconf.target
  105. else:
  106. target_prj = "home:%s:gbs" % apiurl.user
  107. if base_prj:
  108. target_prj += ":%s" % base_prj
  109. else:
  110. target_prj = args.target_obsprj
  111. api_passwd = apiurl.passwd if apiurl.passwd else ''
  112. # Create temporary oscrc
  113. oscrc = OSCRC_TEMPLATE % {
  114. "http_debug": 1 if log.level == DEBUG else 0,
  115. "debug": 1 if log.level == DEBUG else 0,
  116. "apiurl": apiurl,
  117. "user": apiurl.user,
  118. "passwdx": encode_passwd(api_passwd),
  119. }
  120. tmpdir = configmgr.get('tmpdir', 'general')
  121. tmpd = utils.Temp(prefix=os.path.join(tmpdir, '.gbs_remotebuild_'),
  122. directory=True)
  123. exportdir = tmpd.path
  124. tmpf = utils.Temp(dirn=exportdir, prefix='.oscrc', content=oscrc)
  125. oscrcpath = tmpf.path
  126. api = OSC(apiurl, oscrc=oscrcpath)
  127. try:
  128. if args.buildlog:
  129. archlist = []
  130. status = api.get_results(target_prj, package)
  131. for build_repo in status.keys():
  132. for arch in status[build_repo]:
  133. archlist.append('%-15s%-15s' % (build_repo, arch))
  134. if not obs_repo or not obs_arch or obs_repo not in status.keys() \
  135. or obs_arch not in status[obs_repo].keys():
  136. raise GbsError('no valid repo / arch specified for buildlog, '\
  137. 'valid arguments of repo and arch are:\n%s' % \
  138. '\n'.join(archlist))
  139. if status[obs_repo][obs_arch] not in ['failed', 'succeeded',
  140. 'building', 'finishing']:
  141. raise GbsError('build status of %s for %s/%s is %s, '\
  142. 'no build log.' % (package, obs_repo, obs_arch,
  143. status[obs_repo][obs_arch]))
  144. log.info('build log for %s/%s/%s/%s' % (target_prj, package,
  145. obs_repo, obs_arch))
  146. print api.get_buildlog(target_prj, package, obs_repo, obs_arch)
  147. return 0
  148. if args.status:
  149. results = []
  150. status = api.get_results(target_prj, package)
  151. for build_repo in status.keys():
  152. for arch in status[build_repo]:
  153. stat = status[build_repo][arch]
  154. results.append('%-15s%-15s%-15s' % (build_repo, arch, stat))
  155. if results:
  156. log.info('build results from build server:\n%s' \
  157. % '\n'.join(results))
  158. else:
  159. log.info('no build results from build server')
  160. return 0
  161. except OSCError, err:
  162. raise GbsError(str(err))
  163. with utils.Workdir(workdir):
  164. export_sources(repo, commit, exportdir, relative_spec, args)
  165. try:
  166. commit_msg = repo.get_commit_info(args.commit or 'HEAD')['subject']
  167. except GitRepositoryError, exc:
  168. raise GbsError('failed to get commit info: %s' % exc)
  169. files = glob.glob("%s/*" % exportdir)
  170. build_repos = None
  171. try:
  172. log.info('checking status of obs project: %s ...' % target_prj)
  173. if not api.exists(target_prj):
  174. log.info('creating new project %s' % (target_prj))
  175. api.create_project(target_prj, base_prj)
  176. else:
  177. build_repos = api.get_repos_of_project(target_prj)
  178. if not build_repos:
  179. log.warning("no available build repos for %s" % target_prj)
  180. if api.exists(target_prj, package):
  181. _old, _not_changed, changed, new = api.diff_files(target_prj,
  182. package, files)
  183. commit_files = changed + new
  184. else:
  185. log.info('creating new package %s/%s' % (target_prj, package))
  186. api.create_package(target_prj, package)
  187. # new project - submitting all local files
  188. commit_files = files
  189. except OSCError, err:
  190. raise GbsError(str(err))
  191. if not commit_files:
  192. if build_repos:
  193. log.warning("no local changes found. Triggering rebuild")
  194. api.rebuild(target_prj, package, obs_arch)
  195. else:
  196. log.warning("no local changes found. can't trigger rebuild "
  197. "as no available build repos found")
  198. return 0
  199. else:
  200. log.info('commit packaging files to build server ...')
  201. commit_files = [(fpath, fpath in commit_files) for fpath in files]
  202. try:
  203. api.commit_files(target_prj, package, commit_files, commit_msg)
  204. except ObsError as exc:
  205. raise GbsError('commit packages fail: %s, please check the '
  206. 'permission of target project:%s' % (exc, target_prj))
  207. log.info('local changes submitted to build server successfully')
  208. log.info('follow the link to monitor the build progress:\n'
  209. ' %s/package/show?package=%s&project=%s' \
  210. % (apiurl.replace('api', 'build'), package, target_prj))