mirror of
https://github.com/YunoHost/tartiflette.git
synced 2024-09-03 20:06:08 +02:00
First working version of the app maintainer dashboard
This commit is contained in:
parent
5f456bbcd7
commit
905ee51e6d
4 changed files with 222 additions and 7 deletions
22
app/app.py
22
app/app.py
|
@ -1,6 +1,7 @@
|
||||||
from flask import render_template, make_response, Blueprint
|
from flask import render_template, make_response, Blueprint
|
||||||
from .models.pr import PullRequest
|
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 .models.unlistedapps import UnlistedApp
|
||||||
from .settings import SITE_ROOT
|
from .settings import SITE_ROOT
|
||||||
import json
|
import json
|
||||||
|
@ -118,6 +119,9 @@ def badge(app):
|
||||||
|
|
||||||
badge = "level%s.svg" % level if not level is None else "unknown.svg"
|
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()
|
svg = open("./app/static/badges/%s" % badge).read()
|
||||||
response = make_response(svg)
|
response = make_response(svg)
|
||||||
response.content_type = 'image/svg+xml'
|
response.content_type = 'image/svg+xml'
|
||||||
|
@ -151,3 +155,19 @@ def appsobservatory_unlisted():
|
||||||
|
|
||||||
return render_template("unlistedapps.html", apps=apps)
|
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)
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ class AppList(db.Model):
|
||||||
known_app.maintainers = [ maintainer["name"] for maintainer in maintainers_info ]
|
known_app.maintainers = [ maintainer["name"] for maintainer in maintainers_info ]
|
||||||
|
|
||||||
known_app.maintained = app.get("maintained", True)
|
known_app.maintained = app.get("maintained", True)
|
||||||
|
known_app.state = app["state"]
|
||||||
known_app.ci_enabled = app["state"] == self.state_for_ci
|
known_app.ci_enabled = app["state"] == self.state_for_ci
|
||||||
known_app.public_level = app.get("level", None)
|
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.public_commit = app["git"]["revision"]
|
||||||
known_app.master_commit = g.commit(known_app, "master")
|
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.testing_diff = g.diff(known_app, "master", "testing")["ahead_by"]
|
||||||
known_app.opened_issues = issues_and_prs["nb_issues"]
|
known_app.opened_issues = issues_and_prs["nb_issues"]
|
||||||
known_app.opened_prs = issues_and_prs["nb_prs"]
|
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:
|
else:
|
||||||
known_app.public_commit = "???"
|
known_app.public_commit = "???"
|
||||||
known_app.master_commit = "???"
|
known_app.master_commit = "???"
|
||||||
known_app.testing_diff = -1
|
known_app.testing_diff = -1
|
||||||
known_app.opened_issues = 0
|
known_app.opened_issues = 0
|
||||||
known_app.opened_prs = 0
|
known_app.opened_prs = 0
|
||||||
known_app.public_vs_master_time_diff = 0
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -106,6 +105,7 @@ class App(db.Model):
|
||||||
repo = db.Column(db.String(128), unique=True, nullable=False)
|
repo = db.Column(db.String(128), unique=True, nullable=False)
|
||||||
maintainers = db.Column(db.PickleType)
|
maintainers = db.Column(db.PickleType)
|
||||||
maintained = db.Column(db.Boolean, nullable=False)
|
maintained = db.Column(db.Boolean, nullable=False)
|
||||||
|
state = db.Column(db.String(64), nullable=False)
|
||||||
ci_enabled = db.Column(db.Boolean, nullable=False)
|
ci_enabled = db.Column(db.Boolean, nullable=False)
|
||||||
public_level = db.Column(db.Integer, default=-1, nullable=True)
|
public_level = db.Column(db.Integer, default=-1, nullable=True)
|
||||||
|
|
||||||
|
@ -115,10 +115,11 @@ class App(db.Model):
|
||||||
# 'Status info' stuff
|
# 'Status info' stuff
|
||||||
public_commit = db.Column(db.String(64), nullable=False)
|
public_commit = db.Column(db.String(64), nullable=False)
|
||||||
master_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)
|
testing_diff = db.Column(db.Integer, default=-1)
|
||||||
opened_issues = db.Column(db.Integer, default=-1)
|
opened_issues = db.Column(db.Integer, default=-1)
|
||||||
opened_prs = 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):
|
def __repr__(self):
|
||||||
return '<App %r>' % self.name
|
return '<App %r>' % self.name
|
||||||
|
@ -126,9 +127,13 @@ class App(db.Model):
|
||||||
def init():
|
def init():
|
||||||
pass
|
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):
|
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()
|
branches = AppCIBranch.query.all()
|
||||||
for branch in branches:
|
for branch in branches:
|
||||||
most_recent_test = AppCIResult.query \
|
most_recent_test = AppCIResult.query \
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
<a class="dropdown-item" href="{{ url_for('main.appsobservatory_unlisted')}}">Unlisted apps</a>
|
<a class="dropdown-item" href="{{ url_for('main.appsobservatory_unlisted')}}">Unlisted apps</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ url_for('main.app_maintainer_dash') }}">App maintainer dashboard</span></a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
187
app/templates/maintainer.html
Normal file
187
app/templates/maintainer.html
Normal 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 %}
|
Loading…
Reference in a new issue