def handle_msg(msg, suffix, config): """ Function to handle incomming message from datagrepper :param Dict msg: Incoming message :param String suffix: Incoming suffix :param Dict config: Config dict """ issue = None pr = None # Github '.issue.' is used for both PR and Issue # Check for that edge case if suffix == 'github.issue.comment': if 'pull_request' in msg['msg']['issue'] and msg['msg']['action'] != 'deleted': # pr_filter turns on/off the filtering of PRs pr = issue_handlers[suffix](msg, config, pr_filter=False) if not pr: return # Issues do not have suffix and reporter needs to be reformatted pr.suffix = suffix pr.reporter = pr.reporter.get('fullname') setattr(pr, 'match', matcher(pr.content, pr.comments)) else: issue = issue_handlers[suffix](msg, config) elif suffix in issue_handlers: issue = issue_handlers[suffix](msg, config) elif suffix in pr_handlers: pr = pr_handlers[suffix](msg, config, suffix) if not issue and not pr: return if issue: d_issue.sync_with_jira(issue, config) elif pr: d_pr.sync_with_jira(pr, config)
def initialize_pr(config, testing=False, repo_name=None): """ Initial initialization needed to sync any upstream \ repo with JIRA. Goes through all PRs and \ checks if they're already on JIRA / Need to be \ created. :param Dict config: Config dict for JIRA :param Bool testing: Flag to indicate if we are testing. Default false :param String repo_name: Optional individual repo name. If defined we will only sync the provided repo :returns: Nothing """ log.info("Running initialization to sync all PRs from upstream to jira") log.info("Testing flag is %r", config['sync2jira']['testing']) mapping = config['sync2jira']['map'] for upstream in mapping.get('pagure', {}).keys(): if 'pullrequest' not in mapping.get('pagure', {}).get(upstream, {}).get('sync', []): continue if repo_name is not None and upstream != repo_name: continue for pr in u_pr.pagure_prs(upstream, config): if pr: d_pr.sync_with_jira(pr, config) log.info("Done with pagure PR initialization.") for upstream in mapping.get('github', {}).keys(): if 'pullrequest' not in mapping.get('github', {}).get(upstream, {}).get('sync', []): continue if repo_name is not None and upstream != repo_name: continue # Try and except for github API limit try: for pr in u_pr.github_prs(upstream, config): try: if pr: d_pr.sync_with_jira(pr, config) except Exception: log.error(" Failed on %r", pr) 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_pr(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 PR initialization.")
def listen(config): """ Listens to activity on upstream repos on pagure and github \ via fedmsg, and syncs new issues there to the JIRA instance \ defined in 'fedmsg.d/sync2jira.py' :param Dict config: Config dict :returns: Nothing """ if not config['sync2jira'].get('listen'): log.info("`listen` is disabled. Exiting.") return log.info("Waiting for a relevant fedmsg message to arrive...") for _, _, topic, msg in fedmsg.tail_messages(**config): idx = msg['msg_id'] suffix = ".".join(topic.split('.')[3:]) log.debug("Encountered %r %r %r", suffix, topic, idx) if suffix not in issue_handlers and suffix not in pr_handlers: continue log.debug("Handling %r %r %r", suffix, topic, idx) issue = None pr = None # Github '.issue.' is used for both PR and Issue # Check for that edge case if suffix == 'github.issue.comment': if 'pull_request' in msg['msg'][ 'issue'] and msg['msg']['action'] != 'deleted': # pr_filter turns on/off the filtering of PRs pr = issue_handlers[suffix](msg, config, pr_filter=False) if not pr: continue # Issues do not have suffix and reporter needs to be reformatted pr.suffix = suffix pr.reporter = pr.reporter.get('fullname') setattr(pr, 'match', matcher(pr.content, pr.comments)) else: issue = issue_handlers[suffix](msg, config) elif suffix in issue_handlers: issue = issue_handlers[suffix](msg, config) elif suffix in pr_handlers: pr = pr_handlers[suffix](msg, config, suffix) if not issue and not pr: continue if issue: d_issue.sync_with_jira(issue, config) elif pr: d_pr.sync_with_jira(pr, config)
def handle_message(config, incoming_json): # Constantly refresh the config file when we handle a new message config = load_config() # Ensure we are only dealing with one issue at a time, get our lock with lock: if ('pull_request' in incoming_json.keys()): pr = u_pr.handle_github_message(config, incoming_json) if pr: d_pr.sync_with_jira(pr, config) elif ('issue' in incoming_json.keys() and '/pull/' not in incoming_json['issue']['html_url']): issue = u_issue.handle_github_message(config, incoming_json) if issue: d_issue.sync_with_jira(issue, config)
def test_sync_with_jira_no_issues_found(self, mock_d_issue, mock_update_jira_issue): """ This function tests 'sync_with_jira' where no issues are found """ # Set up return values self.mock_client.search_issues.return_value = [] mock_d_issue.get_jira_client.return_value = self.mock_client # Call the function d.sync_with_jira(self.mock_pr, self.mock_config) # Assert everything was called correctly mock_update_jira_issue.assert_not_called() self.mock_client.search_issues.assert_called_with('Key = JIRA-1234') mock_d_issue.get_jira_client.assert_called_with( self.mock_pr, self.mock_config)
def test_sync_with_jira(self, mock_d_issue, mock_update_jira_issue): """ This function tests 'sync_with_jira' """ # Set up return values mock_d_issue.get_jira_client.return_value = self.mock_client # Call the function d.sync_with_jira(self.mock_pr, self.mock_config) # Assert everything was called correctly mock_update_jira_issue.assert_called_with('mock_existing', self.mock_pr, self.mock_client) self.mock_client.search_issues.assert_called_with('Key = JIRA-1234') mock_d_issue.get_jira_client.assert_called_with( self.mock_pr, self.mock_config)
def test_sync_with_jira_testing(self, mock_d_issue, mock_update_jira_issue): """ This function tests 'sync_with_jira' where no issues are found """ # Set up return values mock_client = MagicMock() mock_client.search_issues.return_value = [] self.mock_config['sync2jira']['testing'] = True mock_d_issue.get_jira_client.return_value = mock_client # Call the function d.sync_with_jira(self.mock_pr, self.mock_config) # Assert everything was called correctly mock_update_jira_issue.assert_not_called() mock_client.search_issues.assert_not_called() mock_d_issue.get_jira_client.assert_not_called()
def test_sync_with_jira_merged(self, mock_update_transition, mock_d_issue, mock_update_jira_issue): """ This function tests 'sync_with_jira' """ # Set up return values mock_client = MagicMock() mock_client.search_issues.return_value = ['mock_existing'] mock_d_issue.get_jira_client.return_value = mock_client self.mock_pr.suffix = 'merged' # Call the function d.sync_with_jira(self.mock_pr, self.mock_config) # Assert everything was called correctly mock_update_jira_issue.assert_called_with('mock_existing', self.mock_pr, mock_client) mock_client.search_issues.assert_called_with('Key = JIRA-1234') mock_d_issue.get_jira_client.assert_called_with( self.mock_pr, self.mock_config) mock_update_transition.mock.asset_called_with(mock_client, 'mock_existing', self.mock_pr, 'merged_transition')