mirror of https://github.com/zulip/zulip.git
/team: Fetch contributors data from all major repos.
Also wait 2 seconds before trying again.
This commit is contained in:
parent
84384196f2
commit
771abf4179
|
@ -9,10 +9,12 @@ from lib import sanity_check
|
||||||
sanity_check.check_venv(__file__)
|
sanity_check.check_venv(__file__)
|
||||||
|
|
||||||
from typing import Any, Dict, List, Optional, Union, Text
|
from typing import Any, Dict, List, Optional, Union, Text
|
||||||
|
from mypy_extensions import TypedDict
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
from time import sleep
|
||||||
from datetime import date
|
from datetime import date
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
@ -25,7 +27,6 @@ from django.conf import settings
|
||||||
from zerver.lib.utils import split_by
|
from zerver.lib.utils import split_by
|
||||||
|
|
||||||
FIXTURE_FILE = os.path.join(os.path.dirname(__file__), '../zerver/fixtures/authors.json')
|
FIXTURE_FILE = os.path.join(os.path.dirname(__file__), '../zerver/fixtures/authors.json')
|
||||||
GITHUB_LINK = 'https://api.github.com/repos/zulip/zulip/stats/contributors'
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--max-retries', type=int, default=3,
|
parser.add_argument('--max-retries', type=int, default=3,
|
||||||
|
@ -38,22 +39,18 @@ parser.add_argument('--not-required', action='store_true', default=False,
|
||||||
help='Consider failures to reach GitHub nonfatal')
|
help='Consider failures to reach GitHub nonfatal')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
def fetch_data(retries, link):
|
ContributorsJSON = TypedDict('ContributorsJSON', {
|
||||||
# type: (int, str) -> Optional[List[Dict[str, Any]]]
|
'date': str,
|
||||||
for _ in range(retries):
|
'contrib': Dict[str, Dict[str, Union[str, int]]],
|
||||||
try:
|
})
|
||||||
r = requests.get(link) # type: requests.Response
|
|
||||||
if r.status_code == 200:
|
|
||||||
return r.json()
|
|
||||||
else:
|
|
||||||
print('Github API return non 200 status.')
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def write_to_disk(json_data, out_file):
|
def fetch_contributors(repo_link: str) -> Optional[List[Dict[str, Dict[str, Any]]]]:
|
||||||
# type: (Dict[str, Any], str) -> None
|
r = requests.get(repo_link) # type: requests.Response
|
||||||
|
return r.json() if r.status_code == 200 else None
|
||||||
|
|
||||||
|
|
||||||
|
def write_to_disk(json_data: ContributorsJSON, out_file: str) -> None:
|
||||||
with open(out_file, 'w') as f:
|
with open(out_file, 'w') as f:
|
||||||
try:
|
try:
|
||||||
f.write("{}\n".format(json.dumps(json_data)))
|
f.write("{}\n".format(json.dumps(json_data)))
|
||||||
|
@ -61,53 +58,66 @@ def write_to_disk(json_data, out_file):
|
||||||
print(e)
|
print(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def run_production():
|
|
||||||
# type: () -> None
|
def run_production() -> None:
|
||||||
"""
|
"""
|
||||||
Fetch data from Github and stored it in
|
Get contributors data from Github and insert them into a temporaril
|
||||||
`static/generated/github-contributors.json`
|
dictionary. Retry fetching each repository if responded with non HTTP
|
||||||
|
200 status.
|
||||||
"""
|
"""
|
||||||
json_data = fetch_data(args.max_retries, GITHUB_LINK) # type: Optional[List[Dict[str, Any]]]
|
repositories = {
|
||||||
if json_data:
|
'server': 'https://api.github.com/repos/zulip/zulip/stats/contributors',
|
||||||
# Successfully fetch data from Github
|
'desktop': 'https://api.github.com/repos/zulip/zulip-electron/stats/contributors',
|
||||||
contribs = []
|
'mobile': 'https://api.github.com/repos/zulip/zulip-mobile/stats/contributors',
|
||||||
for user in json_data:
|
'python-zulip-api': 'https://api.github.com/repos/zulip/python-zulip-api/stats/contributors',
|
||||||
author = user.get('author')
|
'zulipbot': 'https://api.github.com/repos/zulip/zulipbot/stats/contributors',
|
||||||
if author is None:
|
}
|
||||||
print("Unable to access fields for %s" % (user,))
|
|
||||||
continue
|
|
||||||
result_user = dict(
|
|
||||||
avatar=author.get('avatar_url'),
|
|
||||||
name=author.get('login'),
|
|
||||||
commits=user.get('total')
|
|
||||||
)
|
|
||||||
contribs.append(result_user)
|
|
||||||
|
|
||||||
out_contrib_data = sorted(
|
data = dict(date=str(date.today()), contrib={}) # type: ContributorsJSON
|
||||||
contribs,
|
contribs_data = {} # type: Dict[str, Dict[str, Union[str, int]]]
|
||||||
key=lambda k: k.get('commits'),
|
|
||||||
reverse=True
|
|
||||||
) # type: List[Dict[str, Union[Text, int]]]
|
|
||||||
|
|
||||||
out_data = dict(
|
for t in range(args.max_retries):
|
||||||
data=out_contrib_data,
|
repo_done = []
|
||||||
date=str(date.today())
|
for k, v in repositories.items():
|
||||||
) # type: Dict[str, Any]
|
contribs = fetch_contributors(v)
|
||||||
|
if contribs:
|
||||||
|
repo_done.append(k)
|
||||||
|
for contrib in contribs:
|
||||||
|
username = contrib.get('author').get('login')
|
||||||
|
contrib_data = {
|
||||||
|
'avatar': contrib.get('author').get('avatar_url'),
|
||||||
|
k: contrib.get('total'),
|
||||||
|
}
|
||||||
|
if username in contribs_data:
|
||||||
|
contribs_data[username].update(contrib_data)
|
||||||
|
else:
|
||||||
|
contribs_data[username] = contrib_data
|
||||||
|
for k in repo_done:
|
||||||
|
del repositories[k]
|
||||||
|
|
||||||
write_to_disk(out_data, settings.CONTRIBUTORS_DATA)
|
if not repositories:
|
||||||
|
break
|
||||||
|
|
||||||
elif not args.not_required:
|
# Wait before retrying failed requests for Github to aggregate data.
|
||||||
print('Fail to fetch data from Github.')
|
sleep(2)
|
||||||
sys.exit(1)
|
else:
|
||||||
|
print("ERROR: Failed fetching contributors data from Github.")
|
||||||
|
if not args.not_required:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def copy_fixture():
|
data['contrib'] = contribs_data
|
||||||
# type: () -> None
|
|
||||||
|
write_to_disk(data, settings.CONTRIBUTORS_DATA)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_fixture() -> None:
|
||||||
"""
|
"""
|
||||||
Copy test fixture file from zerver/fixtures. This is used to avoid
|
Copy test fixture file from zerver/fixtures. This is used to avoid
|
||||||
constantly fetching data from Github during testing.
|
constantly fetching data from Github during testing.
|
||||||
"""
|
"""
|
||||||
subprocess.check_call(['cp', FIXTURE_FILE, settings.CONTRIBUTORS_DATA])
|
subprocess.check_call(['cp', FIXTURE_FILE, settings.CONTRIBUTORS_DATA])
|
||||||
|
|
||||||
|
|
||||||
if args.use_fixture:
|
if args.use_fixture:
|
||||||
copy_fixture()
|
copy_fixture()
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue