Add a very crude web view.

master
Simon Quigley 5 years ago
parent 25b9ecf7a9
commit 36ac2eb5fd

1
.gitignore vendored

@ -1,2 +1,3 @@
__pycache__ __pycache__
*.sqlite *.sqlite
output

@ -32,6 +32,7 @@ def sqlite_run(command, db, return_output=False):
conn = sqlite3.connect(db) conn = sqlite3.connect(db)
c = conn.cursor() c = conn.cursor()
for cmd in command: for cmd in command:
log.debug("Executing: %s" % cmd)
c.execute(cmd) c.execute(cmd)
conn.commit() conn.commit()
@ -48,16 +49,25 @@ def sqlite_run(command, db, return_output=False):
def main(module): def main(module):
"""Given a specific module, set it up and insert recent values""" """Given a specific module, set it up and insert recent values"""
# Initialize the module
module = module() module = module()
run = []
run.append(module.sqlite_setup()) # Stage the setup commands to be ran and run them
run.append(module.sqlite_add()) run = [module.sqlite_setup(), module.sqlite_add()]
#run.append(module.sqlite_time_range(days=10)) log.debug(sqlite_run(run, db=args.db_location))
log.debug("Commands to be ran: " + str(run))
# Pull some useful data and have the module render a template
# Use --db-location to pass to sqlite # The output is in MODULENAME_DAYday.html
log.info("Running SQLite commands") # This generates a report for each of the given day windows
log.debug(sqlite_run(run, db=args.db_location, return_output=True)) for day in (1, 7, 30, 90, 180):
# Fetch the data and log to debug
run = [module.sqlite_time_range(days=day)]
data = sqlite_run(run, db=args.db_location, return_output=True)
log.debug(data)
# Render the template
module.render_template(day, data)
if __name__ == "__main__": if __name__ == "__main__":

@ -20,7 +20,8 @@ import requests_cache
import time import time
from jenkinsapi.custom_exceptions import NoBuildData from jenkinsapi.custom_exceptions import NoBuildData
from jenkinsapi.jenkins import Jenkins from jenkinsapi.jenkins import Jenkins
from os import getenv from jinja2 import Template
from os import getenv, makedirs, path
requests_cache.install_cache("jenkins", backend="sqlite", expire_after=300) requests_cache.install_cache("jenkins", backend="sqlite", expire_after=300)
@ -131,3 +132,58 @@ class JenkinsModule:
command = "SELECT * FROM jenkins WHERE date > %s;" % unix_time command = "SELECT * FROM jenkins WHERE date > %s;" % unix_time
return command return command
def render_template(self, days, data):
"""Render a template with days in the filename, given the data
The above function sqlite_time_range() is ran on the database with
some predetermined date ranges. This function actually interprets that
data, uses Jinja2 to magically render a template, and voila.
"""
# Initialize a (softly) ephemeral dict to store data
jenkins = {}
_data = {"date": [], "nonpassing": [], "failing": [], "total": []}
# Put the data from the DB query into _data
for row in data:
_data["date"].append(row[0])
_data["nonpassing"].append(row[1])
_data["failing"].append(row[2])
_data["total"].append(row[3])
# Get human-readable averages and throw it in a dict
_nonpassing = sum(_data["nonpassing"]) / len(_data["nonpassing"])
_nonpassing = format(_nonpassing, ".1f")
_failing = sum(_data["failing"]) / len(_data["failing"])
_failing = format(_failing, ".1f")
_total = sum(_data["total"]) / len(_data["total"])
_total = format(_total, ".1f")
average = {"nonpassing": _nonpassing,
"failing": _failing,
"total": _total}
# Assign data to the dict Jinja2 is actually going to use
jenkins = {"nonpassing": zip(_data["date"], _data["nonpassing"]),
"failing": zip(_data["date"], _data["failing"]),
"total": zip(_data["date"], _data["total"])}
# Grab our template from templates/ and store it as a Template
t_path = path.join("templates", "jenkins.html")
with open(t_path) as templatef:
template = ""
for text in templatef.readlines():
template += text
template = Template(template)
# Render the template
template = template.render(jenkins=jenkins, average=average, days=days)
# Make the output dir if it doesn't already exist
if not path.exists("output"):
makedirs("output")
# Write it back to the filename in the output dir
with open(path.join("output", "jenkins_%sdays.html" % days),
"w+") as f:
f.write(template)

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- HTML5 compliance -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Import Chart.js 2.9.3 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<!-- Import Bootstrap 4.3.1 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row justify-content-center">
<div class="col">
</div>
</div>
<div class="row justify-content-center">
<div class="col" style="text-align: center;">
<h1>Jenkins data for the past {{ days }} day(s)</h1>
<canvas id="jenkinschart"></canvas>
<h2>Average number of failing jobs: {{ average.failing }}</h2>
<h2>Average number of non-passing jobs: {{ average.nonpassing }}</h2>
<h2>Average number of total jobs: {{ average.total }}</h2>
</div>
</div>
</div>
<!-- This is the actual chart functionality -->
<script>
var ctx = document.getElementById("jenkinschart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: 'Failing Jobs',
backgroundColor: "#FF0000",
//borderColor: "#FF0000",
data: [
{% for timestamp, num in jenkins.failing %}
{
t: new Date({{ timestamp }} * 1000),
y: {{ num }}
},
{% endfor %}
]
},
{
label: 'Non-passing Jobs',
backgroundColor: "#FFFF00",
//borderColor: "#FFFF00",
data: [
{% for timestamp, num in jenkins.nonpassing %}
{
t: new Date({{ timestamp }} * 1000),
y: {{ num }}
},
{% endfor %}
]
},
{
label: 'Total Jobs',
backgroundColor: "#003A72",
//borderColor: "#003A72",
data: [
{% for timestamp, num in jenkins.total %}
{
t: new Date({{ timestamp }} * 1000),
y: {{ num }}
},
{% endfor %}
]
},
]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
}
}]
}
}
});
</script>
</body>
</html>
Loading…
Cancel
Save