mirror of
https://github.com/odoo/runbot.git
synced 2025-04-02 16:25:45 +07:00
[FIX] *: handle rate limit in pylint tests
With a concurrency of 3 or more, it ends up being pretty easy to hit github's rate limit (5000 requests/h), at which point the run hits a cascading failure where every test from thereon blows up to the rate limiting. Add a handling for that case in some of the early github-querying fixtures, so they can wait for the ratelimit delay to be restored. This increases the need for a proper fake github thingie I could run on a per-test basis.
This commit is contained in:
parent
0b1b36d10c
commit
916fb30e75
27
conftest.py
27
conftest.py
@ -55,6 +55,7 @@ import time
|
|||||||
import uuid
|
import uuid
|
||||||
import xmlrpc.client
|
import xmlrpc.client
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
import pytest
|
import pytest
|
||||||
@ -105,7 +106,9 @@ def config(pytestconfig):
|
|||||||
return cnf
|
return cnf
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def rolemap(config):
|
def rolemap(request, config):
|
||||||
|
# hack because capsys is not session-scoped
|
||||||
|
capmanager = request.config.pluginmanager.getplugin("capturemanager")
|
||||||
# only fetch github logins once per session
|
# only fetch github logins once per session
|
||||||
rolemap = {}
|
rolemap = {}
|
||||||
for k, data in config.items():
|
for k, data in config.items():
|
||||||
@ -116,7 +119,8 @@ def rolemap(config):
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
r = requests.get('https://api.github.com/user', headers={'Authorization': 'token %s' % data['token']})
|
with capmanager.global_and_fixture_disabled():
|
||||||
|
r = _rate_limited(lambda: requests.get('https://api.github.com/user', headers={'Authorization': 'token %s' % data['token']}))
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
rolemap[role] = data['user'] = r.json()['login']
|
rolemap[role] = data['user'] = r.json()['login']
|
||||||
@ -336,14 +340,15 @@ def env(port, server, db, default_crons):
|
|||||||
# users is just so I can avoid autouse on toplevel users fixture b/c it (seems
|
# users is just so I can avoid autouse on toplevel users fixture b/c it (seems
|
||||||
# to) break the existing local tests
|
# to) break the existing local tests
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def make_repo(request, config, tunnel, users):
|
def make_repo(capsys, request, config, tunnel, users):
|
||||||
owner = config['github']['owner']
|
owner = config['github']['owner']
|
||||||
github = requests.Session()
|
github = requests.Session()
|
||||||
github.headers['Authorization'] = 'token %s' % config['github']['token']
|
github.headers['Authorization'] = 'token %s' % config['github']['token']
|
||||||
|
|
||||||
# check whether "owner" is a user or an org, as repo-creation endpoint is
|
# check whether "owner" is a user or an org, as repo-creation endpoint is
|
||||||
# different
|
# different
|
||||||
q = github.get('https://api.github.com/users/{}'.format(owner))
|
with capsys.disabled():
|
||||||
|
q = _rate_limited(lambda: github.get('https://api.github.com/users/{}'.format(owner)))
|
||||||
q.raise_for_status()
|
q.raise_for_status()
|
||||||
if q.json().get('type') == 'Organization':
|
if q.json().get('type') == 'Organization':
|
||||||
endpoint = 'https://api.github.com/orgs/{}/repos'.format(owner)
|
endpoint = 'https://api.github.com/orgs/{}/repos'.format(owner)
|
||||||
@ -399,6 +404,20 @@ def make_repo(request, config, tunnel, users):
|
|||||||
for repo in reversed(repos):
|
for repo in reversed(repos):
|
||||||
repo.delete()
|
repo.delete()
|
||||||
|
|
||||||
|
|
||||||
|
def _rate_limited(req):
|
||||||
|
while True:
|
||||||
|
q = req()
|
||||||
|
if not q.ok and q.headers.get('X-RateLimit-Remaining') == '0':
|
||||||
|
reset = int(q.headers['X-RateLimit-Reset'])
|
||||||
|
delay = round(reset - time.time() + 1.0)
|
||||||
|
print("Hit rate limit, sleeping for", delay, "seconds")
|
||||||
|
time.sleep(delay)
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
return q
|
||||||
|
|
||||||
|
|
||||||
Commit = collections.namedtuple('Commit', 'id tree message author committer parents')
|
Commit = collections.namedtuple('Commit', 'id tree message author committer parents')
|
||||||
class Repo:
|
class Repo:
|
||||||
def __init__(self, session, fullname, repos):
|
def __init__(self, session, fullname, repos):
|
||||||
|
Loading…
Reference in New Issue
Block a user