def test_repo_scope_private(self): """Test the private scope of the repository.""" url = 'https://api.github.com/repos/webcompat/webcompat-tests-private' expected = 'private' actual = helpers.repo_scope(url) self.assertEqual(expected, actual)
def test_repo_scope_unknown(self): """Test the unknown of the repository.""" url = 'https://api.github.com/repos/webcompat/webcompat-foobar' expected = 'unknown' actual = helpers.repo_scope(url) self.assertEqual(expected, actual)
def process_issue_action(self): """Route the actions and provide different responses. There are two possible known scopes: * public repo * private repo Currently the actions we are handling are (for now): * opened (public repo only) Aka newly issues created and need to be assigned labels and milestones * milestoned When the issue is moved to needscontact When the issue is being moderated with a milestone: accepted """ source_repo = self.repository_url scope = repo_scope(source_repo) # We do not process further in case # we don't know what we are dealing with if scope == 'unknown': return make_response('Wrong repository', 403) if self.action == 'opened' and scope == 'public': # we are setting labels on each new open issues try: self.tag_as_public() except HTTPError as e: msg_log(f'public:opened labels failed ({e})', self.number) return oops() else: return make_response('gracias, amigo.', 200) elif (self.action == 'milestoned' and scope == 'public' and self.milestoned_with == 'needscontact'): # add a comment with a link to outreach template generator # when issue is moved to needscontact try: self.comment_outreach_generator_uri() except HTTPError as e: msg_log(f'comment failed ({e})', self.number) return oops() else: return make_response('outreach generator url added', 200) elif self.action == 'opened' and scope == 'private': # webcompat-bot needs to comment public URL of the issue # and we try to classify the issue using bugbug try: self.comment_public_uri() except HTTPError as e: msg_log(f'comment failed ({e})', self.number) return oops() try: self.classify() except (HTTPError, ConnectionError) as e: msg_log(f'classification failed ({e})', self.number) return oops() return make_response('public url added and issue classified', 200) elif (self.action == 'milestoned' and scope == 'private' and self.milestoned_with == 'accepted'): # private issue have been moderated and we will make it public try: self.moderate_private_issue() except HTTPError as e: msg_log('private:moving to public failed', self.number) return oops() else: # we didn't get exceptions, so it's safe to close it self.close_private_issue() return make_response('Moderated issue accepted', 200) elif (self.action == 'milestoned' and scope == 'private' and self.milestoned_with == 'accepted: incomplete'): # The private issue has been set to the "accepted: incomplete" # milestone. This will close the public and private issues, and # leave a message for the incomplete issue. try: self.close_public_issue(reason='incomplete') except HTTPError as e: msg_log( 'private:closing public issue as incomplete failed', self.number) return oops() else: # we didn't get exceptions, so it's safe to comment why # it was closed as incomplete, and close it. self.comment_closed_reason(reason='incomplete') self.close_private_issue() return make_response('Moderated issue closed as incomplete', 200) elif (self.action == 'milestoned' and scope == 'private' and self.milestoned_with == 'accepted: invalid'): # The private issue has been set to the "accepted: invalid" # milestone. This will close the public and private issues, and # leave a message for the invalid issue. try: self.close_public_issue(reason='invalid') except HTTPError as e: msg_log( 'private:closing public issue as invalid failed', self.number) return oops() else: # we didn't get exceptions, so it's safe to comment why # it was closed as invalid, and close it. self.comment_closed_reason(reason='invalid') self.close_private_issue() return make_response('Moderated issue closed as invalid', 200) elif (self.action == 'milestoned' and scope == 'private' and self.milestoned_with == 'ml-autoclosed'): # The private issue has been automatically moved to ml-autoclosed # milestone. This will close the public and private issues, and # will replace the content of the public issue with placeholder. try: self.close_public_issue(reason='autoclosed') except HTTPError as e: msg_log( 'private:closing public issue as invalid by ml-bot failed', self.number) return oops() else: # we didn't get exceptions, so it's safe to # close the private issue. self.close_private_issue() return make_response('Issue closed as invalid by ml bot', 200) elif (scope == 'private' and self.action == 'closed' and self.milestone == 'unmoderated'): # The private issue has been closed. It is rejected and the # private and public issues will be closed with a rejected message. try: self.close_public_issue(reason='rejected') except HTTPError as e: msg_log('public rejection failed', self.number) return oops() else: # we didn't get exceptions, so it's safe to close it self.close_private_issue() return make_response('Moderated issue rejected', 200) else: return make_response('Not an interesting hook', 403)