def send_logs( self, tracker_issue: TrackerIssue, logs: List[Log], ) -> SendLogsResult: """ Send logs to the tracker. Args: tracker_issue: information about the tracker issue logs: a list of logs Returns: information about the sent logs """ jira_issue = self._get_issue(issue_id=tracker_issue.issue_id, ) tracker_comments = SendLogsResult( tracker_issue=tracker_issue, added_comments=[], ) for log in logs: jira_comment = self._add_comment( issue=jira_issue, log=log, ) tracker_comments.added_comments.append( TrackerIssueComment( created_at=self._parse_date(date=jira_comment.created, ), author=jira_comment.author.displayName, comment_id=str(jira_comment.id), body=jira2markdown(src=jira_comment.body, ), attachments={}, ), ) return tracker_comments
def send_logs( self, tracker_issue: TrackerIssue, logs: Iterable[Log], ) -> SendLogsResult: """ Send logs to the tracker. Args: tracker_issue: information about the tracker issue logs: a list of comments Raises: GitHubTrackerClientError: if an error occurs Returns: information about the sent comments """ self._ensure_auth() tracker_comments = SendLogsResult( tracker_issue=tracker_issue, added_comments=[], ) github_issue = self._get_github_issue( issue_id=tracker_issue.issue_id, ) if not github_issue: raise GitHubTrackerClientError( f'GitHub issue {tracker_issue.issue_id} not found') for log in logs: github_comment = self._add_comment( github_issue=github_issue, log=log, ) self._upload_comment_attachments( issue=github_issue, comment=github_comment, attachments=log.attachments, ) tracker_comments.added_comments.append( TrackerIssueComment( author=github_comment.user.name or github_comment.user.login, created_at=self._ensure_timezone( dt=github_comment.created_at, tz=self._default_timezone, ), comment_id=str(github_comment.id), body=github_comment.body, attachments={}, ), ) return tracker_comments
def send_logs( self, tracker_issue: TrackerIssue, logs: Iterable[Log], ) -> SendLogsResult: """ Send logs to the tracker. Args: tracker_issue: information about the tracker issue logs: a list of comments Raises: GitLabTrackerClientError: if an error occurs Returns: information about the sent comments """ self._ensure_auth() tracker_comments = SendLogsResult( tracker_issue=tracker_issue, added_comments=[], ) gitlab_project = self._get_gitlab_project() gitlab_issue = self._get_gitlab_issue( issue_id=tracker_issue.issue_id, ) if not gitlab_issue: raise GitLabTrackerClientError( f'GitLab issue {tracker_issue.issue_id} not found in project {self.configuration.project}', ) for log in logs: gitlab_comment = self._add_comment( gitlab_project=gitlab_project, gitlab_issue=gitlab_issue, log=log, ) tracker_comments.added_comments.append( TrackerIssueComment( created_at=self._parse_date( date=gitlab_comment.created_at, ), author=gitlab_comment.author.get( 'name', self._default_author_name), comment_id=str(gitlab_comment.id), body=gitlab_comment.body, attachments={}, ), ) return tracker_comments
def _send_synchronizable_logs( self, tracker_issue: TrackerIssue, logs: List[Log], ) -> SendLogsResult: synchronizable_logs = [] for log in logs: synchronize = self._is_synchronizable_log(log=log, ) if synchronize: synchronizable_logs.append(log) if not synchronizable_logs: return SendLogsResult( tracker_issue=tracker_issue, added_comments=[], ) return self._send_logs( tracker_issue=tracker_issue, logs=synchronizable_logs, )
def test_partially_synced(self, ) -> None: comment_log1 = CommentLog( created_at='2021-01-01T00:00:00+00:00', log_id=1, log_type='comment', private=True, author=Author(username='******', ), message_html='This is a comment', attachments=[], ) tracking_status = TrackingStatusLog( created_at='2021-01-01T00:30:00+00:00', log_id=1, log_type='tracking-status', private=True, author=Author(username='******', ), message_html='Tracked', attachments=[], tracker_name='my-tracker', tracker_url='http://tracker/issue/1', tracker_id='1', ) tracker_update_log1 = TrackerUpdateLog( created_at='2021-01-01T01:00:00+00:00', log_id=2, log_type='tracker-update', private=True, author=Author(username='******', ), message_html='This is a a tracker update', attachments=[], tracker_name='my-tracker', tracker_id='1', tracker_url='http://tracker/issue/1', tracker_token=StateEncryptor.encrypt( key='123', state=TrackerIssueState( closed=False, bugtracker_name='my-tracker', ), ), ) comment_log2 = CommentLog( created_at='2021-01-01T02:00:00+00:00', log_id=3, log_type='comment', private=True, author=Author(username='******', ), message_html='This is another comment', attachments=[], ) report = self._build_report( report_id=123, tracking_status='T', logs=[ comment_log1, tracking_status, tracker_update_log1, comment_log2, ], ) ywh_api_client_mock = create_autospec(YesWeHackApiClient, spec_set=True) tracker_client_mock = create_autospec(TrackerClient, spec_set=True) tracker_client_mock.tracker_type = 'MyTracker' issue = TrackerIssue( tracker_url='http://tracker/issue/1', project='my-project', issue_id='1', issue_url='http://tracker/issue/1', closed=False, ) tracker_client_mock.get_tracker_issue.return_value = issue tracker_client_mock.send_logs.return_value = SendLogsResult( tracker_issue=issue, added_comments=[ TrackerIssueComment( created_at=datetime.datetime( year=2020, month=1, day=1, hour=15, minute=17, second=23, microsecond=420000, tzinfo=datetime.timezone.utc, ), author='tracker-user', comment_id='456', body='', attachments={}, ), ], ) Given( case=self, report=report, yeswehack_client=ywh_api_client_mock, tracker_name='my-tracker', tracker_client=tracker_client_mock, synchronize_options=SynchronizeOptions( upload_private_comments=True, upload_public_comments=True, upload_details_updates=True, upload_rewards=True, upload_status_updates=True, ), feedback_options=FeedbackOptions(), message_formatter=SimpleMessageFormatter( tracking_status_update_format= 'issue url: {tracker_issue.issue_url}', synchronization_done_format= 'issue url: {send_logs_result.tracker_issue.issue_url}', download_comment_format='comment: {comment}', status_update_comment_format='comment: {comment}', ), ).when_synchronize_report().then_assert_no_error( ).then_assert_has_result().then_assert_is_existing_issue( ).then_assert_tracker_client_send_report_not_called( ).then_assert_tracker_client_send_logs_called_once_with( tracker_issue=issue, logs=[ comment_log2, ], ).then_assert_yeswehack_client_post_report_tracker_update_called_once_with( report=report, tracker_name='my-tracker', issue_id='1', issue_url='http://tracker/issue/1', comment='issue url: http://tracker/issue/1', token=StateEncryptor.encrypt( key='123', state=TrackerIssueState(closed=False, bugtracker_name='my-tracker', downloaded_comments=['456']), ), )
def synchronize_report(self, ) -> SynchronizeReportResult: """ Synchronize a YesWeHack report and a tracker issue. Raises: SynchronizerError: if a synchronization error occur Returns: the result of the synchronization """ log = self._report.get_last_tracking_status_update_log( tracker_name=self._tracker_name, ) is_created_issue = False tracker_issue = None if log and isinstance(log, TrackingStatusLog): is_created_issue = True tracker_issue = self._get_tracker_issue_from_logs(log=log, ) if tracker_issue is None: if not self._synchronize_options.recreate_missing_issues: return SynchronizeReportResult( is_created_issue=is_created_issue, is_existing_issue=False, new_report_status=None, send_logs_result=SendLogsResult( tracker_issue=None, added_comments=[], ), download_comments_result=DownloadCommentsResult( downloaded_comments=[], ), ) is_created_issue = False tracker_issue = self._create_tracker_issue() if not isinstance(tracker_issue, TrackerIssue): raise SynchronizerError( f'Unable to create new or get existing issue for #{self._report.report_id} in {self._tracker_name}', ) if self._report.tracking_status != 'T' or not is_created_issue: self._update_tracking_status(tracker_issue=tracker_issue, ) tracker_issue_state = TrackerIssueState( closed=False, bugtracker_name=self._tracker_name, ) logs = self._report.logs if is_created_issue: log_state = self._get_last_tracker_update_log() if log_state: last_tracker_update_log, tracker_issue_state = log_state if last_tracker_update_log: logs = self._report.get_logs_after( log=last_tracker_update_log, ) send_logs_result = self._send_synchronizable_logs( tracker_issue=tracker_issue, logs=logs, ) for added_comment in send_logs_result.added_comments: tracker_issue_state.add_downloaded_comment( added_comment.comment_id) download_comments_result = self._download_comments( tracker_issue=tracker_issue, exclude_comments=tracker_issue_state.downloaded_comments, ) for downloaded_comment in download_comments_result.downloaded_comments: tracker_issue_state.add_downloaded_comment(downloaded_comment) new_report_status = self._update_report_status( tracker_issue=tracker_issue, tracker_issue_state=tracker_issue_state, ) issue_status = self._get_issue_status_change( tracker_issue=tracker_issue, tracker_issue_state=tracker_issue_state, ) tracker_issue_state.closed = tracker_issue.closed self._post_report_tracker_update( tracker_issue=tracker_issue, tracker_issue_state=tracker_issue_state, send_logs_result=send_logs_result, download_comments_result=download_comments_result, new_report_status=new_report_status, issue_status=issue_status, ) return SynchronizeReportResult( is_created_issue=is_created_issue, is_existing_issue=True, new_report_status=new_report_status, send_logs_result=send_logs_result, download_comments_result=download_comments_result, )