Esempio n. 1
0
 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)
Esempio n. 2
0
 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)
Esempio n. 3
0
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.')
Esempio n. 4
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=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)
Esempio n. 5
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)
Esempio n. 6
0
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.')
Esempio n. 7
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.')
Esempio n. 8
0
 def end_project_admin(self, request, project):
     end_project(project.id)
     self.message_user(request, 'Project successfully ended.')
Esempio n. 9
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.')