mirror of
https://github.com/YunoHost/tartiflette.git
synced 2024-09-03 20:06:08 +02:00
Port the pullrequest dashboard as well
This commit is contained in:
parent
7e14e5860f
commit
6970387bad
13 changed files with 337 additions and 55 deletions
20
app/app.py
20
app/app.py
|
@ -1,5 +1,6 @@
|
||||||
from flask import render_template, Blueprint
|
from flask import render_template, Blueprint
|
||||||
from .models import App, AppCI, AppCIBranch
|
from .models.pr import PullRequest
|
||||||
|
from .models.appci import App, AppCI, AppCIBranch
|
||||||
from .settings import SITE_ROOT
|
from .settings import SITE_ROOT
|
||||||
|
|
||||||
main = Blueprint('main', __name__, url_prefix=SITE_ROOT)
|
main = Blueprint('main', __name__, url_prefix=SITE_ROOT)
|
||||||
|
@ -21,6 +22,23 @@ def index():
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
|
@main.route('/pullrequests')
|
||||||
|
def pullrequests():
|
||||||
|
|
||||||
|
prs = PullRequest.query.all()
|
||||||
|
|
||||||
|
prs = sorted(prs, key=lambda pr: (pr.review_priority, pr.created), reverse=True)
|
||||||
|
|
||||||
|
active_prs = [ pr for pr in prs if pr.review_priority >= 0]
|
||||||
|
count_by_team = { "all": len(active_prs),
|
||||||
|
"core": len([pr for pr in active_prs if pr.repo.team == "core"]),
|
||||||
|
"apps": len([pr for pr in active_prs if pr.repo.team == "apps"]),
|
||||||
|
"infra": len([pr for pr in active_prs if pr.repo.team == "infra"]),
|
||||||
|
"doc": len([pr for pr in active_prs if pr.repo.team == "doc"]) }
|
||||||
|
|
||||||
|
return render_template("pullrequests.html", prs=prs, count_by_team=count_by_team)
|
||||||
|
|
||||||
|
|
||||||
@main.route('/appci/branch/<branch>')
|
@main.route('/appci/branch/<branch>')
|
||||||
def appci_branch(branch):
|
def appci_branch(branch):
|
||||||
|
|
||||||
|
|
1
app/models/__init__.py
Normal file
1
app/models/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from . import appci, pr
|
|
@ -1,12 +1,10 @@
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from .. import db
|
||||||
|
|
||||||
from . import db
|
|
||||||
|
|
||||||
class AppList(db.Model):
|
class AppList(db.Model):
|
||||||
|
|
||||||
|
@ -293,7 +291,7 @@ class Github():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
from .settings import GITHUB_USER, GITHUB_TOKEN
|
from ..settings import GITHUB_USER, GITHUB_TOKEN
|
||||||
|
|
||||||
self.user = GITHUB_USER
|
self.user = GITHUB_USER
|
||||||
self.token = GITHUB_TOKEN
|
self.token = GITHUB_TOKEN
|
133
app/models/pr.py
Normal file
133
app/models/pr.py
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from .. import db
|
||||||
|
|
||||||
|
|
||||||
|
class Repo(db.Model):
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
name = db.Column(db.String(64), unique=True, nullable=False)
|
||||||
|
team = db.Column(db.String(64), nullable=False)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<Repo %r>' % self.name
|
||||||
|
|
||||||
|
def init():
|
||||||
|
|
||||||
|
d = {
|
||||||
|
"core": ["yunohost",
|
||||||
|
"yunohost-admin",
|
||||||
|
"SSOwat",
|
||||||
|
"moulinette",
|
||||||
|
"Vagrantfile",
|
||||||
|
"ynh-dev"],
|
||||||
|
|
||||||
|
"doc": ["doc",
|
||||||
|
"Simone",
|
||||||
|
"project-organization"],
|
||||||
|
|
||||||
|
"apps": ["apps",
|
||||||
|
"CI_package_check",
|
||||||
|
"example_ynh",
|
||||||
|
"package_linter",
|
||||||
|
"package_check"],
|
||||||
|
|
||||||
|
"infra": ["build.yunohost.org",
|
||||||
|
"dynette",
|
||||||
|
"YunoPorts",
|
||||||
|
"cd_build",
|
||||||
|
"install_script",
|
||||||
|
"trotinette",
|
||||||
|
"bicyclette",
|
||||||
|
"install-app",
|
||||||
|
"tartiflette",
|
||||||
|
"vinaigrette"]
|
||||||
|
}
|
||||||
|
|
||||||
|
for team, repos in d.items():
|
||||||
|
for repo in repos:
|
||||||
|
yield Repo(name=repo, team=team)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
|
||||||
|
print("Updating PRs for repo %s ..." % self.name)
|
||||||
|
|
||||||
|
PullRequest.query.filter_by(repo=self).delete()
|
||||||
|
|
||||||
|
issues = requests.get("https://api.github.com/repos/yunohost/%s/issues?per_page=100" % self.name)
|
||||||
|
issues = json.loads(issues.text)
|
||||||
|
issues = [i for i in issues if "pull_request" in i.keys()]
|
||||||
|
|
||||||
|
for issue in issues:
|
||||||
|
print(" > Analyzing %s-%s" % (self.name, issue["number"]))
|
||||||
|
db.session.add(PullRequest(self, issue))
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
class PullRequest(db.Model):
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
id_ = db.Column(db.String(64), unique=True, nullable=False)
|
||||||
|
title = db.Column(db.String(256), nullable=False)
|
||||||
|
labels = db.Column(db.PickleType)
|
||||||
|
url = db.Column(db.String(128), nullable=False)
|
||||||
|
milestone = db.Column(db.String(32), nullable=False)
|
||||||
|
|
||||||
|
review_priority = db.Column(db.Integer)
|
||||||
|
|
||||||
|
created = db.Column(db.DateTime)
|
||||||
|
updated = db.Column(db.DateTime)
|
||||||
|
|
||||||
|
repo = db.relationship(Repo, backref='prs', lazy=True, uselist=False)
|
||||||
|
repo_id = db.Column(db.ForeignKey(Repo.id))
|
||||||
|
|
||||||
|
def __init__(self, repo, issue):
|
||||||
|
|
||||||
|
self.repo = repo
|
||||||
|
self.title = issue["title"]
|
||||||
|
self.labels = [label["name"] for label in issue["labels"]]
|
||||||
|
self.milestone = issue["milestone"]["title"] if issue["milestone"] else ""
|
||||||
|
|
||||||
|
self.id_ = "%s-%s" % (repo.name, issue["number"])
|
||||||
|
|
||||||
|
self.created = datetime.datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
self.updated = datetime.datetime.strptime(issue["updated_at"], "%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
self.url = issue["pull_request"]["html_url"]
|
||||||
|
|
||||||
|
for size in ["small", "medium", "big"]:
|
||||||
|
if "%s decision" % size in self.labels:
|
||||||
|
self.labels.remove("%s decision" % size)
|
||||||
|
self.labels.insert(0, size)
|
||||||
|
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
if (now - self.created).days > 60 and (now - self.updated).days > 30:
|
||||||
|
self.labels.append("dying")
|
||||||
|
|
||||||
|
self.review_priority = self.get_review_priority()
|
||||||
|
|
||||||
|
def get_review_priority(self):
|
||||||
|
if "important" in self.labels:
|
||||||
|
base_priority = 100
|
||||||
|
elif "opinion needed" in self.labels:
|
||||||
|
base_priority = 50
|
||||||
|
elif "postponed" in self.labels or "inactive" in self.labels:
|
||||||
|
base_priority = -100
|
||||||
|
else:
|
||||||
|
base_priority = 0
|
||||||
|
|
||||||
|
if "work needed" in self.labels:
|
||||||
|
base_priority += -5
|
||||||
|
|
||||||
|
if "dying" in self.labels and base_priority > -100:
|
||||||
|
base_priority += 5
|
||||||
|
|
||||||
|
return base_priority
|
||||||
|
|
||||||
|
def init():
|
||||||
|
pass
|
||||||
|
|
15
app/static/css/bootstrap.min.css
vendored
15
app/static/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -8,15 +8,11 @@
|
||||||
margin-top:4em;
|
margin-top:4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app-ci-test-results
|
a { color:#007bff; }
|
||||||
{
|
|
||||||
margin-left:auto;
|
|
||||||
margin-right:auto;
|
|
||||||
/*width:1000px;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
table, thead, tbody { display: block; width: 100%;}
|
.ci-app-table > thead, .ci-app-table > tbody { display: block; width: 100%;}
|
||||||
table.ci-app { margin: 0 auto; margin-top: 100px; max-width: 1070px; overflow-x: visible; }
|
.ci-app-table { margin: 0 auto; margin-top: 100px; max-width: 1070px; overflow-x: visible; }
|
||||||
|
.ci-app-table th, .ci-app-table td { display: block; border: none; padding; 0px;float: left; height:33px; width: 33px; margin: 5px; }
|
||||||
|
|
||||||
th.ci-app-test-title
|
th.ci-app-test-title
|
||||||
{
|
{
|
||||||
|
@ -40,24 +36,32 @@ th.ci-app-test-title > div > span
|
||||||
border:none;
|
border:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
th, td { display: block; border: none; padding; 0px;float: left; height:33px; width: 33px; margin: 5px; }
|
|
||||||
|
|
||||||
.ci-app-row-title { text-align: center; width:150px; }
|
|
||||||
td.ci-app-test-result { text-align:center; padding: 14px 8px 8px 8px; }
|
td.ci-app-test-result { text-align:center; padding: 14px 8px 8px 8px; }
|
||||||
td.ci-app-test-result > div { position:relative; background-color: #bdc3c7; border-radius:5px; width: 18px; height: 18px;}
|
td.ci-app-test-result > div { position:relative; background-color: #bdc3c7; border-radius:5px; width: 18px; height: 18px;}
|
||||||
td.ci-app-test-result > div.success { background-color: rgb(46,204,83); }
|
td.ci-app-test-result > div.success { background-color: rgb(46,204,83); }
|
||||||
td.ci-app-test-result > div.danger { background-color: rgb(225,80,62); }
|
td.ci-app-test-result > div.danger { background-color: rgb(225,80,62); }
|
||||||
|
|
||||||
.table > thead > tr > th { border : none; }
|
.ci-app-table > thead > tr > th { border : none; }
|
||||||
.table > tbody > tr > td { border : none; }
|
.ci-app-table > tbody > tr > td { border : none; }
|
||||||
|
.ci-app-table .ci-app-row-title { text-align: center; width:150px; }
|
||||||
|
.ci-app-table .ci-app-test-info { width:150px; font-size: 12px; }
|
||||||
|
|
||||||
.canvasjs-chart-credit { display: none; }
|
.canvasjs-chart-credit { display: none; }
|
||||||
|
|
||||||
.ci-app-test-info { width:150px; font-size: 12px; }
|
|
||||||
.daysAgo a { color: #777; }
|
.daysAgo a { color: #777; }
|
||||||
.official-star { color: #f0ad4e; }
|
.official-star { color: #f0ad4e; }
|
||||||
.level-improvement { color: #2d2; }
|
.level-improvement { color: #2d2; }
|
||||||
.level-regression { color: #f22; }
|
.level-regression { color: #f22; }
|
||||||
.level-unknown { color: #aaa; }
|
.level-unknown { color: #aaa; }
|
||||||
.text-warning { color: #f0ad0e !important; }
|
.text-warning { color: #f0ad0e !important; }
|
||||||
|
|
||||||
|
.table th { border-top: none; }
|
||||||
|
|
||||||
|
.table-pullrequests { width: 1250px; font-family: sans-serif; border: none; }
|
||||||
|
|
||||||
|
.column-pr-title {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width:400px;
|
||||||
|
}
|
||||||
|
|
|
@ -2,21 +2,18 @@
|
||||||
function daysAgo(timestamp) {
|
function daysAgo(timestamp) {
|
||||||
var difference = Math.round(+new Date()/1000) - timestamp;
|
var difference = Math.round(+new Date()/1000) - timestamp;
|
||||||
var daysDifference = Math.round(difference/60/60/24);
|
var daysDifference = Math.round(difference/60/60/24);
|
||||||
//return (new Date(timestamp*1000));
|
|
||||||
return "(" + daysDifference + " days ago)";
|
return "(" + daysDifference + " days ago)";
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".daysAgo").each(function () {
|
$(".daysAgo").each(function () {
|
||||||
var t = $(this).attr("timestamp");
|
var t = $(this).attr("timestamp");
|
||||||
var console = $(this).attr("console");
|
var href = $(this).attr("href");
|
||||||
if (t) {
|
if (t) {
|
||||||
link = document.createElement('a');
|
link = document.createElement('a');
|
||||||
link.setAttribute('href', console);
|
link.setAttribute('href', href);
|
||||||
link.innerHTML = daysAgo(t);
|
link.innerHTML = daysAgo(t);
|
||||||
this.appendChild(link);
|
this.appendChild(link);
|
||||||
}
|
}
|
||||||
// $(this).text(daysAgo(t));
|
|
||||||
//}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".ci-app-test-result div[value=True]").addClass("success")
|
$(".ci-app-test-result div[value=True]").addClass("success")
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2 class="text-center">{{ app.name.title() }}</h2>
|
<h2 class="text-center my-3">{{ app.name.title() }}</h2>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="app-ci-test-results">
|
<div class="mx-auto">
|
||||||
<div>
|
<div>
|
||||||
<table class="table table-responsive ci-app">
|
<table class="table table-responsive ci-app-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ci-app-row-title"><div></div></th>
|
<th class="ci-app-row-title"></th>
|
||||||
<th class="ci-app-test-title"><div>Level</div></th>
|
<th class="ci-app-test-title"><div>Level</div></th>
|
||||||
{% for test in tests %}
|
{% for test in tests %}
|
||||||
<th class="ci-app-test-title"><div><span>{{ test }}</span></div></th>
|
<th class="ci-app-test-title"><div><span>{{ test }}</span></div></th>
|
||||||
|
@ -36,9 +36,9 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<td class="ci-app-test-info">
|
<td class="ci-app-test-info">
|
||||||
{% if result.date == None %}
|
{% if result.date == None %}
|
||||||
<span class="daysAgo" console="{{ result.url }}">???</span>
|
<span class="daysAgo" href="{{ result.url }}">???</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="daysAgo" timestamp="{{ result.date.timestamp() }}" console="{{ result.url }}"></span>
|
<span class="daysAgo" timestamp="{{ result.date.timestamp() }}" href="{{ result.url }}"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if result.commit != result.app.master_commit %}
|
{% if result.commit != result.app.master_commit %}
|
||||||
<span class="oi oi-clock text-warning"
|
<span class="oi oi-clock text-warning"
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2 class="text-center">{{ branch.display_name }}</h2>
|
<h2 class="text-center my-3">{{ branch.display_name }}</h2>
|
||||||
<div id="levelSummary" style="height: 270px;" class="col-sm-6 offset-sm-3"></div>
|
<div id="levelSummary" style="height: 270px;" class="col-sm-6 offset-sm-3 my-3"></div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="app-ci-test-results">
|
<div class="mx-auto">
|
||||||
<div>
|
<div>
|
||||||
<table class="table table-responsive ci-app">
|
<table class="table table-responsive ci-app-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ci-app-row-title"><div></div></th>
|
<th class="ci-app-row-title"></th>
|
||||||
<th class="ci-app-test-title"><div>Level</div></th>
|
<th class="ci-app-test-title"><div>Level</div></th>
|
||||||
{% for test in tests %}
|
{% for test in tests %}
|
||||||
<th class="ci-app-test-title"><div><span>{{ test }}</span></div></th>
|
<th class="ci-app-test-title"><div><span>{{ test }}</span></div></th>
|
||||||
|
@ -40,9 +40,9 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<td class="ci-app-test-info">
|
<td class="ci-app-test-info">
|
||||||
{% if result.date == None %}
|
{% if result.date == None %}
|
||||||
<span class="daysAgo" console="{{ result.url }}">???</span>
|
<span class="daysAgo" href="{{ result.url }}">???</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="daysAgo" timestamp="{{ result.date.timestamp() }}" console="{{ result.url }}"></span>
|
<span class="daysAgo" timestamp="{{ result.date.timestamp() }}" href="{{ result.url }}"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if result.commit != result.app.master_commit %}
|
{% if result.commit != result.app.master_commit %}
|
||||||
<span class="oi oi-clock text-warning"
|
<span class="oi oi-clock text-warning"
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2 class="text-center">{{ ref.display_name }} vs. {{ target.display_name }}</h2>
|
<h2 class="text-center my-3">{{ ref.display_name }} vs. {{ target.display_name }}</h2>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="app-ci-test-results">
|
<div class="mx-auto">
|
||||||
<div>
|
<div>
|
||||||
<table class="table table-responsive ci-app">
|
<table class="table table-responsive ci-app-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ci-app-row-title"><div></div></th>
|
<th class="ci-app-row-title"></th>
|
||||||
<th class="ci-app-test-title"><div>{{ ref.display_name }} </div></th>
|
<th class="ci-app-test-title"><div>{{ ref.display_name }} </div></th>
|
||||||
<th class="ci-app-test-title"><div>{{ target.display_name }} </div></th>
|
<th class="ci-app-test-title"><div>{{ target.display_name }} </div></th>
|
||||||
<th class="ci-app-test-title"></th>
|
<th class="ci-app-test-title"></th>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||||
<a class="navbar-brand" href="#">YunoHost Dev Dashboard</a>
|
<a class="navbar-brand" href="#">YunoHost Dev Dashboard</a>
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||||
data-target="#navbarColor01">
|
data-target="#navbarColor01">
|
||||||
|
|
107
app/templates/pullrequests.html
Normal file
107
app/templates/pullrequests.html
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="text-center my-5">What should you review today ?</h3>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="mx-auto mb-5">
|
||||||
|
<ul id="select-team" class="nav nav-pills">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="select-team-all" class="nav-link active" href="javascript:void(0)" onclick="filter('')">All <span class="badge badge-secondary badge-pill">{{ count_by_team["all"] }}</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item"><a id="select-team-core" class="nav-link" href="javascript:void(0)" onclick="filter('team-core')">Core <span class="badge badge-secondary badge-pill">{{ count_by_team["core"] }}</span></a></li>
|
||||||
|
<li class="nav-item"><a id="select-team-apps" class="nav-link" href="javascript:void(0)" onclick="filter('team-apps')">Apps <span class="badge badge-secondary badge-pill">{{ count_by_team["apps"] }}</span></a/li>
|
||||||
|
<li class="nav-item"><a id="select-team-infra" class="nav-link" href="javascript:void(0)" onclick="filter('team-infra')">Infra / dist <span class="badge badge-secondary badge-pill">{{ count_by_team["infra"] }}</span></a></li>
|
||||||
|
<li class="nav-item"><a id="select-team-doc" class="nav-link" href="javascript:void(0)" onclick="filter('team-doc')">Doc <span class="badge badge-secondary badge-pill">{{ count_by_team["doc"] }}</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="mx-auto">
|
||||||
|
<table id="pullrequests" class="table table-responsive table-sm table-pullrequests">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Created</th>
|
||||||
|
<th>Labels</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for pr in prs %}
|
||||||
|
<tr class="team-{{ pr.repo.team }}">
|
||||||
|
<td class="col-md-2 text-center">
|
||||||
|
<a class="btn btn-sm mx-4 py-2 px-3
|
||||||
|
{% if pr.review_priority >= 90 %}btn-warning{% else %}
|
||||||
|
{% if pr.review_priority >= 40 %}btn-success{% else %}
|
||||||
|
{% if pr.review_priority >= -10 %}btn-info{% else %}
|
||||||
|
{% if pr.review_priority >= -60 %}btn-secondary{% else %}
|
||||||
|
btn-link{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %} text-uppercase font-weight-bold"
|
||||||
|
href="{{ pr.url }}">{{ pr.id_ }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="column-pr-title font-weight-bold"><strong>{{ pr.title }}</strong></td>
|
||||||
|
<td class="col-md-1 daysAgo" timestamp="{{ pr.created.timestamp() }}"
|
||||||
|
style="font-size: 12px;" ></td>
|
||||||
|
<td class="col-md-4">
|
||||||
|
{% for label in pr.labels %}
|
||||||
|
<span class="badge ml-1
|
||||||
|
{% if label == "important" %}badge-danger{%else%}
|
||||||
|
{% if label == "opinion needed" %}badge-warning{%else%}
|
||||||
|
{% if label == "small" %}badge-info{%else%}
|
||||||
|
{% if label == "medium" %}badge-info{%else%}
|
||||||
|
{% if label == "big" %}badge-info{%else%}
|
||||||
|
{% if label == "ready to merge" %}badge-success{%else%}
|
||||||
|
{% if label == "work needed" %}badge-primary{%else%}
|
||||||
|
{% if label == "inactive" %}badge-secondary{%else%}
|
||||||
|
{% if label == "postponed" %}badge-secondary{%else%}
|
||||||
|
{% if label == "dying" %}badge-danger{%else%}
|
||||||
|
badge-secondary
|
||||||
|
{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}{%endif%}
|
||||||
|
">{{ label }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function filter(team) {
|
||||||
|
// Declare variables
|
||||||
|
var input, filter, table, tr, td, i;
|
||||||
|
table = document.getElementById("pullrequests");
|
||||||
|
tr = table.getElementsByTagName("tr");
|
||||||
|
// Loop through all table rows, and hide those who don't match the search query
|
||||||
|
for (i = 0; i < tr.length; i++)
|
||||||
|
{
|
||||||
|
if (team == '') { tr[i].style.display = ""; }
|
||||||
|
else if (tr[i].classList == "") { tr[i].style.display = ""; }
|
||||||
|
else if (tr[i].classList.contains(team)) { tr[i].style.display = ""; }
|
||||||
|
else { tr[i].style.display = "none"; }
|
||||||
|
}
|
||||||
|
selector = document.getElementById("select-team");
|
||||||
|
a = selector.getElementsByTagName("a");
|
||||||
|
if (team == "") { team = "team-all"; }
|
||||||
|
for (i = 0; i < a.length; i++)
|
||||||
|
{
|
||||||
|
if (a[i].getAttribute("id") == "select-".concat(team))
|
||||||
|
{
|
||||||
|
a[i].classList.add("active");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a[i].classList.remove("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
33
manage.py
33
manage.py
|
@ -5,23 +5,34 @@ from app import db, create_app
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
manager = Manager(app)
|
manager = Manager(app)
|
||||||
manager.add_command('shell', Shell(make_context=lambda:{"app":app, "db":db}))
|
manager.add_command('shell', Shell(make_context=lambda:{"app":app, "db":db}))
|
||||||
manager.add_command('nuke', Nuke(db))
|
manager.add_command('nuke', Nuke(db))
|
||||||
manager.add_command('init', Init(db))
|
manager.add_command('init', Init(db))
|
||||||
manager.add_command('update', Update(db))
|
manager.add_command('update-appci', Update(db, "appci"))
|
||||||
|
manager.add_command('update-pr', Update(db, "pr"))
|
||||||
manager.run()
|
manager.run()
|
||||||
|
|
||||||
|
|
||||||
class Update(Command):
|
class Update(Command):
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db, what):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
self.what = what
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
from app.models import AppCI
|
if self.what == "appci":
|
||||||
AppCI.update()
|
from app.models.appci import AppCI
|
||||||
|
AppCI.update()
|
||||||
|
elif self.what == "pr":
|
||||||
|
from app.models.pr import Repo
|
||||||
|
for repo in Repo.query.all():
|
||||||
|
repo.update()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Nuke(Command):
|
class Nuke(Command):
|
||||||
|
@ -32,7 +43,9 @@ class Nuke(Command):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
import app.models
|
import app.models.appci
|
||||||
|
import app.models.pr
|
||||||
|
|
||||||
print("> Droping tables...")
|
print("> Droping tables...")
|
||||||
self.db.drop_all()
|
self.db.drop_all()
|
||||||
print("> Creating tables...")
|
print("> Creating tables...")
|
||||||
|
@ -40,6 +53,7 @@ class Nuke(Command):
|
||||||
print("> Comitting sessions...")
|
print("> Comitting sessions...")
|
||||||
self.db.session.commit()
|
self.db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
class Init(Command):
|
class Init(Command):
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
|
@ -48,8 +62,12 @@ class Init(Command):
|
||||||
def run(self):
|
def run(self):
|
||||||
import app.models
|
import app.models
|
||||||
|
|
||||||
stuff_in_module = [ app.models.__dict__.get(s) for s in dir(app.models) ]
|
# Black magic to extract list of models from 'models' folder
|
||||||
models = [ m for m in stuff_in_module if isinstance(m, type(db.Model)) ]
|
submodules = [ app.models.__dict__.get(m) for m in dir(app.models) if not m.startswith('__') ]
|
||||||
|
stuff = []
|
||||||
|
for submodule in submodules:
|
||||||
|
stuff.extend([submodule.__dict__.get(s) for s in dir(submodule)])
|
||||||
|
models = [s for s in stuff if isinstance(s, type(db.Model))]
|
||||||
|
|
||||||
for model in models:
|
for model in models:
|
||||||
objs = model.init()
|
objs = model.init()
|
||||||
|
@ -59,5 +77,6 @@ class Init(Command):
|
||||||
db.session.add(obj)
|
db.session.add(obj)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue