def test_end_project(self): project = self.projects['project_to_end'] end_project(project.id) self.assertEquals(Project.objects.get(id=project.id).status, Project.Status.ABORTED) for task in Task.objects.filter(project=project): self.assertEquals(task.status, Task.Status.ABORTED)
def test_end_project_calls_abort_completion_function( self, mock_abort_cleanup_fn, mock_archive_project_slack_group): path = 'orchestra.tests.helpers.workflow.abort_cleanup_function' abort_completion_function = { 'path': path, 'kwargs': { 'some_key': 'some_value' } } project = self.projects['test_human_and_machine'] project.workflow_version.abort_completion_function = ( abort_completion_function) project.workflow_version.save() end_project(project.id) kwargs = abort_completion_function['kwargs'] mock_abort_cleanup_fn.assert_called_with( project, **kwargs)
def end_project_api(request): project_id = load_encoded_json(request.body)['project_id'] try: end_project(project_id) except Project.DoesNotExist: raise BadRequest('Project not found for the given id.')
def test_notify_status_change(self): project = self.projects['empty_project'] internal_name = settings.SLACK_INTERNAL_NOTIFICATION_CHANNEL.strip('#') internal_groups = [ group for group in self.slack.groups.list().body['groups'] if group['name'] == internal_name ] internal_group_id = internal_groups[0]['id'] internal_slack_messages = self.slack.get_messages(internal_group_id) experts_slack_messages = self.slack.get_messages( project.slack_group_id) def _validate_slack_messages(message_stub): """ Check that correct slack message was sent if API key present. """ self.assertIn(message_stub, internal_slack_messages.pop()) self.assertIn(message_stub, experts_slack_messages.pop()) task = TaskFactory(project=project, step=self.test_step, status=Task.Status.AWAITING_PROCESSING) # Entry-level worker picks up task self.assertEqual(task.status, Task.Status.AWAITING_PROCESSING) task = assign_task(self.workers[0].id, task.id) self.assertTrue(task.is_worker_assigned(self.workers[0])) # Notification should be sent to entry-level worker self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[0].user.email) self.assertEqual(notification['subject'], "You've been assigned to a new task!") _validate_slack_messages('Task has been picked up by a worker.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=True): # Entry-level worker submits task task = submit_task(task.id, {}, Iteration.Status.REQUESTED_REVIEW, self.workers[0]) self.assertEqual(task.status, Task.Status.PENDING_REVIEW) # Notification should be sent to entry-level worker self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[0].user.email) self.assertEqual(notification['subject'], 'Your task is under review!') _validate_slack_messages('Task is awaiting review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Reviewer picks up task task = assign_task(self.workers[1].id, task.id) self.assertEqual(task.status, Task.Status.REVIEWING) # No notification should be sent self.assertEqual(len(self.mail.inbox), 0) _validate_slack_messages('Task is under review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Reviewer rejects task task = submit_task(task.id, {}, Iteration.Status.PROVIDED_REVIEW, self.workers[1]) self.assertEqual(task.status, Task.Status.POST_REVIEW_PROCESSING) # Notification should be sent to original worker self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[0].user.email) self.assertEqual(notification['subject'], 'Your task has been returned') _validate_slack_messages('Task was returned by reviewer.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Entry-level worker resubmits task task = submit_task(task.id, {}, Iteration.Status.REQUESTED_REVIEW, self.workers[0]) self.assertEqual(task.status, Task.Status.REVIEWING) # Notification should be sent to reviewer self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[1].user.email) self.assertEqual(notification['subject'], 'A task is ready for re-review!') _validate_slack_messages('Task is under review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # First reviewer accepts task with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=True): task = submit_task(task.id, {}, Iteration.Status.REQUESTED_REVIEW, self.workers[1]) self.assertEqual(task.status, Task.Status.PENDING_REVIEW) # Notification should be sent to first reviewer self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[1].user.email) self.assertEqual(notification['subject'], 'Your task is under review!') _validate_slack_messages('Task is awaiting review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Second reviewer picks up task task = assign_task(self.workers[3].id, task.id) self.assertEqual(task.status, Task.Status.REVIEWING) # No notification should be sent self.assertEqual(len(self.mail.inbox), 0) _validate_slack_messages('Task is under review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Second reviewer rejects task task = submit_task(task.id, {}, Iteration.Status.PROVIDED_REVIEW, self.workers[3]) self.assertEqual(task.status, Task.Status.POST_REVIEW_PROCESSING) # Notification should be sent to first reviewer self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[1].user.email) self.assertEqual(notification['subject'], 'Your task has been returned') _validate_slack_messages('Task was returned by reviewer.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # First reviewer resubmits task task = submit_task(task.id, {}, Iteration.Status.REQUESTED_REVIEW, self.workers[1]) self.assertEqual(task.status, Task.Status.REVIEWING) # Notification should be sent to second reviewer self.assertEqual(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEqual(notification['recipient'], self.workers[3].user.email) self.assertEqual(notification['subject'], 'A task is ready for re-review!') _validate_slack_messages('Task is under review.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # Second reviewer accepts task; task is complete with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=False): task = submit_task(task.id, {}, Iteration.Status.REQUESTED_REVIEW, self.workers[3]) self.assertEqual(task.status, Task.Status.COMPLETE) # Notification should be sent to all workers on task self.assertEqual(len(self.mail.inbox), 3) recipients = {mail['recipient'] for mail in self.mail.inbox} subjects = {mail['subject'] for mail in self.mail.inbox} self.assertEqual(recipients, {self.workers[uid].user.email for uid in (0, 1, 3)}) self.assertEqual(subjects, {'Task complete!'}) self.mail.clear() _validate_slack_messages('Task has been completed.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0) # End project end_project(task.project.id) task = Task.objects.get(id=task.id) self.assertEqual(task.status, Task.Status.ABORTED) # Notification should be sent to all workers on task self.assertEqual(len(self.mail.inbox), 3) recipients = {mail['recipient'] for mail in self.mail.inbox} subjects = {mail['subject'] for mail in self.mail.inbox} self.assertEqual(recipients, {self.workers[uid].user.email for uid in (0, 1, 3)}) self.assertEqual(subjects, {'A task you were working on has been ended'}) self.mail.clear() for task in project.tasks.all(): _validate_slack_messages('Task has been aborted.') self.assertEqual(len(internal_slack_messages), 0) self.assertEqual(len(experts_slack_messages), 0)
def test_notify_status_change(self): project = self.projects['empty_project'] internal_name = settings.SLACK_INTERNAL_NOTIFICATION_CHANNEL.strip('#') internal_groups = [ group for group in self.slack.groups.list().body['groups'] if group['name'] == internal_name] internal_group_id = internal_groups[0]['id'] internal_slack_messages = self.slack.get_messages(internal_group_id) experts_slack_messages = self.slack.get_messages( project.slack_group_id) def _validate_slack_messages(message_stub): """ Check that correct slack message was sent if API key present. """ self.assertIn(message_stub, internal_slack_messages.pop()) self.assertIn(message_stub, experts_slack_messages.pop()) task = TaskFactory(project=project, step_slug=self.test_step_slug, status=Task.Status.AWAITING_PROCESSING) # Entry-level worker picks up task self.assertEquals(task.status, Task.Status.AWAITING_PROCESSING) task = assign_task(self.workers[0].id, task.id) self.assertTrue(is_worker_assigned_to_task(self.workers[0], task)) # Notification should be sent to entry-level worker self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[0].user.email) self.assertEquals(notification['subject'], "You've been assigned to a new task!") _validate_slack_messages('Task has been picked up by a worker.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=True): # Entry-level worker submits task task = submit_task(task.id, {}, TaskAssignment.SnapshotType.SUBMIT, self.workers[0], 0) self.assertEquals(task.status, Task.Status.PENDING_REVIEW) # Notification should be sent to entry-level worker self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[0].user.email) self.assertEquals(notification['subject'], 'Your task is under review!') _validate_slack_messages('Task is awaiting review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Reviewer picks up task task = assign_task(self.workers[1].id, task.id) self.assertEquals(task.status, Task.Status.REVIEWING) # No notification should be sent self.assertEquals(len(self.mail.inbox), 0) _validate_slack_messages('Task is under review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Reviewer rejects task task = submit_task(task.id, {}, TaskAssignment.SnapshotType.REJECT, self.workers[1], 0) self.assertEquals(task.status, Task.Status.POST_REVIEW_PROCESSING) # Notification should be sent to original worker self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[0].user.email) self.assertEquals(notification['subject'], 'Your task has been returned') _validate_slack_messages('Task was returned by reviewer.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Entry-level worker resubmits task task = submit_task(task.id, {}, TaskAssignment.SnapshotType.SUBMIT, self.workers[0], 0) self.assertEquals(task.status, Task.Status.REVIEWING) # Notification should be sent to reviewer self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[1].user.email) self.assertEquals(notification['subject'], 'A task is ready for re-review!') _validate_slack_messages('Task is under review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # First reviewer accepts task with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=True): task = submit_task(task.id, {}, TaskAssignment.SnapshotType.ACCEPT, self.workers[1], 0) self.assertEquals(task.status, Task.Status.PENDING_REVIEW) # Notification should be sent to first reviewer self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[1].user.email) self.assertEquals(notification['subject'], 'Your task is under review!') _validate_slack_messages('Task is awaiting review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Second reviewer picks up task task = assign_task(self.workers[3].id, task.id) self.assertEquals(task.status, Task.Status.REVIEWING) # No notification should be sent self.assertEquals(len(self.mail.inbox), 0) _validate_slack_messages('Task is under review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Second reviewer rejects task task = submit_task(task.id, {}, TaskAssignment.SnapshotType.REJECT, self.workers[3], 0) self.assertEquals(task.status, Task.Status.POST_REVIEW_PROCESSING) # Notification should be sent to first reviewer self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[1].user.email) self.assertEquals(notification['subject'], 'Your task has been returned') _validate_slack_messages('Task was returned by reviewer.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # First reviewer resubmits task task = submit_task(task.id, {}, TaskAssignment.SnapshotType.SUBMIT, self.workers[1], 0) self.assertEquals(task.status, Task.Status.REVIEWING) # Notification should be sent to second reviewer self.assertEquals(len(self.mail.inbox), 1) notification = self.mail.inbox.pop() self.assertEquals(notification['recipient'], self.workers[3].user.email) self.assertEquals(notification['subject'], 'A task is ready for re-review!') _validate_slack_messages('Task is under review.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # Second reviewer accepts task; task is complete with patch('orchestra.utils.task_lifecycle._is_review_needed', return_value=False): task = submit_task(task.id, {}, TaskAssignment.SnapshotType.ACCEPT, self.workers[3], 0) self.assertEquals(task.status, Task.Status.COMPLETE) # Notification should be sent to all workers on task self.assertEquals(len(self.mail.inbox), 3) recipients = {mail['recipient'] for mail in self.mail.inbox} subjects = {mail['subject'] for mail in self.mail.inbox} self.assertEquals(recipients, {self.workers[uid].user.email for uid in (0, 1, 3)}) self.assertEquals(subjects, {'Task complete!'}) self.mail.clear() _validate_slack_messages('Task has been completed.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0) # End project end_project(task.project.id) task = Task.objects.get(id=task.id) self.assertEquals(task.status, Task.Status.ABORTED) # Notification should be sent to all workers on task self.assertEquals(len(self.mail.inbox), 3) recipients = {mail['recipient'] for mail in self.mail.inbox} subjects = {mail['subject'] for mail in self.mail.inbox} self.assertEquals(recipients, {self.workers[uid].user.email for uid in (0, 1, 3)}) self.assertEquals(subjects, {'A task you were working on has been ended'}) self.mail.clear() for task in project.tasks.all(): _validate_slack_messages('Task has been aborted.') self.assertEquals(len(internal_slack_messages), 0) self.assertEquals(len(experts_slack_messages), 0)
def end_project_api(request): project_id = json.loads(request.body.decode())['project_id'] try: end_project(project_id) except Project.DoesNotExist: raise BadRequest('Project not found for the given id.')
def end_project_admin(self, request, project): end_project(project.id) self.message_user(request, 'Project successfully ended.')