mirror of
https://github.com/YunoHost/tartiflette.git
synced 2024-09-03 20:06:08 +02:00
Add proof of concept for maintenance ping system
This commit is contained in:
parent
d89848324f
commit
6ef0ea1457
3 changed files with 188 additions and 0 deletions
164
app/scripts/maintenancePing/maintenancePing.py
Executable file
164
app/scripts/maintenancePing/maintenancePing.py
Executable file
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
LOGIN=open("./login").read().strip()
|
||||||
|
TOKEN=open("./token").read().strip()
|
||||||
|
MAINTENANCE_PING_BODY=open("./maintenance_ping_body").read().strip()
|
||||||
|
UNMAINTAINED_WARNING=open("./unmaintained_warning").read().strip()
|
||||||
|
|
||||||
|
def get_github(uri):
|
||||||
|
with requests.Session() as s:
|
||||||
|
s.headers.update({"Authorization": "token {}".format(TOKEN)})
|
||||||
|
r = s.get("https://api.github.com" + uri)
|
||||||
|
|
||||||
|
#assert r.status_code == 200, "Couldn't get {uri} . Reponse : {text}".format(uri=uri, text=r.text)
|
||||||
|
j = json.loads(r.text)
|
||||||
|
return j
|
||||||
|
|
||||||
|
def github_date_to_days_ago(date):
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
date = datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
return (now - date).days
|
||||||
|
|
||||||
|
def get_issues(repo):
|
||||||
|
return get_github("/repos/{repo}/issues".format(repo=repo))
|
||||||
|
|
||||||
|
def get_active_maintenance_ping(issues):
|
||||||
|
|
||||||
|
for issue in issues:
|
||||||
|
if issue["title"].startswith("[Maintenance ping]"):
|
||||||
|
if issue["state"] == "open":
|
||||||
|
issue["created_days_ago"] = github_date_to_days_ago(issue["created_at"])
|
||||||
|
return issue
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_old_maintenance_ping(issues):
|
||||||
|
|
||||||
|
for issue in issues:
|
||||||
|
if issue["title"].startswith("[Maintenance ping]"):
|
||||||
|
if issue["state"] == "closed":
|
||||||
|
issue["updated_days_ago"] = github_date_to_days_ago(issue["updated_at"])
|
||||||
|
return issue
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_commit_days_ago(repo, branch):
|
||||||
|
|
||||||
|
ref = get_github("/repos/{repo}/git/refs/heads/{branch}".format(repo=repo, branch=branch))
|
||||||
|
if not "object" in ref:
|
||||||
|
return 99999
|
||||||
|
|
||||||
|
sha = ref["object"]["sha"]
|
||||||
|
github_date = get_github("/repos/{repo}/commits/{sha}".format(repo=repo, sha=sha))["commit"]["author"]["date"]
|
||||||
|
|
||||||
|
return github_date_to_days_ago(github_date)
|
||||||
|
|
||||||
|
|
||||||
|
def create_maintenance_ping(repo):
|
||||||
|
api_url = "https://api.github.com/repos/{repo}/issues".format(repo=repo)
|
||||||
|
|
||||||
|
issue = { "title": "[Maintenance ping] Is this app still maintained ?",
|
||||||
|
"body": MAINTENANCE_PING_BODY
|
||||||
|
}
|
||||||
|
|
||||||
|
with requests.Session() as s:
|
||||||
|
s.headers.update({"Authorization": "token {}".format(TOKEN)})
|
||||||
|
s.post(api_url, json.dumps(issue))
|
||||||
|
|
||||||
|
def warn_unmaintained_if_needed(repo, issue):
|
||||||
|
|
||||||
|
issue_id = issue["number"]
|
||||||
|
comments = get_github("/repos/{repo}/issues/{id}/comments".format(repo=repo, id=issue_id))
|
||||||
|
existing_warning = [ c for c in comments if c["user"]["login"] == LOGIN
|
||||||
|
and c["body"].startswith(UNMAINTAINED_WARNING[:20]) ]
|
||||||
|
# Nothing to do if there's already a warning about unmaintenained status...
|
||||||
|
if existing_warning:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Otherwise, post a comment
|
||||||
|
api_url = "https://api.github.com/repos/{repo}/issues/{id}/comments" \
|
||||||
|
.format(repo=repo, id=issue_id)
|
||||||
|
comment = { "body": UNMAINTAINED_WARNING }
|
||||||
|
with requests.Session() as s:
|
||||||
|
s.headers.update({"Authorization": "token {}".format(TOKEN)})
|
||||||
|
s.post(api_url, json.dumps(comment))
|
||||||
|
|
||||||
|
|
||||||
|
def get_status_and_todo(repo):
|
||||||
|
|
||||||
|
# (Get issues of repo)
|
||||||
|
issues = get_issues(repo)
|
||||||
|
|
||||||
|
# Is a maintenance ping already opened ?
|
||||||
|
active_maintenance_ping = get_active_maintenance_ping(issues)
|
||||||
|
|
||||||
|
if active_maintenance_ping:
|
||||||
|
# since more than 15 days ?
|
||||||
|
if active_maintenance_ping["created_days_ago"] > 15:
|
||||||
|
# yes - > unmaintained !
|
||||||
|
# -> post a comment if not already done
|
||||||
|
return ("unmaintained", partial(warn_unmaintained_if_needed,
|
||||||
|
issue=active_maintenance_ping))
|
||||||
|
else:
|
||||||
|
# no - > maintained ! (but status being questionned)
|
||||||
|
return ("maintained?", None)
|
||||||
|
|
||||||
|
# Commit in master or testing in last 12 months ?
|
||||||
|
if get_commit_days_ago(repo, "master") < 12*30 \
|
||||||
|
or get_commit_days_ago(repo, "testing") < 12*30:
|
||||||
|
# ok, maintained
|
||||||
|
return ("maintained", None)
|
||||||
|
|
||||||
|
# Maintainenance status is now being questionned...
|
||||||
|
# Was there a (now closed) maintenance ping in the last 6 months ?
|
||||||
|
old_maintenance_ping = get_old_maintenance_ping(issues)
|
||||||
|
if old_maintenance_ping and old_maintenance_ping["update_days_ago"] < 6*30:
|
||||||
|
# Yes - > ok, maintained
|
||||||
|
return ("maintained", None)
|
||||||
|
else:
|
||||||
|
# No - > Gotta create a maintenance ping ! (but still considered maintained)
|
||||||
|
return ("maintained?", create_maintenance_ping)
|
||||||
|
|
||||||
|
def get_apps_to_check():
|
||||||
|
|
||||||
|
official="https://raw.githubusercontent.com/YunoHost/apps/master/official.json"
|
||||||
|
community="https://raw.githubusercontent.com/YunoHost/apps/master/community.json"
|
||||||
|
|
||||||
|
raw_apps = []
|
||||||
|
raw_apps += json.loads(requests.get(official).text).values()
|
||||||
|
raw_apps += json.loads(requests.get(community).text).values()
|
||||||
|
|
||||||
|
return [ app for app in raw_apps \
|
||||||
|
if app["state"] in ["validated", "working", "inprogress"] ]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
monitored_apps = get_apps_to_check()
|
||||||
|
|
||||||
|
status = {}
|
||||||
|
todo = {}
|
||||||
|
|
||||||
|
# For each monitored app :
|
||||||
|
for app in monitored_apps:
|
||||||
|
|
||||||
|
app = app["url"].replace("https://github.com/","")
|
||||||
|
|
||||||
|
try:
|
||||||
|
status[app], todo[app] = get_status_and_todo(app)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
#print("maintained?")
|
||||||
|
#print(len([ app for app in monitored_apps if status[app] == "maintained?"]))
|
||||||
|
#print("maintained")
|
||||||
|
#print(len([ app for app in monitored_apps if status[app] == "maintained"]))
|
||||||
|
|
||||||
|
main()
|
19
app/scripts/maintenancePing/maintenance_ping_body
Normal file
19
app/scripts/maintenancePing/maintenance_ping_body
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Hello !
|
||||||
|
|
||||||
|
This is a friendly automatic notice from the Yunohost Apps team : our tool noticed that this app is listed in the community/official app lists - but this app appears to be inactive.
|
||||||
|
|
||||||
|
Hence, **this issue was created automatically to check if this app is still actively maintained.**
|
||||||
|
|
||||||
|
## You are the current maintainer ? :construction_worker_man: :construction_worker_woman:
|
||||||
|
|
||||||
|
#### You still actively maintain this app ? :tada:
|
||||||
|
|
||||||
|
Please close this issue to signify that you still actively maintain this app. Nothing else, and thank you for your work :heart: !
|
||||||
|
|
||||||
|
#### You don't intend to maintain this app anymore ? :cry:
|
||||||
|
|
||||||
|
Either don't do anything, or add a comment to explicitly state that you do not intend / have time / ... to maintain this app (but thanks for your work so far ! :kissing_heart:). After 15 days, if this issue is still opened, the app will be considered *unmaintained*.
|
||||||
|
|
||||||
|
## You wish to become the new maintainer of this app ? :smile:
|
||||||
|
|
||||||
|
You are welcome and free to comment in this thread that you wish to become the new maintainer, amd/or to create the corresponding pull request to fix this issue ! (If you do not already have commit rights on this repo, we can then arrange things with the rest of the app team. :wink:) Once this issue is closed, the app will then be flagged again as *maintained* !
|
5
app/scripts/maintenancePing/unmaintained_warning
Normal file
5
app/scripts/maintenancePing/unmaintained_warning
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
:warning: **Warning**: according to the previous instructions, since this issue is opened since more than 15 days, this app is now flagged as "unmaintained".
|
||||||
|
|
||||||
|
Feel free to volunteer as a maintainer and close this issue to reflag it as "maintained".
|
||||||
|
|
||||||
|
*(This is an automatic message)*
|
Loading…
Reference in a new issue