Dashboard: Add git support

svn-origin-rev: 18382
This commit is contained in:
Ole Schütt 2018-04-20 14:28:50 +00:00
parent 02196a15bb
commit 43bfa281ef
2 changed files with 239 additions and 228 deletions

View file

@ -1,5 +1,5 @@
#!/bin/bash
wget -nH -Nxi http://dashboard.cp2k.org/archive/list_recent.txt
wget --no-verbose -nH -Nxi http://dashboard.cp2k.org/archive/list_recent.txt
#EOF

View file

@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Generates the CP2K Dashboard html page
@ -13,60 +13,61 @@ from email.mime.text import MIMEText
import re
import gzip
from datetime import datetime, timedelta
import subprocess
from subprocess import check_output
import traceback
from os import path
from pprint import pformat
from xml.dom import minidom
from glob import glob
import itertools
try:
from urllib.parse import urlencode
except ImportError:
from urllib import urlencode
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
try:
import configparser
except ImportError:
import ConfigParser as configparser
from urllib.parse import urlencode
from urllib.request import urlopen
import configparser
import matplotlib as mpl
mpl.use('Agg') # change backend, to run without X11
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
#===============================================================================
class GitLog(list):
def __init__(self):
cmd = ["git", "log", "--pretty=format:%H%n%ct%n%an%n%s%n%b<--seperator-->"]
outbytes = check_output(cmd)
output = outbytes.decode("utf-8")
for entry in output.split("<--seperator-->")[:-1]:
lines = entry.strip().split("\n")
commit = dict()
commit['git-sha'] = lines[0]
commit['date'] = datetime.fromtimestamp(float(lines[1]))
commit['author'] = lines[2]
commit['msg'] = lines[3]
m = re.match("git-svn-id: svn://svn.code.sf.net/p/cp2k/code/trunk@(\d+) .+", lines[-1])
if(m):
commit['svn-rev'] = int(m.group(1))
self.append(commit)
# git-log outputs entries from new to old.
self.index = { c['git-sha']: i for i, c in enumerate(self) }
self.svn2git = { c['svn-rev']: c['git-sha'] for c in self if 'svn-rev' in c }
print("done.")
#===============================================================================
def main():
if(len(sys.argv) not in (5, 6)):
print("Usage update_dashboard.py <config-file> <addressbook> <status-file> <output-dir> [--full-archive]")
if(len(sys.argv) != 5):
print("Usage update_dashboard.py <config-file> <addressbook> <status-file> <output-dir>")
sys.exit(1)
config_fn, abook_fn, status_fn, outdir = sys.argv[1:5]
config_fn, abook_fn, status_fn, outdir = sys.argv[1:]
assert(outdir.endswith("/"))
assert(path.exists(config_fn))
full_archive = False
if(len(sys.argv) == 6):
assert(sys.argv[5] == "--full-archive")
full_archive = True
config = configparser.ConfigParser()
config.read(config_fn)
log = GitLog() # Reads history from local git repo.
if(full_archive):
log = svn_log() # fetch entire history
else:
log = svn_log(limit=100)
gen_frontpage(config, log, abook_fn, status_fn, outdir)
gen_archive(config, log, outdir, full_archive)
gen_url_list(config, outdir, full_archive)
gen_frontpage(config, log, abook_fn, status_fn, outdir)
gen_archive(config, log, outdir)
gen_url_list(config, outdir)
#===============================================================================
def gen_frontpage(config, log, abook_fn, status_fn, outdir):
@ -77,22 +78,20 @@ def gen_frontpage(config, log, abook_fn, status_fn, outdir):
else:
status = dict()
trunk_revision = log[0]['num']
log_index = dict([(r['num'], r) for r in log])
now = datetime.utcnow().replace(microsecond=0)
output = html_header(title="CP2K Dashboard", rev=trunk_revision)
output = html_header(title="CP2K Dashboard")
output += '<div id="flex-container"><div>\n'
output += html_svnbox(log)
output += html_gitbox(log)
output += html_linkbox()
output += '</div>\n'
output += '<table border="1" cellspacing="3" cellpadding="5">\n'
output += '<tr><th>Name</th><th>Host</th><th>Status</th>'
output += '<th>Revision</th><th>Summary</th><th>Last OK</th></tr>\n\n'
output += '<th>Commit</th><th>Summary</th><th>Last OK</th></tr>\n\n'
def get_sortkey(s):
return config.getint(s, "sortkey")
now = datetime.utcnow().replace(microsecond=0)
for s in sorted(config.sections(), key=get_sortkey):
print("Working on summary entry of: "+s)
name = config.get(s,"name")
@ -102,48 +101,48 @@ def gen_frontpage(config, log, abook_fn, status_fn, outdir):
do_notify = config.getboolean(s,"notify") if(config.has_option(s,"notify")) else False
timeout = config.getint(s,"timeout") if(config.has_option(s,"timeout")) else 24
# find latest revision that should have been tested by now
# find latest commit that should have been tested by now
freshness_threshold = now - timedelta(hours=timeout)
revs_beyond_threshold = [ r['num'] for r in log if r['date'] < freshness_threshold ]
threshold_rev = revs_beyond_threshold[0]
ages_beyond_threshold = [ i for i, c in enumerate(log) if c['date'] < freshness_threshold ]
threshold_age = ages_beyond_threshold[0]
# get and parse report
report_txt = retrieve_report(report_url)
report = parse_report(report_txt, report_type)
report = parse_report(report_txt, report_type, log)
if(s not in status.keys()):
if(s not in status):
status[s] = {'last_ok': None, 'notified': False}
if(report['status'] == "OK"):
status[s]['last_ok'] = report['revision']
status[s]['last_ok'] = report['git-sha']
status[s]['notified'] = False
elif(do_notify and not status[s]['notified']):
send_notification(report, addressbook, status[s]['last_ok'], log_index, name, s)
send_notification(report, addressbook, status[s]['last_ok'], log, name, s)
status[s]['notified'] = True
uptodate = report['revision']==trunk_revision # report from latest commit?
if(report['revision'] != None):
if(report['revision']<threshold_rev):
if(report['git-sha']):
age = log.index[report['git-sha']]
if(age > threshold_age):
report['status'] = "OUTDATED"
elif(report['status'] in ("OK", "FAILED")):
# store only useful and fresh reports, prevents overwriting archive
fn = outdir+"archive/%s/rev_%d.txt.gz"%(s,report['revision'])
write_file(fn, report_txt, gz=True)
store_report(report, report_txt, s, outdir)
uptodate = report['git-sha'] == log[0]['git-sha'] # report from latest commit?
output += '<tr align="center">'
output += '<td align="left"><a href="archive/%s/index.html">%s</a></td>'%(s, name)
output += '<td align="left">%s</td>'%host
output += status_cell(report['status'], report_url, uptodate)
#Revision
output += revision_cell(report['revision'], trunk_revision)
#Commit
output += commit_cell(report['git-sha'], log)
#Summary
output += '<td align="left">%s</td>'%report['summary']
#Last OK
if(report['status'] != "OK"):
output += revision_cell(status[s]['last_ok'], trunk_revision)
output += commit_cell(status[s]['last_ok'], log)
else:
output += '<td></td>'
@ -152,104 +151,107 @@ def gen_frontpage(config, log, abook_fn, status_fn, outdir):
output += '</table>\n'
output += '<div id="dummybox"></div></div>\n' # complete flex-container
output += html_footer()
write_file(outdir+"index.html", output.encode("utf8"))
write_file(outdir+"index.html", output)
write_file(status_fn, pformat(status))
#===============================================================================
def gen_archive(config, log, outdir, full_archive):
log_index = dict([(r['num'], r) for r in log])
if(full_archive):
print("Doing the full archive index pages")
trunk_revision = None # trunk_version changes quickly, leave it out.
html_out_postfix = "index_full.html"
urls_out_postfix = "list_full.txt"
other_index_link = '<p>View <a href="index.html">recent archive</a></p>'
else:
print("Doing recent archive index pages")
trunk_revision = log[0]['num']
html_out_postfix = "index.html"
urls_out_postfix = "list_recent.txt"
other_index_link = '<p>View <a href="index_full.html">full archive</a></p>'
def gen_archive(config, log, outdir):
for s in config.sections():
print("Working on archive page of: "+s)
name = config.get(s,"name")
report_type = config.get(s,"report_type")
info_url = config.get(s,"info_url") if(config.has_option(s,"info_url")) else None
html_out_fn = outdir+"archive/%s/%s"%(s,html_out_postfix)
urls_out_fn = outdir+"archive/%s/%s"%(s,urls_out_postfix)
archive_files = glob(outdir+"archive/%s/rev_*.txt.gz"%s)
# check if anything has changed
if(path.exists(html_out_fn)):
last_change = max([path.getmtime(fn) for fn in archive_files])
if(last_change < path.getmtime(html_out_fn)):
print("Nothing has changed, skipping: "+html_out_fn)
continue
archive_files = glob(outdir+"archive/%s/rev_*.txt.gz"%s) + \
glob(outdir+"archive/%s/commit_*.txt.gz"%s)
# read all archived reports
archive_reports = dict()
for fn in sorted(archive_files, reverse=True):
report_txt = gzip.open(fn, 'rb').read()
report = parse_report(report_txt, report_type)
for fn in archive_files:
report_txt = gzip.open(fn, 'rb').read().decode("utf-8")
report = parse_report(report_txt, report_type, log)
report['url'] = path.basename(fn)[:-3]
archive_reports[report['revision']] = report
sha = report['git-sha']
assert sha not in archive_reports
archive_reports[sha] = report
# generate archive index
archive_output = html_header(title=name, rev=trunk_revision)
archive_output += '<p>Go back to <a href="../../index.html">main page</a></p>\n'
if(info_url):
archive_output += '<p>Get <a href="%s">more information</a></p>\n'%info_url
if(report_type == "generic"):
archive_output += gen_plots(archive_reports, log, outdir+"archive/"+s+"/", full_archive)
archive_output += other_index_link
archive_output += '<table border="1" cellspacing="3" cellpadding="5">\n'
archive_output += '<tr><th>Revision</th><th>Status</th><th>Summary</th><th>Author</th><th>Commit Message</th></tr>\n\n'
# loop over all relevant revisions
url_list = ""
rev_start = max(min(archive_reports.keys()), min(log_index.keys()))
rev_end = max(log_index.keys())
for r in range(rev_end, rev_start-1, -1):
archive_output += '<tr>'
archive_output += revision_cell(r, trunk_revision)
if(archive_reports.has_key(r)):
report = archive_reports[r]
archive_output += status_cell(report['status'], report['url'])
archive_output += '<td align="left">%s</td>'%report['summary']
url_list += "https://dashboard.cp2k.org/archive/%s/%s.gz\n"%(s, report['url'])
# loop over all relevant commits
all_url_rows = []
all_html_rows = []
max_age = max([log.index[sha] for sha in archive_reports.keys()])
for commit in log[:max_age]:
sha = commit['git-sha']
html_row = '<tr>'
html_row += commit_cell(sha, log)
if(sha in archive_reports):
report = archive_reports[sha]
html_row += status_cell(report['status'], report['url'])
html_row += '<td align="left">%s</td>'%report['summary']
url_row = "https://dashboard.cp2k.org/archive/%s/%s.gz\n"%(s, report['url'])
else:
archive_output += 2*'<td></td>'
svn_rev = log_index[r]
archive_output += '<td align="left">%s</td>'%svn_rev['author']
archive_output += '<td align="left">%s</td>'%svn_rev['msg'].split("\n")[0]
archive_output += '</tr>\n\n'
html_row += 2*'<td></td>'
url_row = ""
html_row += '<td align="left">%s</td>'%commit['author']
html_row += '<td align="left">%s</td>'%commit['msg']
html_row += '</tr>\n\n'
all_html_rows.append(html_row)
all_url_rows.append(url_row)
archive_output += '</table>\n'
archive_output += other_index_link
archive_output += html_footer()
write_file(html_out_fn, archive_output.encode("utf8"))
write_file(urls_out_fn, url_list)
# generate html pages
for full_archive in (False, True):
if(full_archive):
html_out_postfix = "index_full.html"
urls_out_postfix = "list_full.txt"
other_index_link = '<p>View <a href="index.html">recent archive</a></p>'
max_age = None # output all
else:
html_out_postfix = "index.html"
urls_out_postfix = "list_recent.txt"
other_index_link = '<p>View <a href="index_full.html">full archive</a></p>'
max_age = 100
# generate archive index
output = html_header(title=name)
output += '<p>Go back to <a href="../../index.html">main page</a></p>\n'
if(info_url):
output += '<p>Get <a href="%s">more information</a></p>\n'%info_url
if(report_type == "generic"):
output += gen_plots(archive_reports, log, outdir+"archive/"+s+"/", full_archive)
output += other_index_link
output += '<table border="1" cellspacing="3" cellpadding="5">\n'
output += '<tr><th>Commit</th><th>Status</th><th>Summary</th><th>Author</th><th>Commit Message</th></tr>\n\n'
output += "".join(all_html_rows[:max_age])
output += '</table>\n'
output += other_index_link
output += html_footer()
html_out_fn = outdir+"archive/%s/%s"%(s,html_out_postfix)
write_file(html_out_fn, output)
url_list = "".join(all_url_rows[:max_age])
urls_out_fn = outdir+"archive/%s/%s"%(s,urls_out_postfix)
write_file(urls_out_fn, url_list)
#===============================================================================
def gen_url_list(config, outdir, full_archive):
print("Working url list:")
urls_out_postfix = "list_full.txt" if full_archive else "list_recent.txt"
url_list = ""
for s in config.sections():
fn = outdir+"archive/%s/%s"%(s,urls_out_postfix)
if(not path.exists(fn)):
continue
url_list += open(fn).read()
write_file(outdir+"archive/"+urls_out_postfix, url_list)
def gen_url_list(config, outdir):
print("Working on url lists.")
for postfix in ("list_full.txt", "list_recent.txt"):
url_list = ""
for s in config.sections():
fn = outdir+"archive/%s/%s"%(s, postfix)
if(not path.exists(fn)):
continue
url_list += open(fn).read()
write_file(outdir+"archive/" + postfix, url_list)
#===============================================================================
def gen_plots(all_reports, log, outdir, full_archive):
def gen_plots(archive_reports, log, outdir, full_archive):
ordered_shas = [commit['git-sha'] for commit in log]
ordered_reports = [archive_reports[sha] for sha in ordered_shas if sha in archive_reports]
# collect plot data
plots = {}
for revision in sorted(all_reports.keys()):
report = all_reports[revision]
for report in ordered_reports:
for p in report['plots']:
if(p['name'] not in plots.keys()):
plots[p['name']] = {'curves':{}}
@ -260,7 +262,8 @@ def gen_plots(all_reports, log, outdir, full_archive):
if(pp['name'] not in p['curves'].keys()):
p['curves'][pp['name']] = {'x':[], 'y':[], 'yerr':[]}
c = p['curves'][pp['name']]
c['x'].append(report['revision'])
age = log.index[report['git-sha']]
c['x'].append(-age)
c['y'].append(pp['y'])
c['yerr'].append(pp['yerr'])
c['label'] = pp['label'] # update label
@ -268,13 +271,13 @@ def gen_plots(all_reports, log, outdir, full_archive):
# write raw data
tags = sorted([(pname, cname) for pname, p in plots.items() for cname in p['curves'].keys()])
if(tags):
raw_output = "#%9s"%"revision"
raw_output = "# %6s %40s" % ("age", "commit")
for pname, cname in tags:
raw_output += " %18s %22s"%(pname+"/"+cname,pname+"/"+cname+"_err")
raw_output += "\n"
for revision in sorted(all_reports.keys(), reverse=True):
report = all_reports[revision]
raw_output += "%10d"%revision
for report in reversed(ordered_reports):
age = log.index[report['git-sha']]
raw_output += "%8d %40s"%(-age, report['git-sha'])
for pname, cname in tags:
pp = [pp for pp in report['plotpoints'] if(pp['plot']==pname and pp['name']==cname)]
assert(len(pp)<=1)
@ -286,16 +289,20 @@ def gen_plots(all_reports, log, outdir, full_archive):
write_file(outdir+"plot_data.txt", raw_output)
# create png images
fig_ext = "_full.png" if(full_archive) else ".png"
rev_end = log[0]['num']
rev_start = min(all_reports.keys()) if(full_archive) else rev_end-100
if (full_archive):
fig_ext = "_full.png"
max_age = max([log.index[sha] for sha in archive_reports.keys()])
else:
fig_ext = ".png"
max_age = 100
for pname, p in plots.items():
print("Working on plot: "+pname)
fig = plt.figure(figsize=(12,4))
fig.subplots_adjust(bottom=0.18, left=0.06, right=0.70)
fig.suptitle(p['title'], fontsize=14, fontweight='bold', x=0.4)
ax = fig.add_subplot(111)
ax.set_xlabel('SVN Revision')
ax.set_xlabel('Commit Age')
ax.set_ylabel(p['ylabel'])
markers = itertools.cycle('os>^*')
for cname in sorted(p['curves'].keys()):
@ -304,13 +311,13 @@ def gen_plots(all_reports, log, outdir, full_archive):
ax.plot(c['x'], c['y'], label=c['label'], linewidth=2) # less crowded
else:
ax.errorbar(c['x'], c['y'], yerr=c['yerr'], label=c['label'],
marker=markers.next(), linewidth=2, markersize=6)
ax.set_xlim(rev_start-1, rev_end+1)
marker=next(markers), linewidth=2, markersize=6)
ax.set_xlim(-max_age-1, 0)
ax.xaxis.set_minor_locator(AutoMinorLocator())
ax.legend(bbox_to_anchor=(1.01, 1), loc='upper left',
numpoints=1, fancybox=True, shadow=True, borderaxespad=0.0)
visibles = [[y for x,y in zip(c['x'],c['y']) if x>=rev_start] for c in p['curves'].values()] # visible y-values
ymin = min([min(ys) for ys in visibles if ys]) # lowest point from lowest curve
visibles = [[y for x,y in zip(c['x'],c['y']) if x>=-max_age] for c in p['curves'].values()] # visible y-values
ymin = min([min(ys) for ys in visibles if ys]) # lowest point from lowest curve
ymax = max([max(ys) for ys in visibles if ys]) # highest point from highest curve
if(full_archive):
ax.set_ylim(0.98*ymin, 1.02*ymax)
@ -318,6 +325,7 @@ def gen_plots(all_reports, log, outdir, full_archive):
ymax2 = max([min(ys) for ys in visibles if ys]) # lowest point from highest curve
ax.set_ylim(0.98*ymin, min(1.02*ymax, 1.3*ymax2)) # protect against outlayers
fig.savefig(outdir+pname+fig_ext)
plt.close(fig)
# write html output
html_output = ""
@ -326,33 +334,11 @@ def gen_plots(all_reports, log, outdir, full_archive):
return(html_output)
#===============================================================================
def retrieve_report(report_url):
try:
return urlopen(report_url, timeout=5).read()
except:
print(traceback.print_exc())
return None
#===============================================================================
def parse_report(report_txt, report_type):
if(report_txt==None):
return( {'status':'UNKNOWN', 'summary':'Error while retrieving report.', 'revision':None} )
try:
if(report_type == "regtest"):
return parse_regtest_report(report_txt)
elif(report_type == "generic"):
return parse_generic_report(report_txt)
else:
raise(Exception("Unknown report_type"))
except:
print(traceback.print_exc())
return( {'status':'UNKNOWN', 'summary':'Error while parsing report.', 'revision':None} )
#===============================================================================
def send_notification(report, addressbook, last_ok, svn_log, name, s):
rev_end = report['revision'] if(report['revision']) else max(svn_log.keys())
if(rev_end==last_ok): return # probably a flapping tester
authors = set([svn_log[r]['author'] for r in range(last_ok+1, rev_end+1)])
def send_notification(report, addressbook, last_ok, log, name, s):
idx_end = log.index[report['git-sha']] if(report['git-sha']) else 0
idx_last_ok = log.index[last_ok]
if(idx_end == idx_last_ok): return # probably a flapping tester
authors = set([log[i]['author'] for i in range(idx_end, last_ok)])
emails = [addressbook[a] for a in authors]
print("Sending email to: "+", ".join(emails))
@ -361,7 +347,7 @@ def send_notification(report, addressbook, last_ok, svn_log, name, s):
msg_txt += " test name: %s\n"%name
msg_txt += " report state: %s\n"%report['status']
msg_txt += " report summary: %s\n"%report['summary']
msg_txt += " last OK rev: %d\n\n"%last_ok
msg_txt += " last OK commit: %d\n\n"%last_ok
msg_txt += "For more information visit:\n"
msg_txt += " https://dashboard.cp2k.org/archive/%s/index.html \n\n"%s
msg_txt += "Sincerely,\n"
@ -377,7 +363,7 @@ def send_notification(report, addressbook, last_ok, svn_log, name, s):
smtp_conn.quit()
#===============================================================================
def html_header(title, rev=None):
def html_header(title):
output = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n'
output += '<html><head>\n'
output += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n'
@ -437,7 +423,7 @@ def html_header(title, rev=None):
output += ' width: 15em;\n'
output += '}\n'
output += '</style>\n'
output += '<title>%s%s</title>\n'%(title, (" (%d)"%rev if rev else ""))
output += '<title>%s</title>\n'%title
output += '</head><body>\n'
output += '<div class="ribbon"><a href="https://cp2k.org/dev:dashboard">Need Help?</a></div>\n'
output += '<center><h1>%s</h1></center>\n'%title.upper()
@ -454,19 +440,22 @@ def html_linkbox():
return(output)
#===============================================================================
def html_svnbox(log):
def html_gitbox(log):
now = datetime.utcnow()
output = '<div class="sidebox">\n'
output += '<h2>Recent Commits</h2>\n'
for r in log[0:10]:
url = "https://sourceforge.net/p/cp2k/code/%d/"%r['num']
msg = r['msg'].split("\n")[0]
for commit in log[0:10]:
url = "https://github.com/cp2k/cp2k/commit/" + commit['git-sha']
msg = commit['msg']
if(len(msg) > 27):
msg = msg[:26] + "..."
output += '<p><a title="%s" href="%s">%s</a><br>\n'%(r['msg'], url, msg)
delta = now - r['date']
output += '<p><a title="%s" href="%s">%s</a><br>\n'%(commit['msg'], url, msg)
delta = now - commit['date']
age = delta.days*24.0 + delta.seconds/3600.0
output += '<small>%s %s %.1fh ago.</small></p>\n'%(r['num'], r['author'], age)
output += '<small>git:' + commit['git-sha'][:7]
if 'svn-rev' in commit:
output += ' / svn:%d'%commit['svn-rev']
output += '<br>\n%s %.1fh ago.</small></p>\n'%(commit['author'], age)
output += '</div>\n'
return(output)
@ -488,38 +477,11 @@ def write_file(fn, content, gz=False):
if(old_content == content):
print("File did not change: "+fn)
return
f = gzip.open(fn, 'wb') if(gz) else open(fn, "w")
f.write(content)
f = gzip.open(fn, 'wb') if(gz) else open(fn, "wb")
f.write(content.encode("utf-8"))
f.close()
print("Wrote: "+fn)
#===============================================================================
def svn_log(limit=None):
sys.stdout.write("Fetching svn log... ")
sys.stdout.flush()
# xml version contains nice UTC timestamp
if(limit):
cmd = "svn log --limit %d svn://svn.code.sf.net/p/cp2k/code --xml"%limit
else:
# our server is much faster, but might be 5 minutes old
cmd = "svn log https://svn.cp2k.org/cp2k --xml"
log_xml = check_output(cmd.split())
dom = minidom.parseString(log_xml)
revisions = []
for entry in dom.getElementsByTagName("logentry"):
rev = dict()
rev['num'] = int(entry.attributes['revision'].value)
rev_date_str = entry.getElementsByTagName('date')[0].firstChild.nodeValue
rev['date'] = datetime.strptime(rev_date_str[:19], '%Y-%m-%dT%H:%M:%S')
# some revisions lack an author
author = entry.getElementsByTagName('author')
rev['author'] = author[0].firstChild.nodeValue if (len(author)==1) else ""
msg = entry.getElementsByTagName('msg')[0].firstChild
rev['msg'] = msg.nodeValue.strip() if(msg) else ""
revisions.append(rev)
print("done.")
return(revisions)
#===============================================================================
def status_cell(status, report_url, uptodate=True):
if(status == "OK"):
@ -531,22 +493,71 @@ def status_cell(status, report_url, uptodate=True):
return('<td bgcolor="%s"><a href="%s">%s</a></td>'%(bgcolor, report_url, status))
#===============================================================================
def revision_cell(rev, trunk_rev):
if(rev == None):
def commit_cell(git_sha, log):
if(git_sha is None):
return('<td>N/A</td>')
rev_url = "https://sourceforge.net/p/cp2k/code/%d/"%rev
rev_delta = "(%d)"%(rev - trunk_rev) if(trunk_rev) else ""
output = '<td align="left"><a href="%s">%s</a> %s</td>'%(rev_url, rev, rev_delta)
idx = log.index[git_sha]
commit = log[idx]
git_url = "https://github.com/cp2k/cp2k/commit/" + git_sha
output = '<td align="left"><a href="%s">%s</a>'%(git_url, git_sha[:7])
if 'svn-rev' in commit:
svn_rev = commit['svn-rev']
svn_url = "https://sourceforge.net/p/cp2k/code/%d/"%svn_rev
output += ' / <a href="%s">%d</a>'%(svn_url, svn_rev)
output += ' (%d)</td>'%(-idx)
return(output)
#===============================================================================
def retrieve_report(report_url):
try:
return urlopen(report_url, timeout=5).read().decode("utf-8")
except:
print(traceback.print_exc())
return None
#===============================================================================
def store_report(report, report_txt, section, outdir):
if ('svn-rev' in report):
fn = outdir+"archive/%s/rev_%d.txt.gz"%(section, report['svn-rev'])
else:
fn = outdir+"archive/%s/commit_%s.txt.gz"%(section, report['git-sha'])
write_file(fn, report_txt, gz=True)
#===============================================================================
def parse_report(report_txt, report_type, log):
if(report_txt is None):
return( {'status':'UNKNOWN', 'summary':'Error while retrieving report.', 'git-sha':None} )
try:
if(report_type == "regtest"):
report = parse_regtest_report(report_txt)
elif(report_type == "generic"):
report = parse_generic_report(report_txt)
else:
raise(Exception("Unknown report_type"))
if ('svn-rev' in report):
assert 'git-sha' not in report
rev = report['svn-rev']
if rev not in log.svn2git:
return( {'status':'UNKNOWN', 'summary':'Could not convert svn revision to git commit.', 'git-sha':None} )
report['git-sha'] = log.svn2git[rev]
return(report)
except:
print(traceback.print_exc())
return( {'status':'UNKNOWN', 'summary':'Error while parsing report.', 'git-sha':None} )
#===============================================================================
def parse_regtest_report(report_txt):
m = re.search("svn: .*(Can't connect .*):", report_txt)
if(m):
return({'revision':None, 'status':'UNKNOWN', 'summary':m.group(1)})
return({'status':'UNKNOWN', 'summary':m.group(1)})
report = dict()
report['revision'] = int(re.search("(revision|Revision:) (\d+)\.?\n", report_txt).group(2))
m = re.search("(revision|Revision:) (\d+)\.?\n", report_txt)
if (m):
report['svn-rev'] = int(m.group(2))
m = re.search("(commit|Commit:) (\w{40})\n", report_txt)
if (m):
report['git-sha'] = int(m.group(2))
if("LOCKFILE" in report_txt):
report['status'] = "UNKNOWN"
@ -590,22 +601,22 @@ def parse_regtest_report(report_txt):
def parse_generic_report(report_txt):
m = re.search("svn: .*(Can't connect .*):", report_txt)
if(m):
return({'revision':None, 'status':'UNKNOWN', 'summary':m.group(1)})
return({'status':'UNKNOWN', 'summary':m.group(1)})
report = dict()
report['revision'] = int(re.search("(^|\n)Revision: (\d+)\n", report_txt).group(2))
m = re.search("(^|\n)Revision: (\d+)\n", report_txt)
if (m):
report['svn-rev'] = int(m.group(2))
m = re.search("(^|\n)Commit: (\w{40})\n", report_txt)
if (m):
report['git-sha'] = int(m.group(2))
report['summary'] = re.search("(^|\n)Summary: (.+)\n", report_txt).group(2)
report['status'] = re.search("(^|\n)Status: (.+)\n", report_txt).group(2)
report['plots'] = [eval("dict(%s)"%m[1]) for m in re.findall("(^|\n)Plot: (.+)(?=\n)", report_txt)]
report['plotpoints'] = [eval("dict(%s)"%m[1]) for m in re.findall("(^|\n)PlotPoint: (.+)(?=\n)", report_txt)]
return(report)
#===============================================================================
def check_output(command, **kwargs):
p = subprocess.Popen(command, stdout=subprocess.PIPE, **kwargs)
output = p.communicate()[0]
assert(p.wait() == 0)
return(output)
#===============================================================================
if(len(sys.argv)==2 and sys.argv[-1]=="--selftest"):
pass #TODO implement selftest