From be7063d53cb3a139c26c2c585d888781cf75ab10 Mon Sep 17 00:00:00 2001 From: sidpremkumar Date: Oct 30 2019 20:51:24 +0000 Subject: Add catch for github api limit --- diff --git a/sync2jira/main.py b/sync2jira/main.py index dab17bf..e5af266 100644 --- a/sync2jira/main.py +++ b/sync2jira/main.py @@ -25,6 +25,7 @@ Run with systemd, please. import logging import warnings import traceback +from time import sleep import fedmsg import fedmsg.config @@ -134,6 +135,7 @@ def listen(config): idx = msg['msg_id'] suffix = ".".join(topic.split('.')[3:]) log.debug("Encountered %r %r %r", suffix, topic, idx) + if suffix not in handlers: continue @@ -150,7 +152,7 @@ def listen(config): d.sync_with_jira(issue, config) -def initialize(config): +def initialize(config, testing=False): """ Initial initialization needed to sync any upstream \ repo with JIRA. Goes through all issues and \ @@ -158,6 +160,7 @@ def initialize(config): created. :param Dict config: Config dict for JIRA + :param Bool testing: Flag to indicate if we are testing. Default false :returns: Nothing """ log.info(" Running initialization to sync all issues from upstream to jira") @@ -173,12 +176,28 @@ def initialize(config): log.info(" Done with pagure initialization.") for upstream in mapping.get('github', {}).keys(): - for issue in u.github_issues(upstream, config): - try: - d.sync_with_jira(issue, config) - except Exception: - log.error(" Failed on %r", issue) - raise + # Try and except for github API limit + try: + for issue in u.github_issues(upstream, config): + try: + d.sync_with_jira(issue, config) + except Exception: + log.error(" Failed on %r", issue) + raise + except Exception as e: + if "API rate limit exceeded" in e.__str__(): + # If we've hit out API limit: + # Sleep for 1 hour and call our function again + log.info(" Hit Github API limit. Sleeping for 1 hour...") + sleep(3600) + if not testing: + initialize(config) + return + else: + if not config['sync2jira']['develop']: + # Only send the failure email if we are not developing + report_failure(config) + raise log.info(" Done with github initialization.") @@ -193,6 +212,7 @@ def main(): config = load_config() logging.basicConfig(level=logging.INFO) warnings.simplefilter("ignore") + config['validate_signatures'] = False try: if config['sync2jira'].get('initialize'): diff --git a/tests/test_main.py b/tests/test_main.py index d9ab496..0abf7a7 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -33,7 +33,8 @@ class TestMain(unittest.TestCase): 'github': {'key_github': 'value1'} }, 'initialize': True, - 'listen': True + 'listen': True, + 'develop': False, }, } @@ -205,6 +206,62 @@ class TestMain(unittest.TestCase): @mock.patch(PATH + 'u') @mock.patch(PATH + 'd') + @mock.patch(PATH + 'sleep') + @mock.patch(PATH + 'report_failure') + def test_initialize_api_limit(self, + mock_report_failure, + mock_sleep, + mock_d, + mock_u): + """ + This tests 'initialize' where we get an GitHub API limit error. + """ + # Set up return values + mock_error = MagicMock(side_effect=Exception('API rate limit exceeded')) + mock_u.pagure_issues.return_value = ['mock_issue_pagure'] + mock_u.github_issues.side_effect = mock_error + + # Call the function + m.initialize(self.mock_config, testing=True) + + # Assert everything was called correctly + mock_u.pagure_issues.assert_called_with('key_pagure', self.mock_config) + mock_d.sync_with_jira.assert_any_call('mock_issue_pagure', self.mock_config) + mock_u.github_issues.assert_called_with('key_github', self.mock_config) + mock_sleep.assert_called_with(3600) + mock_report_failure.assert_not_called() + + @mock.patch(PATH + 'u') + @mock.patch(PATH + 'd') + @mock.patch(PATH + 'sleep') + @mock.patch(PATH + 'report_failure') + def test_initialize_github_error(self, + mock_report_failure, + mock_sleep, + mock_d, + mock_u): + """ + This tests 'initialize' where we get a GitHub API (not limit) error. + """ + # Set up return values + mock_error = MagicMock(side_effect=Exception('Random Error')) + mock_u.pagure_issues.return_value = ['mock_issue_pagure'] + mock_u.github_issues.side_effect = mock_error + + # Call the function + with self.assertRaises(Exception): + m.initialize(self.mock_config, testing=True) + + # Assert everything was called correctly + mock_u.pagure_issues.assert_called_with('key_pagure', self.mock_config) + mock_d.sync_with_jira.assert_any_call('mock_issue_pagure', self.mock_config) + mock_u.github_issues.assert_called_with('key_github', self.mock_config) + mock_sleep.assert_not_called() + mock_report_failure.assert_called_with(self.mock_config) + + + @mock.patch(PATH + 'u') + @mock.patch(PATH + 'd') @mock.patch(PATH + 'fedmsg') def test_listen_no_handlers(self, mock_fedmsg,