def update(self): self.instance.update() self._history = \ HistoryWrapper(self, cachedir=self.cachedir, usecache=True) if self.is_pullrequest(): self.pullrequest.update() if self.instance.updated_at > self.pullrequest.updated_at: logging.error('breakpoint!') import epdb; epdb.st()
def update(self): self.instance.update() self._history = \ HistoryWrapper(self, cachedir=self.cachedir, usecache=True) if self.is_pullrequest(): self.pullrequest.update() if self.instance.updated_at > self.pullrequest.updated_at: import epdb epdb.st()
def process_history(self, usecache=True): self.meta = {} today = self.get_current_time() # Build the history self.debug(msg="Building event history ...") self.history = HistoryWrapper(self.issue, usecache=usecache) # what was the last commment? bot_broken = False if self.issue.current_comments: for comment in self.issue.current_comments: if 'bot_broken' in comment.body: bot_broken = True # who made this and when did they last comment? submitter = self.issue.get_submitter() submitter_last_commented = self.history.last_commented_at(submitter) submitter_last_comment = self.history.last_comment(submitter) submitter_last_notified = self.history.last_notified(submitter) # what did they not provide? missing_sections = self.issue.get_missing_sections() if 'ansible version' in missing_sections: missing_sections.remove('ansible version') # DEBUG + FIXME - speeds up bulk triage if 'component name' in missing_sections and self.match: missing_sections.remove('component name') #import epdb; epdb.st() # Is this a valid module? valid_module = False correct_repo = True if self.match: valid_module = True if self.match['repository'] != self.github_repo: correct_repo = False #import epdb; epdb.st() # Do these after evaluating the module self.add_desired_labels_by_issue_type() if 'ansible version' in missing_sections: #self.debug(msg='desired_comments: %s' % self.issue.desired_comments) self.add_desired_labels_by_ansible_version() #self.debug(msg='desired_comments: %s' % self.issue.desired_comments) self.add_desired_labels_by_namespace() #self.debug(msg='desired_comments: %s' % self.issue.desired_comments) # Who are the maintainers? maintainers = [x for x in self.get_module_maintainers()] #if 'ansible' in maintainers: # maintainers.remove('ansible') # maintainers += self.ansible_members #print("MAINTAINERS: %s" % maintainers) if 'ansible' in maintainers: maintainers.remove('ansible') maintainers.extend(self.ansible_members) if 'ansibot' in maintainers: maintainers.remove('ansibot') if submitter in maintainers: maintainers.remove(submitter) maintainers = sorted(set(maintainers)) # Has maintainer been notified? When? notification_maintainers = self.get_module_maintainers() if 'ansible' in notification_maintainers: notification_maintainers.extend(self.ansible_members) if 'ansibot' in notification_maintainers: notification_maintainers.remove('ansibot') maintainer_last_notified = self.history.\ last_notified(notification_maintainers) #import epdb; epdb.st() # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) maintainer_last_viewed = self.history.last_viewed_at(maintainers) #import epdb; epdb.st() # Has maintainer been mentioned? maintainer_mentioned = self.history.is_mentioned(maintainers) # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) # Has the maintainer ever responded? maintainer_commented = self.history.has_commented(maintainers) maintainer_last_commented = self.history.last_commented_at(maintainers) maintainer_last_comment = self.history.last_comment(maintainers) maintainer_comments = self.history.get_user_comments(maintainers) #import epdb; epdb.st() # Was the maintainer the last commentor? last_commentor_ismaintainer = False last_commentor_issubmitter = False last_commentor = self.history.last_commentor() if last_commentor in maintainers and last_commentor != self.github_user: last_commentor_ismaintainer = True elif last_commentor == submitter: last_commentor_issubmitter = True # Did the maintainer issue a command? maintainer_commands = self.history.get_commands(maintainers, self.VALID_COMMANDS) #import epdb; epdb.st() maintainer_command_close = False maintainer_command_needsinfo = False maintainer_command_not_needsinfo = False maintainer_command_notabug = False maintainer_command_wontfix = False maintainer_command_resolved_bug = False maintainer_command_resolved_pr = False maintainer_command_needscontributor = False maintainer_command_duplicateof = False if maintainer_commented and not maintainer_last_comment: print('ERROR: should have a comment from maintainer') import epdb; epdb.st() elif maintainer_last_comment and last_commentor_ismaintainer: maintainer_last_comment = maintainer_last_comment.strip() if 'needs_info' in maintainer_last_comment \ and not '!needs_info' in maintainer_last_comment: maintainer_command_needsinfo = True elif '!needs_info' in maintainer_last_comment: maintainer_command_not_needsinfo = True elif 'notabug' in maintainer_last_comment: maintainer_command_notabug = True maintainer_command_close = True elif 'wontfix' in maintainer_last_comment: maintainer_command_wontfix = True maintainer_command_close = True elif 'bug_resolved' in maintainer_last_comment: maintainer_command_resolved_bug = True maintainer_command_close = True elif 'resolved_by_pr' in maintainer_last_comment: maintainer_command_resolved_pr = True maintainer_command_close = True elif 'needs_contributor' in maintainer_last_comment: maintainer_command_needscontributor = True elif 'duplicate_of' in maintainer_last_comment: maintainer_command_duplicateof = True maintainer_command_close = True elif maintainer_commands: # are there any persistant commands? if 'needs_contributor' in maintainer_commands: maintainer_command_needscontributor = True elif not missing_sections and not submitter_last_commented and maintainer_commands[-1] == 'needs_info': maintainer_command_needsinfo = True elif not missing_sections and not submitter_last_commented and maintainer_commands[-1] == '!needs_info': maintainer_command_not_needsinfo = True #import epdb; epdb.st() #import epdb; epdb.st() # Has the maintainer ever subscribed? maintainer_subscribed = self.history.has_subscribed(maintainers) # Was it ever needs_info? was_needs_info = self.history.was_labeled(label='needs_info') needsinfo_last_applied = self.history.label_last_applied('needs_info') needsinfo_last_removed = self.history.label_last_removed('needs_info') #import epdb; epdb.st() # Still needs_info? needsinfo_add = False needsinfo_remove = False if 'needs_info' in self.issue.current_labels: if submitter_last_commented and needsinfo_last_applied: if submitter_last_commented > needsinfo_last_applied \ and not missing_sections: needsinfo_remove = True if maintainer_command_needsinfo and maintainer_last_commented: if submitter_last_commented and maintainer_last_commented: if submitter_last_commented > maintainer_last_commented: needsinfo_add = False needsinfo_remove = True else: needsinfo_add = True needsinfo_remove = False # Is needs_info stale or expired? needsinfo_age = None needsinfo_stale = False needsinfo_expired = False if 'needs_info' in self.issue.current_labels: time_delta = today - needsinfo_last_applied needsinfo_age = time_delta.days if needsinfo_age > 14: needsinfo_stale = True if needsinfo_age > 56: needsinfo_expired = True # Should we be in waiting_on_maintainer mode? maintainer_waiting_on = False if (needsinfo_remove or not needsinfo_add) \ or not was_needs_info \ and not missing_sections: maintainer_waiting_on = True # Should we [re]notify the submitter? submitter_waiting_on = False submitter_to_ping = False submitter_to_reping = False if not maintainer_waiting_on: submitter_waiting_on = True if missing_sections: submitter_waiting_on = True maintainer_waiting_on = False else: if 'needs_info' in self.issue.current_labels \ and not maintainer_command_not_needsinfo: needsinfo_remove = True submitter_waiting_on = False maintainer_waiting_on = True if maintainer_command_not_needsinfo: submitter_waiting_on = False maintainer_waiting_on = True if maintainer_command_needsinfo: submitter_waiting_on = True maintainer_waiting_on = False needsinfo_add = True needsinfo_remove = False # Time to [re]ping maintainer? maintainer_to_ping = False maintainer_to_reping = False if maintainer_waiting_on: #import epdb; epdb.st() if maintainer_viewed and not maintainer_last_notified: time_delta = today - maintainer_last_viewed view_age = time_delta.days if view_age > 14: maintainer_to_reping = True elif maintainer_last_notified: time_delta = today - maintainer_last_notified ping_age = time_delta.days if ping_age > 14: maintainer_to_reping = True else: maintainer_to_ping = True # Time to [re]ping the submitter? if submitter_waiting_on: if submitter_last_notified: time_delta = today - submitter_last_notified notification_age = time_delta.days if notification_age > 14: submitter_to_reping = True else: submitter_to_reping = False submitter_to_ping = False else: submitter_to_ping = True submitter_to_reping = False issue_type = self.template_data.get('issue type', None) issue_type = self.issue_type_to_label(issue_type) self.meta['issue_type'] = issue_type # new module requests need to disable everything # https://github.com/ansible/ansible-modules-core/issues/4112 # https://github.com/ansible/ansible-modules-core/issues/2267 # https://github.com/ansible/ansible-modules-core/issues/2626 # https://github.com/ansible/ansible-modules-core/issues/645 new_module_request = False if 'feature_idea' in self.issue.desired_labels: if self.template_data['component name'] == 'new': new_module_request = True # reset the maintainers maintainers = self.get_module_maintainers() ################################################# # FINAL LOGIC LOOP ################################################# if bot_broken: self.debug(msg='broken bot stanza') self.issue.add_desired_label('bot_broken') elif maintainer_command_close: self.debug(msg='maintainer closure stanza') # Need to close the issue ... self.issue.set_desired_state('closed') elif new_module_request: self.debug(msg='new module request stanza') self.issue.desired_comments = [] for label in self.issue.current_labels: if not label in self.issue.desired_labels: self.issue.desired_labels.append(label) elif not correct_repo: self.debug(msg='wrong repo stanza') self.issue.desired_comments = ['issue_wrong_repo'] self.actions['close'] = True #import epdb; epdb.st() elif not valid_module and not maintainer_command_needsinfo: self.debug(msg='invalid module stanza') #import epdb; epdb.st() self.issue.add_desired_label('needs_info') if 'issue_invalid_module' not in self.issue.current_bot_comments \ and not 'issue_needs_info' in self.issue.current_bot_comments: self.issue.desired_comments = ['issue_invalid_module'] elif not maintainers and not maintainer_command_needsinfo: self.debug(msg='no maintainer stanza') self.issue.add_desired_label('waiting_on_maintainer') self.issue.add_desired_comment("issue_module_no_maintainer") elif maintainer_command_needscontributor: # maintainer can't or won't fix this, but would like someone else to self.debug(msg='maintainer needs contributor stanza') self.issue.add_desired_label('waiting_on_contributor') #import epdb; epdb.st() elif maintainer_waiting_on: self.debug(msg='maintainer wait stanza') #import epdb; epdb.st() self.issue.add_desired_label('waiting_on_maintainer') if len(self.issue.current_comments) == 0: if issue_type: self.issue.add_desired_comment('issue_new') else: if maintainers != ['DEPRECATED']: if maintainer_to_ping and maintainers: self.issue.add_desired_comment("issue_notify_maintainer") elif maintainer_to_reping and maintainers: self.issue.add_desired_comment("issue_renotify_maintainer") #import epdb; epdb.st() elif submitter_waiting_on: self.debug(msg='submitter wait stanza') #import epdb; epdb.st() if 'waiting_on_maintainer' in self.issue.desired_labels: self.issue.desired_labels.remove('waiting_on_maintainer') if (needsinfo_add or missing_sections) \ or (not needsinfo_remove and missing_sections) \ or (needsinfo_add and not missing_sections): self.issue.add_desired_label('needs_info') if len(self.issue.current_comments) == 0: self.issue.add_desired_comment("issue_needs_info") # needs_info: warn if stale, close if expired elif needsinfo_expired: self.issue.add_desired_comment("issue_closure") self.issue.set_desired_state('closed') elif needsinfo_stale \ and (submitter_to_ping or submitter_to_reping): self.issue.add_desired_comment("issue_pending_closure")
def history(self): if self._history is False: self._history = \ HistoryWrapper(self, cachedir=self.cachedir, usecache=True) return self._history
def get_facts(self, usecache=True): '''Only used by the ansible/ansible triager at the moment''' hfacts = {} today = self.get_current_time() self.history = HistoryWrapper( self.issue, usecache=usecache, cachedir=self.cachedir ) # what was the last commment? bot_broken = False if self.issue.current_comments: for comment in self.issue.current_comments: if 'bot_broken' in comment.body: bot_broken = True # did someone from ansible want this issue skipped? bot_skip = False if self.issue.current_comments: for comment in self.issue.current_comments: if 'bot_skip' in comment.body and comment.user.login in self.ansible_members: bot_skip = True ######################################################### # Facts for new "triage" workflow ######################################################### # these logins don't count for the next set of facts exclude_logins = ['ansibot', 'gregdek', self.issue.instance.user.login] # Has a human (not ansibot + not submitter) ever changed labels? lchanges = [x for x in self.history.history if x['event'] in ['labeled', 'unlabeled'] and x['actor'] not in exclude_logins] if lchanges: hfacts['human_labeled'] = True else: hfacts['human_labeled'] = False # Has a human (not ansibot + not submitter) ever changed the title? tchanges = [x for x in self.history.history if x['event'] in ['renamed'] and x['actor'] not in exclude_logins] if tchanges: hfacts['human_retitled'] = True else: hfacts['human_retitled'] = False # Has a human (not ansibot + not submitter) ever changed the description? # ... github doesn't record an event for this. Lame. # Has a human (not ansibot + not submitter) ever set a milestone? mchanges = [x for x in self.history.history if x['event'] in ['milestoned', 'demilestoned'] and x['actor'] not in exclude_logins] if mchanges: hfacts['human_milestoned'] = True else: hfacts['human_milestoned'] = False # Has a human (not ansibot + not submitter) ever set/unset assignees? achanges = [x for x in self.history.history if x['event'] in ['assigned', 'unassigned'] and x['actor'] not in exclude_logins] if achanges: hfacts['human_assigned'] = True else: hfacts['human_assigned'] = False ######################################################### # Has the bot been overzealous with comments? hfacts['bot_spam'] = False bcg = self.history.get_user_comments_groupby('ansibot', groupby='w') for k,v in bcg.iteritems(): if v >= self.MAX_BOT_COMMENTS_PER_WEEK: hfacts['bot_spam'] = True # Is this a new module? hfacts['new_module_request'] = False if 'feature_idea' in self.issue.desired_labels: if self.template_data['component name'] == 'new': hfacts['new_module_request'] = True # who made this and when did they last comment? submitter = self.issue.get_submitter() submitter_last_commented = self.history.last_commented_at(submitter) if not submitter_last_commented: submitter_last_commented = self.issue.instance.created_at #import epdb; epdb.st() submitter_last_comment = self.history.last_comment(submitter) submitter_last_notified = self.history.last_notified(submitter) # what did they not provide? missing_sections = self.issue.get_missing_sections() # Is this a valid module? if self.match: self.meta['valid_module'] = True else: self.meta['valid_module'] = False # Filed in the right place? if self.meta['valid_module']: if self.match['repository'] != self.github_repo: hfacts['correct_repo'] = False else: hfacts['correct_repo'] = True else: hfacts['correct_repo'] = True # DEBUG + FIXME - speeds up bulk triage if 'component name' in missing_sections \ and (self.match or self.github_repo == 'ansible'): missing_sections.remove('component name') #import epdb; epdb.st() # Who are the maintainers? maintainers = [x for x in self.get_module_maintainers()] #hfacts['maintainers'] = maintainers #import epdb; epdb.st() # Set a fact to indicate that we know the maintainer self.meta['maintainers_known'] = False if maintainers: self.meta['maintainers_known'] = True if 'ansible' in maintainers: maintainers.remove('ansible') maintainers.extend(self.ansible_members) if 'ansibot' in maintainers: maintainers.remove('ansibot') if submitter in maintainers: maintainers.remove(submitter) maintainers = sorted(set(maintainers)) # Has maintainer been notified? When? notification_maintainers = [x for x in self.get_module_maintainers()] if 'ansible' in notification_maintainers: notification_maintainers.extend(self.ansible_members) if 'ansibot' in notification_maintainers: notification_maintainers.remove('ansibot') hfacts['notification_maintainers'] = notification_maintainers maintainer_last_notified = self.history.\ last_notified(notification_maintainers) # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) maintainer_last_viewed = self.history.last_viewed_at(maintainers) #import epdb; epdb.st() # Has maintainer been mentioned? maintainer_mentioned = self.history.is_mentioned(maintainers) # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) # Has the maintainer ever responded? maintainer_commented = self.history.has_commented(maintainers) maintainer_last_commented = self.history.last_commented_at(maintainers) maintainer_last_comment = self.history.last_comment(maintainers) maintainer_comments = self.history.get_user_comments(maintainers) #import epdb; epdb.st() # Was the maintainer the last commentor? last_commentor_ismaintainer = False last_commentor_issubmitter = False last_commentor = self.history.last_commentor() if last_commentor in maintainers and last_commentor != self.github_user: last_commentor_ismaintainer = True elif last_commentor == submitter: last_commentor_issubmitter = True # Did the maintainer issue a command? maintainer_commands = self.history.get_commands(maintainers, self.VALID_COMMANDS) # Keep all commands hfacts['maintainer_commands'] = maintainer_commands # Set a bit for the last command given if hfacts['maintainer_commands']: hfacts['maintainer_command'] = hfacts['maintainer_commands'][-1] else: hfacts['maintainer_command'] = None # Is the last command a closure command? if hfacts['maintainer_command'] in self.CLOSURE_COMMANDS: hfacts['maintainer_closure'] = True else: hfacts['maintainer_closure'] = False # handle resolved_by_pr ... if 'resolved_by_pr' in maintainer_commands: maintainer_comments = self.history.get_user_comments(maintainers) maintainer_comments = [x for x in reversed(maintainer_comments) \ if 'resolved_by_pr' in x] for comment in maintainer_comments: pr_number = extract_pr_number_from_comment(comment) hfacts['resolved_by_pr'] = { 'number': pr_number, 'merged': self.is_pr_merged(pr_number), } if not hfacts['resolved_by_pr']['merged']: hfacts['maintainer_closure'] = False break # needs_info toggles ni_commands = [x for x in maintainer_commands if 'needs_info' in x] # Has the maintainer ever subscribed? maintainer_subscribed = self.history.has_subscribed(maintainers) # Was it ever needs_info? was_needs_info = self.history.was_labeled(label='needs_info') needsinfo_last_applied = self.history.label_last_applied('needs_info') needsinfo_last_removed = self.history.label_last_removed('needs_info') # Still needs_info? needsinfo_add = False needsinfo_remove = False if 'needs_info' in self.issue.current_labels: if not needsinfo_last_applied or not submitter_last_commented: import epdb; epdb.st() if submitter_last_commented > needsinfo_last_applied: needsinfo_add = False needsinfo_remove = True #if 'needs_info' in maintainer_commands and maintainer_last_commented: if ni_commands and maintainer_last_commented: if ni_commands[-1] == 'needs_info': #import epdb; epdb.st() if submitter_last_commented and maintainer_last_commented: if submitter_last_commented > maintainer_last_commented: needsinfo_add = False needsinfo_remove = True else: needsinfo_add = True needsinfo_remove = False else: needsinfo_add = False needsinfo_remove = True # Save existing needs_info if not time to remove ... if 'needs_info' in self.issue.current_labels \ and not needsinfo_add \ and not needsinfo_remove: needsinfo_add = True if ni_commands and maintainer_last_commented: if maintainer_last_commented > submitter_last_commented: if ni_commands[-1] == 'needs_info': needsinfo_add = True needsinfo_remove = False else: needsinfo_add = False needsinfo_remove = True #import epdb; epdb.st() # Is needs_info stale or expired? needsinfo_age = None needsinfo_stale = False needsinfo_expired = False if 'needs_info' in self.issue.current_labels: time_delta = today - needsinfo_last_applied needsinfo_age = time_delta.days if needsinfo_age > self.RENOTIFY_INTERVAL: needsinfo_stale = True if needsinfo_age > self.RENOTIFY_EXPIRE: needsinfo_expired = True # Should we be in waiting_on_maintainer mode? maintainer_waiting_on = False if (needsinfo_remove or not needsinfo_add) \ or not was_needs_info \ and not missing_sections: maintainer_waiting_on = True # Should we [re]notify the submitter? submitter_waiting_on = False submitter_to_ping = False submitter_to_reping = False if not maintainer_waiting_on: submitter_waiting_on = True if missing_sections: submitter_waiting_on = True maintainer_waiting_on = False # use [!]needs_info to set final state if ni_commands: if ni_commands[-1] == '!needs_info': submitter_waiting_on = False maintainer_waiting_on = True elif ni_commands[-1] == 'needs_info': submitter_waiting_on = True maintainer_waiting_on = False # Time to [re]ping maintainer? maintainer_to_ping = False maintainer_to_reping = False if maintainer_waiting_on: # if feature idea, extend the notification interval interval = self.RENOTIFY_INTERVAL if self.meta.get('issue_type', None) == 'feature idea' \ or 'feature_idea' in self.issue.current_labels: interval = self.FEATURE_RENOTIFY_INTERVAL if maintainer_viewed and not maintainer_last_notified: time_delta = today - maintainer_last_viewed view_age = time_delta.days if view_age > interval: maintainer_to_reping = True elif maintainer_last_notified: time_delta = today - maintainer_last_notified ping_age = time_delta.days if ping_age > interval: maintainer_to_reping = True else: maintainer_to_ping = True # Time to [re]ping the submitter? if submitter_waiting_on: if submitter_last_notified: time_delta = today - submitter_last_notified notification_age = time_delta.days if notification_age > self.RENOTIFY_INTERVAL: submitter_to_reping = True else: submitter_to_reping = False submitter_to_ping = False else: submitter_to_ping = True submitter_to_reping = False # needs_contributor ... hfacts['needs_contributor'] = False for command in maintainer_commands: if command == 'needs_contributor': hfacts['needs_contributor'] = True elif command == '!needs_contributor': hfacts['needs_contributor'] = False hfacts['bot_broken'] = bot_broken hfacts['bot_skip'] = bot_skip hfacts['missing_sections'] = missing_sections hfacts['was_needsinfo'] = was_needs_info hfacts['needsinfo_age'] = needsinfo_age hfacts['needsinfo_stale'] = needsinfo_stale hfacts['needsinfo_expired'] = needsinfo_expired hfacts['needsinfo_add'] = needsinfo_add hfacts['needsinfo_remove'] = needsinfo_remove hfacts['notification_maintainers'] = self.get_module_maintainers() or 'ansible' hfacts['maintainer_last_notified'] = maintainer_last_notified hfacts['maintainer_commented'] = maintainer_commented hfacts['maintainer_viewed'] = maintainer_viewed hfacts['maintainer_subscribed'] = maintainer_subscribed hfacts['maintainer_command_needsinfo'] = 'needs_info' in maintainer_commands hfacts['maintainer_command_not_needsinfo'] = '!needs_info' in maintainer_commands hfacts['maintainer_waiting_on'] = maintainer_waiting_on hfacts['maintainer_to_ping'] = maintainer_to_ping hfacts['maintainer_to_reping'] = maintainer_to_reping hfacts['submitter'] = submitter hfacts['submitter_waiting_on'] = submitter_waiting_on hfacts['submitter_to_ping'] = submitter_to_ping hfacts['submitter_to_reping'] = submitter_to_reping hfacts['last_commentor_ismaintainer'] = last_commentor_ismaintainer hfacts['last_commentor_issubmitter'] = last_commentor_issubmitter hfacts['last_commentor'] = last_commentor return hfacts
def get_history_facts(self, usecache=True): hfacts = {} today = self.get_current_time() self.history = HistoryWrapper(self.issue, usecache=usecache, cachedir=self.cachedir) # what was the last commment? bot_broken = False if self.issue.current_comments: for comment in self.issue.current_comments: if 'bot_broken' in comment.body: bot_broken = True # who made this and when did they last comment? submitter = self.issue.get_submitter() submitter_last_commented = self.history.last_commented_at(submitter) if not submitter_last_commented: submitter_last_commented = self.issue.instance.created_at #import epdb; epdb.st() submitter_last_comment = self.history.last_comment(submitter) submitter_last_notified = self.history.last_notified(submitter) # what did they not provide? missing_sections = self.issue.get_missing_sections() #if 'ansible version' in missing_sections: # missing_sections.remove('ansible version') # DEBUG + FIXME - speeds up bulk triage if 'component name' in missing_sections \ and (self.match or self.github_repo == 'ansible'): missing_sections.remove('component name') #import epdb; epdb.st() # Who are the maintainers? maintainers = [x for x in self.get_module_maintainers()] if 'ansible' in maintainers: maintainers.remove('ansible') maintainers.extend(self.ansible_members) if 'ansibot' in maintainers: maintainers.remove('ansibot') if submitter in maintainers: maintainers.remove(submitter) maintainers = sorted(set(maintainers)) # Has maintainer been notified? When? notification_maintainers = self.get_module_maintainers() if 'ansible' in notification_maintainers: notification_maintainers.extend(self.ansible_members) if 'ansibot' in notification_maintainers: notification_maintainers.remove('ansibot') maintainer_last_notified = self.history.\ last_notified(notification_maintainers) # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) maintainer_last_viewed = self.history.last_viewed_at(maintainers) #import epdb; epdb.st() # Has maintainer been mentioned? maintainer_mentioned = self.history.is_mentioned(maintainers) # Has maintainer viewed issue? maintainer_viewed = self.history.has_viewed(maintainers) # Has the maintainer ever responded? maintainer_commented = self.history.has_commented(maintainers) maintainer_last_commented = self.history.last_commented_at(maintainers) maintainer_last_comment = self.history.last_comment(maintainers) maintainer_comments = self.history.get_user_comments(maintainers) #import epdb; epdb.st() # Was the maintainer the last commentor? last_commentor_ismaintainer = False last_commentor_issubmitter = False last_commentor = self.history.last_commentor() if last_commentor in maintainers and last_commentor != self.github_user: last_commentor_ismaintainer = True elif last_commentor == submitter: last_commentor_issubmitter = True # Did the maintainer issue a command? maintainer_commands = self.history.get_commands( maintainers, self.VALID_COMMANDS) # needs_info toggles ni_commands = [x for x in maintainer_commands if 'needs_info' in x] # Has the maintainer ever subscribed? maintainer_subscribed = self.history.has_subscribed(maintainers) # Was it ever needs_info? was_needs_info = self.history.was_labeled(label='needs_info') needsinfo_last_applied = self.history.label_last_applied('needs_info') needsinfo_last_removed = self.history.label_last_removed('needs_info') # Still needs_info? needsinfo_add = False needsinfo_remove = False if 'needs_info' in self.issue.current_labels: if not needsinfo_last_applied or not submitter_last_commented: import epdb epdb.st() if submitter_last_commented > needsinfo_last_applied: needsinfo_add = False needsinfo_remove = True #if 'needs_info' in maintainer_commands and maintainer_last_commented: if ni_commands and maintainer_last_commented: if ni_commands[-1] == 'needs_info': #import epdb; epdb.st() if submitter_last_commented and maintainer_last_commented: if submitter_last_commented > maintainer_last_commented: needsinfo_add = False needsinfo_remove = True else: needsinfo_add = True needsinfo_remove = False else: needsinfo_add = False needsinfo_remove = True # Save existing needs_info if not time to remove ... if 'needs_info' in self.issue.current_labels \ and not needsinfo_add \ and not needsinfo_remove: needsinfo_add = True if ni_commands and maintainer_last_commented: if maintainer_last_commented > submitter_last_commented: if ni_commands[-1] == 'needs_info': needsinfo_add = True needsinfo_remove = False else: needsinfo_add = False needsinfo_remove = True #import epdb; epdb.st() # Is needs_info stale or expired? needsinfo_age = None needsinfo_stale = False needsinfo_expired = False if 'needs_info' in self.issue.current_labels: time_delta = today - needsinfo_last_applied needsinfo_age = time_delta.days if needsinfo_age > 14: needsinfo_stale = True if needsinfo_age > 56: needsinfo_expired = True # Should we be in waiting_on_maintainer mode? maintainer_waiting_on = False if (needsinfo_remove or not needsinfo_add) \ or not was_needs_info \ and not missing_sections: maintainer_waiting_on = True # Should we [re]notify the submitter? submitter_waiting_on = False submitter_to_ping = False submitter_to_reping = False if not maintainer_waiting_on: submitter_waiting_on = True if missing_sections: submitter_waiting_on = True maintainer_waiting_on = False # use [!]needs_info to set final state if ni_commands: if ni_commands[-1] == '!needs_info': submitter_waiting_on = False maintainer_waiting_on = True elif ni_commands[-1] == 'needs_info': submitter_waiting_on = True maintainer_waiting_on = False # Time to [re]ping maintainer? maintainer_to_ping = False maintainer_to_reping = False if maintainer_waiting_on: #import epdb; epdb.st() if maintainer_viewed and not maintainer_last_notified: time_delta = today - maintainer_last_viewed view_age = time_delta.days if view_age > 14: maintainer_to_reping = True elif maintainer_last_notified: time_delta = today - maintainer_last_notified ping_age = time_delta.days if ping_age > 14: maintainer_to_reping = True else: maintainer_to_ping = True # Time to [re]ping the submitter? if submitter_waiting_on: if submitter_last_notified: time_delta = today - submitter_last_notified notification_age = time_delta.days if notification_age > 14: submitter_to_reping = True else: submitter_to_reping = False submitter_to_ping = False else: submitter_to_ping = True submitter_to_reping = False hfacts['bot_broken'] = bot_broken hfacts['missing_sections'] = missing_sections hfacts['was_needsinfo'] = was_needs_info hfacts['needsinfo_age'] = needsinfo_age hfacts['needsinfo_stale'] = needsinfo_stale hfacts['needsinfo_expired'] = needsinfo_expired hfacts['needsinfo_add'] = needsinfo_add hfacts['needsinfo_remove'] = needsinfo_remove hfacts['notification_maintainers'] = self.get_module_maintainers( ) or 'ansible' hfacts['maintainer_last_notified'] = maintainer_last_notified hfacts['maintainer_commented'] = maintainer_commented hfacts['maintainer_viewed'] = maintainer_viewed hfacts['maintainer_subscribed'] = maintainer_subscribed hfacts[ 'maintainer_command_needsinfo'] = 'needs_info' in maintainer_commands hfacts[ 'maintainer_command_not_needsinfo'] = '!needs_info' in maintainer_commands hfacts['maintainer_waiting_on'] = maintainer_waiting_on hfacts['maintainer_to_ping'] = maintainer_to_ping hfacts['maintainer_to_reping'] = maintainer_to_reping hfacts['submitter'] = submitter hfacts['submitter_waiting_on'] = submitter_waiting_on hfacts['submitter_to_ping'] = submitter_to_ping hfacts['submitter_to_reping'] = submitter_to_reping hfacts['last_commentor_ismaintainer'] = last_commentor_ismaintainer hfacts['last_commentor_issubmitter'] = last_commentor_issubmitter hfacts['last_commentor'] = last_commentor #import epdb; epdb.st() return hfacts