def batch_record_to_dict(record): format_version = BatchFormatVersion(record['format_version']) if record['state'] == 'open': state = 'open' elif record['n_failed'] > 0: state = 'failure' elif record['cancelled'] or record['n_cancelled'] > 0: state = 'cancelled' elif record['state'] == 'complete': assert record['n_succeeded'] == record['n_jobs'] state = 'success' else: state = 'running' def _time_msecs_str(t): if t: return time_msecs_str(t) return None time_created = _time_msecs_str(record['time_created']) time_closed = _time_msecs_str(record['time_closed']) time_completed = _time_msecs_str(record['time_completed']) if record['time_closed'] and record['time_completed']: duration = humanize_timedelta_msecs(record['time_completed'] - record['time_closed']) else: duration = None d = { 'id': record['id'], 'user': record['user'], 'billing_project': record['billing_project'], 'token': record['token'], 'state': state, 'complete': record['state'] == 'complete', 'closed': record['state'] != 'open', 'n_jobs': record['n_jobs'], 'n_completed': record['n_completed'], 'n_succeeded': record['n_succeeded'], 'n_failed': record['n_failed'], 'n_cancelled': record['n_cancelled'], 'time_created': time_created, 'time_closed': time_closed, 'time_completed': time_completed, 'duration': duration, } attributes = json.loads(record['attributes']) if attributes: d['attributes'] = attributes msec_mcpu = record['msec_mcpu'] d['msec_mcpu'] = msec_mcpu cost = format_version.cost(record['msec_mcpu'], record['cost']) d['cost'] = cost return d
async def get_pr(request, userdata): # pylint: disable=unused-argument wb, pr = wb_and_pr_from_request(request) page_context = {} page_context['repo'] = wb.branch.repo.short_str() page_context['wb'] = wb page_context['pr'] = pr # FIXME batch = pr.batch if batch: if hasattr(batch, 'id'): status = await batch.status() jobs = await collect_agen(batch.jobs()) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) page_context['batch'] = status page_context['jobs'] = jobs page_context[ 'artifacts'] = f'/{BUCKET}/build/{batch.attributes["token"]}' else: page_context['exception'] = '\n'.join( traceback.format_exception(None, batch.exception, batch.exception.__traceback__)) batch_client = request.app['batch_client'] batches = batch_client.list_batches(f'test=1 pr={pr.number}') batches = sorted([b async for b in batches], key=lambda b: b.id, reverse=True) page_context['history'] = [await b.status() for b in batches] return await render_template('ci', request, userdata, 'pr.html', page_context)
async def get_batch(request, userdata): batch_id = int(request.match_info['batch_id']) batch_client = request.app['batch_client'] b = await batch_client.get_batch(batch_id) status = await b.last_known_status() jobs = await collect_agen(b.jobs()) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) page_context = {'batch': status, 'jobs': jobs} return await render_template('ci', request, userdata, 'batch.html', page_context)
async def ui_get_job(request, userdata): app = request.app db = app['db'] batch_id = int(request.match_info['batch_id']) job_id = int(request.match_info['job_id']) user = userdata['username'] job_status = await _get_job(app, batch_id, job_id, user) attempts = [ attempt async for attempt in db.select_and_fetchall( ''' SELECT * FROM attempts WHERE batch_id = %s AND job_id = %s ''', (batch_id, job_id)) ] for attempt in attempts: start_time = attempt['start_time'] if start_time: attempt['start_time'] = time_msecs_str(start_time) else: del attempt['start_time'] end_time = attempt['end_time'] if end_time is not None: attempt['end_time'] = time_msecs_str(end_time) else: del attempt['end_time'] if start_time is not None: # elapsed time if attempt is still running if end_time is None: end_time = time_msecs() duration_msecs = max(end_time - start_time, 0) attempt['duration'] = humanize_timedelta_msecs(duration_msecs) page_context = { 'batch_id': batch_id, 'job_id': job_id, 'job_log': await _get_job_log(app, batch_id, job_id, user), 'attempts': attempts, 'job_status': json.dumps(job_status, indent=2) } return await render_template('batch', request, userdata, 'job.html', page_context)
async def ui_batch(request, userdata): app = request.app batch_id = int(request.match_info['batch_id']) user = userdata['username'] batch = await _get_batch(app, batch_id, user) jobs, last_job_id = await _query_batch_jobs(request, batch_id) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) batch['jobs'] = jobs page_context = { 'batch': batch, 'q': request.query.get('q'), 'last_job_id': last_job_id } return await render_template('batch', request, userdata, 'batch.html', page_context)
async def get_pr(request, userdata): # pylint: disable=unused-argument watched_branch_index = int(request.match_info['watched_branch_index']) pr_number = int(request.match_info['pr_number']) if watched_branch_index < 0 or watched_branch_index >= len( watched_branches): raise web.HTTPNotFound() wb = watched_branches[watched_branch_index] if not wb.prs or pr_number not in wb.prs: raise web.HTTPNotFound() pr = wb.prs[pr_number] page_context = {} page_context['repo'] = wb.branch.repo.short_str() page_context['pr'] = pr # FIXME if pr.batch: if hasattr(pr.batch, 'id'): status = await pr.batch.status() jobs = await collect_agen(pr.batch.jobs()) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) page_context['batch'] = status page_context['jobs'] = jobs # [4:] strips off gs:/ page_context[ 'artifacts'] = f'{BUCKET}/build/{pr.batch.attributes["token"]}'[ 4:] else: page_context['exception'] = '\n'.join( traceback.format_exception(None, pr.batch.exception, pr.batch.exception.__traceback__)) batch_client = request.app['batch_client'] batches = batch_client.list_batches(f'test=1 pr={pr_number}') batches = sorted([b async for b in batches], key=lambda b: b.id, reverse=True) page_context['history'] = [await b.status() for b in batches] return await render_template('ci', request, userdata, 'pr.html', page_context)