tartiflette/appci/fetch.py
2017-11-19 09:41:32 +01:00

150 lines
4.5 KiB
Python
Executable file

import os
import time
import json
import requests
import dateutil.parser
tests = [ "Package linter",
"Installation",
"Deleting",
"Upgrade",
"Backup",
"Restore",
"Change URL",
"Installation in a sub path",
"Deleting from a sub path",
"Installation on the root",
"Deleting from root",
"Installation in private mode",
"Installation in public mode",
"Multi-instance installations",
"Malformed path",
"Port already used" ]
def main():
apps = fetch_applist()
ci_results = {}
for appname, appinfo in sorted(apps.items()):
print "==> %s" % appname
ci_results[appname] = {}
for ci_branch in ["stable", "testing", "unstable", "arm"]:
print " > Fetching results for CI branch %s" % ci_branch
raw_console = get_raw_ci_output(appinfo, ci_branch)
if raw_console is None:
ci_results[appname][ci_branch] = None
continue
test_results = analyze_ci_output(raw_console)
ci_results[appname][ci_branch] = test_results
with open('data/%s' % appname, 'w') as f:
json.dump(ci_results[appname], f)
def fetch_applist():
official = json.loads(requests.get("https://raw.githubusercontent.com/YunoHost/apps/master/official.json").text)
community = json.loads(requests.get("https://raw.githubusercontent.com/YunoHost/apps/master/community.json").text)
for appname, appinfo in official.items():
appinfo["ci_name"] = ci_name(appinfo, official=True)
for appname, appinfo in community.items():
# Ignore apps that are not declared as 'working'
if appinfo["state"] != "working":
del community[appname]
appinfo["ci_name"] = ci_name(appinfo, official=False)
return dict(official.items() + community.items())
def ci_name(app, official):
ci_name = os.path.basename(app["url"]).replace("_ynh", "")
ci_name += " (Official)" if official else " (Community)"
return ci_name
def get_raw_ci_output(app, ci_branch="stable"):
assert ci_branch in [ "stable", "testing", "unstable", "stretch", "arm", "apptesting" ]
ci_server="ci-apps.yunohost.org"
ci_test_name = app["ci_name"]
if ci_branch == "stable":
# Keep default
pass
if ci_branch == "testing":
ci_test_name += " (testing)"
if ci_branch == "unstable":
ci_test_name += " (unstable)"
if ci_branch == "arm":
ci_test_name += " (~ARM~)"
if ci_branch == "stretch":
ci_server = "???"
if ci_branch == "apptesting":
# Not supported yet
return ""
console_url = "https://%s/jenkins/job/%s/lastBuild/consoleText" % (ci_server, ci_test_name)
print console_url
# FIXME : should force ipv4 here?
r = requests.get(console_url)
return r.text.split('\n') if r.status_code == 200 else None
def analyze_ci_output(raw_console):
tests_results = {}
# Find individual tests results
for test in tests:
# A test can have been done several times... We grep all lines
# corresponding to this test
test_results = [ line for line in raw_console if line.startswith(test+":") ]
# For each line corresponding to this test, if there's at least one
# failed, it means this test failed
if [ line for line in test_results if "FAIL" in line ]:
tests_results[test] = False
# Otherwise, if there's at least one success, it means this test
# succeeded
elif [ line for line in test_results if "SUCCESS" in line ]:
tests_results[test] = True
# Otherwise, this means it has not been evaluated
else:
tests_results[test] = None
# Find level
level = 0
for line in raw_console:
if line.startswith('Level of this application:'):
try:
level = int(line.replace('Level of this application:', '').split()[0])
except:
pass # Sorry Bram :<
# Find date
date = None
for previous_line, line in zip(raw_console, raw_console[1:]):
if line == "Test finished.":
# Get date from previous line and parse it into a timestamp
date = previous_line
try:
date = int(time.mktime(dateutil.parser.parse(date).timetuple()))
except:
# Meh
date = None
results = {
"tests": tests_results,
"level": level,
"date": date
}
return results
main()