First working version of the app maintainer dashboard

This commit is contained in:
Alexandre Aubin 2018-11-07 20:12:36 +01:00
parent 5f456bbcd7
commit 905ee51e6d
4 changed files with 222 additions and 7 deletions

View file

@ -1,6 +1,7 @@
from flask import render_template, make_response, Blueprint
from .models.pr import PullRequest
from .models.appci import App, AppCI, AppCIBranch
from .models.applists import App
from .models.appci import AppCI, AppCIBranch
from .models.unlistedapps import UnlistedApp
from .settings import SITE_ROOT
import json
@ -118,6 +119,9 @@ def badge(app):
badge = "level%s.svg" % level if not level is None else "unknown.svg"
if not app.ci_enabled:
badge = "unknown.svg"
svg = open("./app/static/badges/%s" % badge).read()
response = make_response(svg)
response.content_type = 'image/svg+xml'
@ -151,3 +155,19 @@ def appsobservatory_unlisted():
return render_template("unlistedapps.html", apps=apps)
@main.route('/app_maintainer_dash')
def app_maintainer_dash():
maintainers = set()
apps = App.query.all()
for app in apps:
maintainers.update(app.maintainers)
for test in app.most_recent_tests_per_branch():
if test.branch.name == "stable":
app.ci_level = test.level
maintainers = sorted(maintainers, key=lambda m: m.lower())
apps = sorted(apps, key=lambda app: app.name.lower())
return render_template("maintainer.html", maintainers=maintainers, apps=apps)

View file

@ -70,6 +70,7 @@ class AppList(db.Model):
known_app.maintainers = [ maintainer["name"] for maintainer in maintainers_info ]
known_app.maintained = app.get("maintained", True)
known_app.state = app["state"]
known_app.ci_enabled = app["state"] == self.state_for_ci
known_app.public_level = app.get("level", None)
@ -78,20 +79,18 @@ class AppList(db.Model):
known_app.public_commit = app["git"]["revision"]
known_app.master_commit = g.commit(known_app, "master")
known_app.public_commit_date = g.commit_date(known_app, known_app.public_commit)
known_app.master_commit_date = g.commit_date(known_app, known_app.master_commit)
known_app.testing_diff = g.diff(known_app, "master", "testing")["ahead_by"]
known_app.opened_issues = issues_and_prs["nb_issues"]
known_app.opened_prs = issues_and_prs["nb_prs"]
known_app.public_vs_master_time_diff = \
(g.commit_date(known_app, known_app.master_commit) -
g.commit_date(known_app, known_app.public_commit)).days
else:
known_app.public_commit = "???"
known_app.master_commit = "???"
known_app.testing_diff = -1
known_app.opened_issues = 0
known_app.opened_prs = 0
known_app.public_vs_master_time_diff = 0
try:
db.session.commit()
@ -106,6 +105,7 @@ class App(db.Model):
repo = db.Column(db.String(128), unique=True, nullable=False)
maintainers = db.Column(db.PickleType)
maintained = db.Column(db.Boolean, nullable=False)
state = db.Column(db.String(64), nullable=False)
ci_enabled = db.Column(db.Boolean, nullable=False)
public_level = db.Column(db.Integer, default=-1, nullable=True)
@ -115,10 +115,11 @@ class App(db.Model):
# 'Status info' stuff
public_commit = db.Column(db.String(64), nullable=False)
master_commit = db.Column(db.String(64), nullable=False)
public_commit_date = db.Column(db.DateTime, nullable=True)
master_commit_date = db.Column(db.DateTime, nullable=True)
testing_diff = db.Column(db.Integer, default=-1)
opened_issues = db.Column(db.Integer, default=-1)
opened_prs = db.Column(db.Integer, default=-1)
public_vs_master_time_diff = db.Column(db.Integer, default=9999)
def __repr__(self):
return '<App %r>' % self.name
@ -126,9 +127,13 @@ class App(db.Model):
def init():
pass
@property
def public_vs_master_time_diff(self):
return (self.public_commit_date - self.master_commit_date).days
def most_recent_tests_per_branch(self):
from appci import AppCIBranch, AppCIResult, AppCI
from app.models.appci import AppCIBranch, AppCIResult, AppCI
branches = AppCIBranch.query.all()
for branch in branches:
most_recent_test = AppCIResult.query \

View file

@ -50,6 +50,9 @@
<a class="dropdown-item" href="{{ url_for('main.appsobservatory_unlisted')}}">Unlisted apps</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.app_maintainer_dash') }}">App maintainer dashboard</span></a>
</li>
</ul>
</div>
</nav>

View file

@ -0,0 +1,187 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="mx-auto">
<select id="maintainer-select">
<option value="all">All</option>
<option value="nobody">Nobody / Unmaintained</option>
{% for maintainer in maintainers %}
<option value="{{ maintainer.lower()|replace(" ", "") }}">{{ maintainer }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<div class="mx-auto">
<div>
<table class="table table-responsive ci-app-table">
<thead>
<tr>
<th class="ci-app-row-title">App</th>
<th class="ci-app-test-title"><div>Declared state</div></th>
<th class="ci-app-test-title"><div>Maintained</div></th>
<th class="ci-app-test-title"><div>Public level</div></th>
<th class="ci-app-test-title"><div>CI level</div></th>
<th class="ci-app-test-title"><div># opened issues</div></th>
<th class="ci-app-test-title"><div># opened PR</div></th>
<th class="ci-app-test-title"><div>Last commit</div></th>
<th></th>
</tr>
</thead>
<tbody>
{% for app in apps %}
<tr class="appline" app="{{ app.name }}" maintainers="{% for m in app.maintainers %}{{ m.lower()|replace(" ", "") }}|{% endfor %}" maintained="{{ app.maintained }}">
<td class="ci-app-row-title">
<a href="{{ url_for('main.appci_app', app=app.name) }}">
<span class="font-weight-bold" title="More tests / info for this app">
{{ app.name }}</span>
</a>
</td>
<td>
{% if app.list.name == "official" %}
<span class="official-star oi oi-star" title="Official" aria-hidden="true"></span>
{% elif app.state == "working" %}
<span class="text-success oi oi-circle-check" title="Working" aria-hidden="true"></span>
{% elif app.state == "inprogress" %}
<span class="text-warning oi oi-wrench" title="In progress" aria-hidden="true"></span>
{% else %}
<span class="text-danger oi oi-fire" title="Not working" aria-hidden="true"></span>
{% endif %}
</td>
{% if app.maintained %}
<td class="text-success">
<span class="oi oi-circle-check" aria-hidden="true"></span>
{% else %}
<td class="text-warning">
<span class="oi oi-warning" aria-hidden="true"></span>
{% endif %}
</td>
{% if app.state == "inprogress" or app.state == "notworking" %}
<td class="ci-app-level"><div title="Public Level"></div></td>
<td class="ci-app-level"><div title="CI Level"></div></td>
{% else %}
<td class="ci-app-level
{% if app.public_level == None or app.public_level == -1 or app.public_level == "?" %}
table-active
{% elif app.public_level <= 0 %}
table-danger
{% elif app.public_level <= 2 %}
table-warning
{% else %}
table-success
{% endif %}
" value="{{ app.public_level }}">
<div title="Public Level"><strong>{{ app.public_level if app.public_level >= 0 else "?" }}</strong></div>
</td>
<td class="ci-app-level
{% if app.ci_level == None or app.ci_level == -1 or app.ci_level == "?" %}
table-active
{% elif app.ci_level <= 0 %}
table-danger
{% elif app.ci_level <= 2 %}
table-warning
{% else %}
table-success
{% endif %}
" value="{{ app.ci_level }}">
<div title="CI Level"><strong>{{ app.ci_level if app.ci_level and app.ci_level >= 0 else "?" }}</strong></div>
</td>
{% endif %}
<td class="font-weight-bold
{% if app.opened_issues >= 10 %}
text-danger
{% elif app.opened_issues >= 5 %}
text-warning
{% elif app.opened_issues > 0 %}
text-active
{% else %}
text-success
{% endif %}
">{{ app.opened_issues }}</a></td>
<td class="font-weight-bold
{% if app.opened_prs > 0 %}
text-info
{% endif %}
">{{ app.opened_prs }}</td>
<td class="ci-app-test-info">
{% if app.public_commit_date %}
<span class="daysAgo" timestamp={{ app.public_commit_date.timestamp() }}></span></td>
{% else %}
<span class="daysAgo">???</span></td>
{% endif %}
</td>
<td class="px-0">
<a href="{{ app.repo }}">
<span class="oi oi-external-link text-info"
aria-hidden="true"
title="To the Git repo!"></span>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
window.onload = function () {
$('#maintainer-select').on('change', function() {
var maintainer = this.value;
if (maintainer == "all")
{
$(".appline").show();
return;
}
else if (maintainer == "nobody")
{
$(".appline").each(function (i) {
if ((this.attributes["maintainers"].value == "") || (this.attributes["maintained"].value == "False"))
{
$(this).show();
}
else {
$(this).hide();
}
});
}
else
{
$(".appline").each(function (i) {
var maintainers = this.attributes["maintainers"].value.split("|");
if (maintainers.includes(maintainer)) {
$(this).show();
}
else {
$(this).hide();
}
});
}
});
}
</script>
{% endblock %}