1 | #!/usr/bin/env python |
---|
2 | |
---|
3 | import argparse |
---|
4 | from csv import DictReader |
---|
5 | from glob import glob |
---|
6 | import logging |
---|
7 | import os |
---|
8 | from pprint import pprint,pformat |
---|
9 | import jenkinsapi.custom_exceptions |
---|
10 | from jenkinsapi.jenkins import Jenkins |
---|
11 | import shlex |
---|
12 | import subprocess |
---|
13 | import sys |
---|
14 | import xml.etree.ElementTree as etree |
---|
15 | |
---|
16 | |
---|
17 | destdir="" |
---|
18 | |
---|
19 | class STATE: |
---|
20 | disabled="DISABLED" |
---|
21 | unknown="UNKNOWN" |
---|
22 | pending="PENDING" |
---|
23 | failed="FAILED" |
---|
24 | succeeded="SUCCEEDED" |
---|
25 | |
---|
26 | def write_status(obs, jenkins_status): |
---|
27 | filename = "status.succeeded" |
---|
28 | status = STATE.succeeded |
---|
29 | component="" |
---|
30 | if obs.get_state() != STATE.succeeded and obs.get_state() != STATE.disabled: |
---|
31 | component = "obs" |
---|
32 | status = obs.get_state() |
---|
33 | elif jenkins_status['status'] != STATE.succeeded and jenkins_status['status'] != STATE.disabled: |
---|
34 | component = "jenkins" |
---|
35 | status = jenkins_status['status'] |
---|
36 | |
---|
37 | if component: |
---|
38 | filename="status." + status.lower() + "." + component |
---|
39 | |
---|
40 | if destdir: |
---|
41 | filepath=destdir + "/" + filename |
---|
42 | out=open(filepath, 'w') |
---|
43 | logger.info("status will be written to " + filepath) |
---|
44 | # remove outdated files |
---|
45 | for i in glob(destdir + "/status*"): |
---|
46 | if not os.path.samefile(i, filepath): |
---|
47 | logger.debug("remove outdated status file " + i) |
---|
48 | os.remove(i) |
---|
49 | else: |
---|
50 | out=sys.stdout |
---|
51 | |
---|
52 | out.write( "#\n" ) |
---|
53 | out.write( "STATUS="+status+"\n" ) |
---|
54 | out.write( "#\n" ) |
---|
55 | out.write( "NAME="+filename+"\n" ) |
---|
56 | obs_status = obs.get_status() |
---|
57 | for key in sorted(obs_status): |
---|
58 | out.write( "#\n" ) |
---|
59 | if key == "status": |
---|
60 | out.write( "OBS_STATUS" +"="+ obs_status[key] +"\n" ) |
---|
61 | else: |
---|
62 | out.write( "OBS_STATUS_" + key.upper() +"="+",".join(get_repo_list(obs_status[key]))+"\n" ) |
---|
63 | |
---|
64 | out.write( "#\n" ) |
---|
65 | version = obs.get_pkg_info() |
---|
66 | for key in sorted(version): |
---|
67 | out.write( "BUILD_" + key.upper() +"="+str(version[key])+"\n") |
---|
68 | |
---|
69 | out.write( "#\n" ) |
---|
70 | out.write("PACKAGES_SUCCESSFUL='%s'\n" % (get_packages_string(obs.get_successful_packages()))) |
---|
71 | |
---|
72 | out.write( "#\n" ) |
---|
73 | out.write("PACKAGES_FAILED='%s'\n" % (get_packages_string(obs.get_failed_packages()))) |
---|
74 | |
---|
75 | out.write( "#\n" ) |
---|
76 | for key in sorted(jenkins_status): |
---|
77 | out.write( "JENKINS_" + key.upper() +"="+str(jenkins_status[key])+"\n") |
---|
78 | |
---|
79 | |
---|
80 | |
---|
81 | def get_repo_name(repository, arch, jenkins=False): |
---|
82 | # obs: DISTRIBUTION_VERSION |
---|
83 | # jenkins: DISTRIBUTION-VERSION-ARCH |
---|
84 | # |
---|
85 | # use "-" as separator between repository and arch, |
---|
86 | # because repository and arch can contain: |
---|
87 | # repository: "." and "_" (openSUSE_13.1) |
---|
88 | # arch: "_" (x86_64) |
---|
89 | if jenkins: |
---|
90 | repo = str(repository).replace( "_", "-", 1 ) + "-" + str(arch) |
---|
91 | else: |
---|
92 | repo = str(repository) + "-" + str(arch) |
---|
93 | return repo |
---|
94 | |
---|
95 | def get_repo_list(array, jenkins=False): |
---|
96 | result=[] |
---|
97 | for i in sorted( array, key=lambda k: ( k['repository'], k['arch'] ) ): |
---|
98 | repo = get_repo_name(i['repository'], i['arch'], jenkins) |
---|
99 | result.append(repo) |
---|
100 | return result |
---|
101 | |
---|
102 | def get_packages_string(packages): |
---|
103 | pkg = '' |
---|
104 | for dist in packages: |
---|
105 | pkg += '%s:%s\n' % (dist, ','.join(packages[dist])) |
---|
106 | return pkg |
---|
107 | |
---|
108 | class Osc: |
---|
109 | def __init__(self, osc_paramter): |
---|
110 | self.osc="osc" |
---|
111 | self.paramter=osc_paramter |
---|
112 | |
---|
113 | def get_command(self, args): |
---|
114 | return self.__format_command([ self.osc, self.paramter ] + args) |
---|
115 | |
---|
116 | def __format_command(self, cmd): |
---|
117 | logger=logging.getLogger(__name__) |
---|
118 | #logger.debug( "cmd1:" + str(cmd) ) |
---|
119 | cmd2=" ".join( cmd ) |
---|
120 | logger.debug( "cmd2:" + str(cmd2) ) |
---|
121 | cmd3=shlex.split( cmd2 ) |
---|
122 | #logger.debug( "cmd3:" + str(cmd3) ) |
---|
123 | return cmd3 |
---|
124 | |
---|
125 | |
---|
126 | class ObsStatus: |
---|
127 | def __init__(self, osc, prj, pkg): |
---|
128 | self.logger = logging.getLogger() |
---|
129 | self.osc = osc |
---|
130 | self.prj = prj |
---|
131 | self.pkg = pkg |
---|
132 | self.state = STATE.unknown |
---|
133 | self.status = { |
---|
134 | 'broken': [], |
---|
135 | 'building': [], |
---|
136 | 'disabled': [], |
---|
137 | 'failed': [], |
---|
138 | 'finished': [], |
---|
139 | 'other': [], |
---|
140 | 'unresolvable': [], |
---|
141 | } |
---|
142 | self.pkg_info = { |
---|
143 | 'srcmd5': "", |
---|
144 | 'version': "", |
---|
145 | 'rev': -1, |
---|
146 | 'time': "", |
---|
147 | } |
---|
148 | self.packages_successful = {} |
---|
149 | self.packages_failed = {} |
---|
150 | |
---|
151 | #def get_repo_name(self, repository, arch): |
---|
152 | #return get_repo_name(repository, arch, jenkins=False): |
---|
153 | |
---|
154 | def __get_obs_results(self): |
---|
155 | # get results of a project: |
---|
156 | # %(repository)s|%(arch)s|%(state)s|%(dirty)s|%(code)s|%(details)s |
---|
157 | # Debian_5.0|i586|published|False|succeeded| |
---|
158 | # Debian_5.0|x86_64|published|False|succeeded| |
---|
159 | cmd = self.osc.get_command( ["results", "--csv", "--format='%(state)s|%(repository)s|%(arch)s|%(dirty)s|%(code)s|%(details)s'", "--verbose", self.prj, self.pkg] ) |
---|
160 | # "--last-build": NO, because if --last-build, disabled in 'code' is replaced by succeeded/failed |
---|
161 | results=subprocess.Popen( cmd, stdout=subprocess.PIPE) |
---|
162 | rc=results.wait() |
---|
163 | if rc != 0: |
---|
164 | logger.error( "failed to get osc results: " + str(rc) ) |
---|
165 | exit( rc ) |
---|
166 | |
---|
167 | reader = DictReader(results.stdout, |
---|
168 | delimiter='|', |
---|
169 | fieldnames=['state', 'repository', |
---|
170 | 'arch', 'dirty', |
---|
171 | 'code', 'details']) |
---|
172 | return reader |
---|
173 | |
---|
174 | |
---|
175 | def __get_obs_last_build(self, repository, arch): |
---|
176 | # {'rev': '99', 'version': '1.2.1170-1.3', 'srcmd5': '611f626d431d06dc81a32e0e021da0d7', 'time': '2014-03-12 16:43:55'} |
---|
177 | cmd = self.osc.get_command( [ "buildhist", "--csv", self.prj, self.pkg, repository, arch ] ) |
---|
178 | buildhist=subprocess.Popen( cmd, stdout=subprocess.PIPE ) |
---|
179 | rc=buildhist.wait() |
---|
180 | reader={} |
---|
181 | if rc != 0: |
---|
182 | logger.error( "failed: " + rc ) |
---|
183 | else: |
---|
184 | buildhist2 = subprocess.Popen(['tail', '-n', '1'], |
---|
185 | stdin=buildhist.stdout, |
---|
186 | stdout=subprocess.PIPE, |
---|
187 | ) |
---|
188 | reader = DictReader(buildhist2.stdout, |
---|
189 | delimiter='|', |
---|
190 | fieldnames=['time', 'srcmd5', 'rev', 'version']) |
---|
191 | try: |
---|
192 | # there should only be one entry |
---|
193 | return reader.next() |
---|
194 | except StopIteration: |
---|
195 | return |
---|
196 | |
---|
197 | |
---|
198 | def __update_packages(self): |
---|
199 | cmd = self.osc.get_command( [ "results", "--xml", self.prj ] ) |
---|
200 | # "--last-build": NO, because if --last-build, disabled in 'code' is replaced by succeeded/failed |
---|
201 | results=subprocess.Popen(cmd, stdout=subprocess.PIPE) |
---|
202 | #rc=results.wait() |
---|
203 | (xmldata, stderr) = results.communicate() |
---|
204 | rc=results.returncode |
---|
205 | if rc != 0: |
---|
206 | logger.error("failed to get osc results: " + str(rc)) |
---|
207 | return False |
---|
208 | #root = etree.parse(xmldata).getroot() |
---|
209 | root = etree.fromstring(xmldata) |
---|
210 | #print etree.dump(root) |
---|
211 | for result in root.getiterator('result'): |
---|
212 | #print result.attrib |
---|
213 | #print result.attrib['repository'], result.attrib['arch'] |
---|
214 | dist = get_repo_name(result.attrib['repository'], result.attrib['arch'], jenkins=True) |
---|
215 | self.packages_successful[dist] = [] |
---|
216 | self.packages_failed[dist] = [] |
---|
217 | for status in result.getiterator('status'): |
---|
218 | #print status.attrib |
---|
219 | if status.attrib['code'] == 'succeeded': |
---|
220 | self.packages_successful[dist].append(status.attrib['package']) |
---|
221 | elif status.attrib['code'] == 'disabled': |
---|
222 | pass |
---|
223 | else: |
---|
224 | logger.error("%s %s (%s) = %s" % (self.prj, status.attrib['package'], result.attrib['repository'], status.attrib['code'])) |
---|
225 | self.packages_failed[dist].append(status.attrib['package']) |
---|
226 | # if no failed packages are added to the dist, remove the dist |
---|
227 | if not self.packages_failed[dist]: |
---|
228 | del(self.packages_failed[dist]) |
---|
229 | return True |
---|
230 | |
---|
231 | |
---|
232 | def __update_status(self): |
---|
233 | obs_results=self.__get_obs_results() |
---|
234 | |
---|
235 | for i in obs_results: |
---|
236 | logger.debug( i ) |
---|
237 | if i['state'] == 'published' and i['dirty'] == 'False' and i['code'] == 'succeeded': |
---|
238 | self.status['finished'].append(i) |
---|
239 | elif i['state'] == 'building': |
---|
240 | self.status['building'].append(i) |
---|
241 | elif i['code'] == 'disabled': |
---|
242 | self.status['disabled'].append(i) |
---|
243 | elif i['code'] == 'failed': |
---|
244 | self.status['failed'].append(i) |
---|
245 | elif i['code'] == 'broken': |
---|
246 | self.status['broken'].append(i) |
---|
247 | elif i['code'] == 'unresolvable': |
---|
248 | self.status['unresolvable'].append(i) |
---|
249 | else: |
---|
250 | self.status['other'].append(i) |
---|
251 | return True |
---|
252 | |
---|
253 | |
---|
254 | def __update_pkg_info(self): |
---|
255 | rv=[] |
---|
256 | # get max 'rev' and 'time' from finished builds |
---|
257 | for i in self.status['finished']: |
---|
258 | last_build=self.__get_obs_last_build(i['repository'], i['arch']) |
---|
259 | self.logger.debug( str(last_build) ) |
---|
260 | #rv.append( dict(i.items() + j.items() ) ) |
---|
261 | if last_build: |
---|
262 | rev=int(last_build['rev']) |
---|
263 | time=last_build['time'].replace(" ","_") |
---|
264 | if ( rev > self.pkg_info['rev'] ) or ( rev == self.pkg_info['rev'] and time > self.pkg_info['time'] ): |
---|
265 | self.pkg_info['rev'] = rev |
---|
266 | self.pkg_info['time'] = time |
---|
267 | self.pkg_info['srcmd5'] = last_build['srcmd5'] |
---|
268 | self.pkg_info['version'] = last_build['version'] |
---|
269 | rv.append( { 'result': i, 'buildhist': last_build } ) |
---|
270 | else: |
---|
271 | self.logger.warn( "no buildhistory definied for " + i['repository'] + "-" + i['arch'] ) |
---|
272 | self.logger.debug( "result (max): " + str(self.pkg_info) ) |
---|
273 | |
---|
274 | for i in rv: |
---|
275 | if int(i['buildhist']['rev']) != self.pkg_info['rev']: |
---|
276 | self.logger.error( "UNKNOWN: " + pformat( i ) ) |
---|
277 | self.logger.debug( "finished:" ) |
---|
278 | for i in rv: |
---|
279 | if int(i['buildhist']['rev']) == self.pkg_info['rev']: |
---|
280 | self.logger.debug( pformat( i ) ) |
---|
281 | return True |
---|
282 | |
---|
283 | |
---|
284 | def __update_state(self): |
---|
285 | if self.status['building'] or self.status['other']: |
---|
286 | self.state = STATE.pending |
---|
287 | elif self.status['failed'] or self.status['broken'] or self.status['unresolvable'] or self.packages_failed: |
---|
288 | self.state = STATE.failed |
---|
289 | else: |
---|
290 | self.state = STATE.succeeded |
---|
291 | return True |
---|
292 | |
---|
293 | |
---|
294 | def update(self): |
---|
295 | self.__update_status() |
---|
296 | self.__update_packages() |
---|
297 | self.__update_pkg_info() |
---|
298 | self.__update_state() |
---|
299 | return True |
---|
300 | |
---|
301 | def get_state(self): |
---|
302 | return self.state |
---|
303 | |
---|
304 | def get_status(self, statustype=None): |
---|
305 | result = None |
---|
306 | if statustype == None: |
---|
307 | result = self.status |
---|
308 | else: |
---|
309 | result = self.status[statustype] |
---|
310 | return result |
---|
311 | |
---|
312 | def get_pkg_info(self): |
---|
313 | return self.pkg_info |
---|
314 | |
---|
315 | def get_pkg_version(self): |
---|
316 | return self.pkg_info['version'] |
---|
317 | |
---|
318 | def get_successful_packages(self): |
---|
319 | return self.packages_successful |
---|
320 | |
---|
321 | def get_failed_packages(self): |
---|
322 | return self.packages_failed |
---|
323 | |
---|
324 | |
---|
325 | class JenkinsTrigger: |
---|
326 | def __init__(self, url, jobname, obs): |
---|
327 | self.logger = logging.getLogger() |
---|
328 | self.url = url |
---|
329 | self.jobname = jobname |
---|
330 | self.obs = obs |
---|
331 | self.status = { |
---|
332 | 'status': STATE.unknown, |
---|
333 | 'jobname': jobname, |
---|
334 | } |
---|
335 | self.jenkins = Jenkins(self.url) |
---|
336 | # J.keys() # Jenkins objects appear to be dict-like, mapping keys (job-names) to |
---|
337 | #['foo', 'test_jenkinsapi'] |
---|
338 | self.job = self.jenkins.get_job(jobname) |
---|
339 | |
---|
340 | self.distreleases = get_repo_list(self.obs.get_status('finished'), jenkins=True) |
---|
341 | self.version = self.obs.get_pkg_info() |
---|
342 | |
---|
343 | self.project_packages = get_packages_string(self.obs.get_successful_packages()) |
---|
344 | |
---|
345 | |
---|
346 | def __add_jenkins_build_parameter(self, xmlConfig, build_params_add): |
---|
347 | # check, if build_params_add are already parameter of Jenkins job |
---|
348 | for child in xmlConfig.findall("./properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition"): |
---|
349 | name=child.find('name').text |
---|
350 | if name in build_params_add.keys(): |
---|
351 | # remove item from configuration parameter |
---|
352 | self.logger.debug( "build parameter " + name + " already in jenkins build configuration" ) |
---|
353 | build_params_add.pop( name ) |
---|
354 | |
---|
355 | #etree.dump( xmlConfig ) |
---|
356 | |
---|
357 | # add remaining build parameter |
---|
358 | parameterDefinitions = xmlConfig.find("./properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions") |
---|
359 | |
---|
360 | if len(parameterDefinitions) == 0: |
---|
361 | self.logger.error( "no jenkins build paramter defined. This should not happen. Skipping adding build parameter" ) |
---|
362 | return |
---|
363 | |
---|
364 | #etree.dump( parameterDefinitions ) |
---|
365 | |
---|
366 | for item in build_params_add: |
---|
367 | self.logger.debug( "add build parameter " + str(item) ) |
---|
368 | # example: |
---|
369 | #<hudson.model.StringParameterDefinition> |
---|
370 | #<name>BUILD_VERSION</name> |
---|
371 | #<description>automatically set by obs-status</description> |
---|
372 | #<defaultValue /> |
---|
373 | #</hudson.model.StringParameterDefinition> |
---|
374 | new = etree.Element('hudson.model.StringParameterDefinition') |
---|
375 | |
---|
376 | # add name |
---|
377 | name = etree.Element( 'name' ) |
---|
378 | name.text = item |
---|
379 | new.append(name) |
---|
380 | |
---|
381 | # add description |
---|
382 | description = etree.Element( 'description' ) |
---|
383 | description.text = "BUILD parameter, required by and added from repo-status" |
---|
384 | new.append(description) |
---|
385 | |
---|
386 | # add defaultValue |
---|
387 | defaultValue = etree.Element( 'defaultValue' ) |
---|
388 | # no default value |
---|
389 | new.append(defaultValue) |
---|
390 | |
---|
391 | parameterDefinitions.append(new) |
---|
392 | return |
---|
393 | |
---|
394 | |
---|
395 | def __get_jenkins_build_parameter(self, parameter): |
---|
396 | try: |
---|
397 | build=self.job.get_last_build() |
---|
398 | parameters = build.get_actions()['parameters'] |
---|
399 | for i in parameters: |
---|
400 | if i['name'] == parameter: |
---|
401 | return i['value'] |
---|
402 | except jenkinsapi.custom_exceptions.NoBuildData: |
---|
403 | pass |
---|
404 | logger.warn( "jenkins build parameter " + parameter + " not defined" ) |
---|
405 | return |
---|
406 | |
---|
407 | |
---|
408 | def __set_jenkins_matrix_distrelease(self, xmlConfig): |
---|
409 | for child in xmlConfig.findall("./axes/hudson.matrix.TextAxis"): |
---|
410 | name=child.find('name').text |
---|
411 | if name == "DISTRELEASE": |
---|
412 | #etree.dump( child ) |
---|
413 | values=child.find('values') |
---|
414 | for value in child.findall('values/string'): |
---|
415 | logger.debug( "distrelease old: " + value.text ) |
---|
416 | values.remove( value ) |
---|
417 | for i in self.distreleases: |
---|
418 | new = etree.Element('string') |
---|
419 | new.text=i |
---|
420 | values.append( new ) |
---|
421 | #etree.dump( child ) |
---|
422 | #print "new:" |
---|
423 | for value in child.findall('values/string'): |
---|
424 | self.logger.debug( "distrelease new: " + str(value.text) ) |
---|
425 | return |
---|
426 | |
---|
427 | |
---|
428 | def checkAndTrigger(self, wait = False): |
---|
429 | self.logger.debug("check_jenkins_status") |
---|
430 | |
---|
431 | try: |
---|
432 | build=self.job.get_last_build() |
---|
433 | self.status['BUILD_NUMBER']=build.get_number() |
---|
434 | self.status['BUILD_URL']=build.get_result_url() |
---|
435 | except jenkinsapi.custom_exceptions.NoBuildData: |
---|
436 | pass |
---|
437 | |
---|
438 | if self.job.is_queued_or_running(): |
---|
439 | # TODO: if job is queue, but not running, BUILD_NUMBER is wrong |
---|
440 | self.logger.debug( "jenkins job " + self.jobname + " is running" ) |
---|
441 | self.status['status']=STATE.pending |
---|
442 | return self.status['status'] |
---|
443 | |
---|
444 | # jenkins job is not running |
---|
445 | self.logger.debug( "no jenkins job is running for " + self.jobname ) |
---|
446 | jenkins_job_build_version=self.__get_jenkins_build_parameter('BUILD_VERSION') |
---|
447 | |
---|
448 | self.logger.debug( "OBS version: " + str(self.version['version']) + ", " + "jenkins version: " + str(jenkins_job_build_version) ) |
---|
449 | |
---|
450 | if jenkins_job_build_version == self.obs.get_pkg_version(): |
---|
451 | # TODO: check if number DISTRELEASES have changed |
---|
452 | logger.debug( "skipped jenkins, as it has already tested the current OBS version" ) |
---|
453 | if build.is_good(): |
---|
454 | # success |
---|
455 | self.status['status']=STATE.succeeded |
---|
456 | else: |
---|
457 | self.status['status']=STATE.failed |
---|
458 | return self.status['status'] |
---|
459 | |
---|
460 | # jenkins job is not running and last_build has not been for current version |
---|
461 | |
---|
462 | # get config data in xml format |
---|
463 | configString=self.job.get_config() |
---|
464 | |
---|
465 | # https://docs.python.org/2.7/library/xml.etree.elementtree.html |
---|
466 | xmlConfig=etree.fromstring( configString ) |
---|
467 | |
---|
468 | build_params = { |
---|
469 | 'BUILD_VERSION': self.version['version'], |
---|
470 | 'BUILD_REV': self.version['rev'], |
---|
471 | 'BUILD_SRCMD5': self.version['srcmd5'], |
---|
472 | 'PACKAGES': self.project_packages, |
---|
473 | } |
---|
474 | # build paramter that must be present as Jenkins parameter configuration |
---|
475 | self.__add_jenkins_build_parameter( xmlConfig, build_params.copy() ) |
---|
476 | self.__set_jenkins_matrix_distrelease(xmlConfig) |
---|
477 | |
---|
478 | xmlString=etree.tostring( xmlConfig ) |
---|
479 | self.job.update_config( xmlString ) |
---|
480 | |
---|
481 | self.logger.info( "starting jenkins for obs build " + self.version['version'] ) |
---|
482 | invocation=self.job.invoke( build_params=build_params ) |
---|
483 | |
---|
484 | if wait: |
---|
485 | try: |
---|
486 | invocation.block() |
---|
487 | except jenkinsapi.custom_exceptions.TimeOut as e: |
---|
488 | self.logger.exception( "timeout while waiting for jenkins job" ) |
---|
489 | |
---|
490 | # recusive |
---|
491 | return self.checkAndTrigger() |
---|
492 | |
---|
493 | |
---|
494 | def get_status(self): |
---|
495 | return self.status |
---|
496 | |
---|
497 | |
---|
498 | if __name__ == '__main__': |
---|
499 | logging.basicConfig(level=logging.INFO) |
---|
500 | logger=logging.getLogger(__name__) |
---|
501 | |
---|
502 | parser = argparse.ArgumentParser(description='check overall build status of an OBS package.' ) |
---|
503 | |
---|
504 | parser.add_argument( '--debug', action='store_true', help="enable debugging output" ) |
---|
505 | parser.add_argument( '--obsapiurl', help="OBS API url" ) |
---|
506 | parser.add_argument( '--jenkinsurl', help="Jenkins base url" ) |
---|
507 | parser.add_argument( '--jenkinsjob', help="Jenkins job name" ) |
---|
508 | parser.add_argument( '--destdir', help="directory to write status info to. If not given, status will be written to stdout" ) |
---|
509 | parser.add_argument( '--wait', action='store_true', help="wait untils jobs are finished (currently only jenkins)" ) |
---|
510 | parser.add_argument( 'project', help="OBS project" ) |
---|
511 | parser.add_argument( 'package', help="OBS package" ) |
---|
512 | |
---|
513 | args = parser.parse_args() |
---|
514 | |
---|
515 | if args.debug: |
---|
516 | logger.setLevel(logging.DEBUG) |
---|
517 | |
---|
518 | wait=args.wait |
---|
519 | |
---|
520 | prj=args.project |
---|
521 | pkg=args.package |
---|
522 | |
---|
523 | if args.obsapiurl: |
---|
524 | osc_paramter="--apiurl=" + args.obsapiurl |
---|
525 | |
---|
526 | if args.destdir: |
---|
527 | destdir=args.destdir |
---|
528 | |
---|
529 | jenkins_status = { |
---|
530 | 'status': STATE.disabled |
---|
531 | } |
---|
532 | |
---|
533 | osc = Osc(osc_paramter) |
---|
534 | # check obs |
---|
535 | obs = ObsStatus(osc, prj, pkg) |
---|
536 | obs.update() |
---|
537 | if obs.get_state() == STATE.succeeded and obs.get_pkg_version(): |
---|
538 | if args.jenkinsurl and args.jenkinsjob: |
---|
539 | # run and check jenkins |
---|
540 | jenkins = JenkinsTrigger(args.jenkinsurl, args.jenkinsjob, obs) |
---|
541 | jenkins.checkAndTrigger(wait) |
---|
542 | jenkins_status = jenkins.get_status() |
---|
543 | else: |
---|
544 | logger.info( "skipped jenkins tests, because prior steps" ) |
---|
545 | |
---|
546 | logger.debug( "write status" ) |
---|
547 | write_status(obs, jenkins_status) |
---|