2018-11-05 17:17:03 +01:00
|
|
|
import re
|
|
|
|
import os
|
|
|
|
import time
|
|
|
|
import json
|
|
|
|
import requests
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
from .. import db
|
|
|
|
|
|
|
|
|
|
|
|
class AppList(db.Model):
|
|
|
|
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
name = db.Column(db.String(64), unique=True, nullable=False)
|
|
|
|
url = db.Column(db.String(128), nullable=False)
|
|
|
|
state_for_ci = db.Column(db.String(32), nullable=False)
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return '<AppList %r>' % self.name
|
|
|
|
|
|
|
|
def init():
|
|
|
|
yield AppList(name='official',
|
|
|
|
url="https://app.yunohost.org/official.json",
|
|
|
|
state_for_ci='validated')
|
|
|
|
yield AppList(name='community',
|
|
|
|
url="https://app.yunohost.org/community.json",
|
|
|
|
state_for_ci='working')
|
|
|
|
|
|
|
|
def update():
|
|
|
|
|
|
|
|
applists = AppList.query.all()
|
|
|
|
for applist in applists:
|
|
|
|
applist.update_list()
|
|
|
|
|
|
|
|
def update_list(self):
|
|
|
|
|
|
|
|
g = Github()
|
|
|
|
|
2018-12-12 17:32:23 +01:00
|
|
|
raw_apps = json.loads(requests.get(self.url).text)
|
2018-11-05 17:17:03 +01:00
|
|
|
|
2019-05-14 19:00:38 +02:00
|
|
|
for name in sorted(raw_apps.keys()):
|
|
|
|
|
|
|
|
app = raw_apps[name]
|
2018-11-05 17:17:03 +01:00
|
|
|
|
|
|
|
app['url'] = app["git"]["url"].strip('/')
|
|
|
|
|
|
|
|
# Try to find an app for this name
|
|
|
|
known_app = App.query.filter_by(name=name).first()
|
|
|
|
|
|
|
|
# If this app is not already registered...
|
|
|
|
if not known_app:
|
|
|
|
print("Adding new app {}".format(name))
|
|
|
|
known_app = App(name=name,
|
|
|
|
repo=app["url"],
|
|
|
|
list=self,
|
|
|
|
public_commit=app["git"]["revision"])
|
|
|
|
db.session.add(known_app)
|
|
|
|
else:
|
|
|
|
print("Updating already known app {}".format(name))
|
|
|
|
|
|
|
|
maintainers_info = app["manifest"].get("maintainer", app["manifest"].get("developer", None))
|
|
|
|
if maintainers_info is None:
|
|
|
|
known_app.maintainers = [ ]
|
|
|
|
if isinstance(maintainers_info, dict):
|
|
|
|
if maintainers_info["name"] == "-" or maintainers_info["name"] == "":
|
|
|
|
known_app.maintainers = [ ]
|
|
|
|
else:
|
|
|
|
known_app.maintainers = re.split(", | et ", maintainers_info["name"])
|
|
|
|
if isinstance(maintainers_info, list):
|
|
|
|
known_app.maintainers = [ maintainer["name"] for maintainer in maintainers_info ]
|
|
|
|
|
|
|
|
known_app.maintained = app.get("maintained", True)
|
2019-05-14 19:00:38 +02:00
|
|
|
# Quick and dirty fix to convert maintained state to boolean
|
|
|
|
if known_app.maintained == "orphaned":
|
|
|
|
known_app.maintained = False
|
|
|
|
elif isinstance(known_app.maintained, str):
|
|
|
|
known_app.maintained = True
|
2018-11-07 20:12:36 +01:00
|
|
|
known_app.state = app["state"]
|
2018-11-05 17:17:03 +01:00
|
|
|
known_app.ci_enabled = app["state"] == self.state_for_ci
|
|
|
|
known_app.public_level = app.get("level", None)
|
|
|
|
|
|
|
|
if "github" in known_app.repo:
|
|
|
|
issues_and_prs = g.issues(known_app)
|
|
|
|
|
|
|
|
known_app.public_commit = app["git"]["revision"]
|
|
|
|
known_app.master_commit = g.commit(known_app, "master")
|
2018-11-07 20:12:36 +01:00
|
|
|
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)
|
2019-05-14 19:00:38 +02:00
|
|
|
known_app.testing_pr = g.testing_pr(known_app)
|
2018-11-05 17:17:03 +01:00
|
|
|
known_app.opened_issues = issues_and_prs["nb_issues"]
|
|
|
|
known_app.opened_prs = issues_and_prs["nb_prs"]
|
|
|
|
|
|
|
|
else:
|
|
|
|
known_app.public_commit = "???"
|
|
|
|
known_app.master_commit = "???"
|
2019-05-14 19:00:38 +02:00
|
|
|
known_app.testing_pr = None
|
2018-11-05 17:17:03 +01:00
|
|
|
known_app.opened_issues = 0
|
|
|
|
known_app.opened_prs = 0
|
|
|
|
|
2020-09-03 19:33:59 +02:00
|
|
|
try:
|
|
|
|
db.session.commit()
|
|
|
|
except Exception as e:
|
|
|
|
print(e)
|
|
|
|
db.session.rollback()
|
2018-11-05 17:17:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
class App(db.Model):
|
|
|
|
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
name = db.Column(db.String(64), unique=True, nullable=False)
|
|
|
|
repo = db.Column(db.String(128), unique=True, nullable=False)
|
|
|
|
maintainers = db.Column(db.PickleType)
|
|
|
|
maintained = db.Column(db.Boolean, nullable=False)
|
2018-11-07 20:12:36 +01:00
|
|
|
state = db.Column(db.String(64), nullable=False)
|
2018-11-05 17:17:03 +01:00
|
|
|
ci_enabled = db.Column(db.Boolean, nullable=False)
|
|
|
|
public_level = db.Column(db.Integer, default=-1, nullable=True)
|
|
|
|
|
|
|
|
list = db.relationship(AppList, backref='apps', lazy=True, uselist=False)
|
|
|
|
list_id = db.Column(db.ForeignKey(AppList.id))
|
|
|
|
|
|
|
|
# 'Status info' stuff
|
|
|
|
public_commit = db.Column(db.String(64), nullable=False)
|
|
|
|
master_commit = db.Column(db.String(64), nullable=False)
|
2018-11-07 20:12:36 +01:00
|
|
|
public_commit_date = db.Column(db.DateTime, nullable=True)
|
|
|
|
master_commit_date = db.Column(db.DateTime, nullable=True)
|
2019-05-14 19:00:38 +02:00
|
|
|
testing_pr = db.Column(db.PickleType, default=None)
|
2018-11-05 17:17:03 +01:00
|
|
|
opened_issues = db.Column(db.Integer, default=-1)
|
|
|
|
opened_prs = db.Column(db.Integer, default=-1)
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return '<App %r>' % self.name
|
|
|
|
|
|
|
|
def init():
|
|
|
|
pass
|
|
|
|
|
2018-11-07 20:12:36 +01:00
|
|
|
@property
|
|
|
|
def public_vs_master_time_diff(self):
|
|
|
|
return (self.public_commit_date - self.master_commit_date).days
|
|
|
|
|
2018-11-05 17:17:03 +01:00
|
|
|
def most_recent_tests_per_branch(self):
|
|
|
|
|
2018-11-07 20:12:36 +01:00
|
|
|
from app.models.appci import AppCIBranch, AppCIResult, AppCI
|
2018-11-05 17:17:03 +01:00
|
|
|
branches = AppCIBranch.query.all()
|
|
|
|
for branch in branches:
|
|
|
|
most_recent_test = AppCIResult.query \
|
|
|
|
.filter_by(branch = branch) \
|
|
|
|
.filter_by(app = self) \
|
2019-04-29 22:29:56 +02:00
|
|
|
.order_by(AppCIResult.date.desc()) \
|
2018-11-05 17:17:03 +01:00
|
|
|
.first()
|
|
|
|
if most_recent_test:
|
|
|
|
yield most_recent_test
|
|
|
|
else:
|
|
|
|
yield AppCIResult(app = self,
|
|
|
|
branch = branch,
|
|
|
|
level = None,
|
|
|
|
date = datetime.datetime.fromtimestamp(0),
|
2018-11-08 14:48:35 +01:00
|
|
|
results = { t:None for t in AppCI.tests })
|
2018-11-05 17:17:03 +01:00
|
|
|
|
|
|
|
class Github():
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
|
|
from ..settings import GITHUB_USER, GITHUB_TOKEN
|
|
|
|
|
|
|
|
self.user = GITHUB_USER
|
|
|
|
self.token = GITHUB_TOKEN
|
|
|
|
|
|
|
|
def request(self, uri, autoretry=True):
|
|
|
|
|
|
|
|
r = requests.get('https://api.github.com/{}'.format(uri), auth=(self.user, self.token)).json()
|
|
|
|
if "message" in r and r["message"] == "Not Found" and autoretry:
|
|
|
|
time.sleep(30)
|
|
|
|
r = requests.get('https://api.github.com/{}'.format(uri), auth=(self.user, self.token)).json()
|
|
|
|
if "message" in r and r["message"] == "Not Found":
|
|
|
|
print('https://api.github.com/{}'.format(uri))
|
|
|
|
return {}
|
|
|
|
return r
|
|
|
|
|
|
|
|
def issues(self, app):
|
|
|
|
|
|
|
|
repo = app.repo.replace("https://github.com/", "")
|
|
|
|
j = self.request('repos/{}/issues'.format(repo))
|
|
|
|
|
|
|
|
nb_issues = len([ i for i in j if not "pull_request" in i.keys() ])
|
|
|
|
nb_prs = len([ i for i in j if "pull_request" in i.keys() ])
|
|
|
|
|
|
|
|
return { "nb_issues": nb_issues,
|
|
|
|
"nb_prs": nb_prs }
|
|
|
|
|
2019-05-14 19:00:38 +02:00
|
|
|
def testing_pr(self, app):
|
|
|
|
|
|
|
|
repo = app.repo.replace("https://github.com/", "")
|
|
|
|
owner = repo.split("/")[0]
|
|
|
|
j = self.request('repos/{}/pulls?head={}:testing&base=master'.format(repo,owner))
|
|
|
|
|
|
|
|
if len(j) == 0:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
j = j[0]
|
|
|
|
|
|
|
|
return { "number": j["number"],
|
|
|
|
"created_at": datetime.datetime.strptime(j["created_at"], "%Y-%m-%dT%H:%M:%SZ"),
|
|
|
|
"updated_at": datetime.datetime.strptime(j["updated_at"], "%Y-%m-%dT%H:%M:%SZ"),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-05 17:17:03 +01:00
|
|
|
def commit(self, app, ref):
|
|
|
|
|
|
|
|
repo = app.repo.replace("https://github.com/", "")
|
|
|
|
j = self.request('repos/{}/git/refs/heads/{}'.format(repo, ref))
|
|
|
|
if not "object" in j:
|
|
|
|
print('Failed to fetch repos/{}/git/refs/heads/{}'.format(repo, ref))
|
|
|
|
return "???"
|
|
|
|
return j["object"]["sha"]
|
|
|
|
|
|
|
|
|
|
|
|
def commit_date(self, app, sha):
|
|
|
|
|
|
|
|
repo = app.repo.replace("https://github.com/", "")
|
2019-04-16 17:26:36 +02:00
|
|
|
try:
|
|
|
|
github_date = self.request('repos/{}/commits/{}'.format(repo, sha))["commit"]["author"]["date"]
|
|
|
|
except:
|
2019-05-14 19:00:38 +02:00
|
|
|
print("Error parsing date...")
|
|
|
|
github_date = "1970-01-01T00:00:00Z"
|
2018-11-05 17:17:03 +01:00
|
|
|
parsed_date = datetime.datetime.strptime(github_date, "%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
return parsed_date
|