def test_context_local(): responses.add(responses.GET, "https://google.com") # set up two apps with two different set of auth tokens app1 = Flask(__name__) jbp1 = make_jira_blueprint( "https://t1.atlassian.com", "foo1", "bar1", redirect_to="url1" ) app1.register_blueprint(jbp1) app2 = Flask(__name__) jbp2 = make_jira_blueprint( "https://t2.atlassian.com", "foo2", "bar2", redirect_to="url2" ) app2.register_blueprint(jbp2) # outside of a request context, referencing functions on the `jira` object # will raise an exception with pytest.raises(RuntimeError): jira.get("https://google.com") # inside of a request context, `jira` should be a proxy to the correct # blueprint session with app1.test_request_context("/"): jbp1.session.auth.client.get_oauth_signature = mock.Mock(return_value="sig1") jbp2.session.auth.client.get_oauth_signature = mock.Mock(return_value="sig2") app1.preprocess_request() jira.get("https://google.com") auth_header = dict( parse_authorization_header( responses.calls[0].request.headers["Authorization"].decode("utf-8") ) ) assert auth_header["oauth_consumer_key"] == "foo1" assert auth_header["oauth_signature"] == "sig1" with app2.test_request_context("/"): jbp1.session.auth.client.get_oauth_signature = mock.Mock(return_value="sig1") jbp2.session.auth.client.get_oauth_signature = mock.Mock(return_value="sig2") app2.preprocess_request() jira.get("https://google.com") auth_header = dict( parse_authorization_header( responses.calls[1].request.headers["Authorization"].decode("utf-8") ) ) assert auth_header["oauth_consumer_key"] == "foo2" assert auth_header["oauth_signature"] == "sig2"
def index(): """ Display an HTML overview page, with links to other functions that this application can perform. """ github_username = None if github_session.authorized: gh_user_resp = github_session.get("/user") if gh_user_resp.ok: try: github_username = gh_user_resp.json()["login"] except Exception as e: logger.error("Failed to process response: {}".format( gh_user_resp.text)) raise jira_username = None if jira_session.authorized: jira_user_resp = jira_session.get("/rest/api/2/myself") if jira_user_resp.ok: try: jira_username = jira_user_resp.json()["displayName"] except Exception as e: logger.error("Failed to process response: {}".format( jira_user_resp.text)) raise return render_template( "main.html", github_username=github_username, jira_username=jira_username, )
def get_jira_custom_fields(): """ Return a name-to-id mapping for the custom fields on JIRA. """ field_resp = jira.get("/rest/api/2/field") if not field_resp.ok: raise requests.exceptions.RequestException(field_resp.text) field_map = dict(pop_dict_id(f) for f in field_resp.json()) return { value["name"]: id for id, value in field_map.items() if value["custom"] }
def test_context_local(): responses.add(responses.GET, "https://google.com") # set up two apps with two different set of auth tokens app1 = Flask(__name__) jbp1 = make_jira_blueprint("https://t1.atlassian.com", "foo1", "bar1", redirect_to="url1") app1.register_blueprint(jbp1) app2 = Flask(__name__) jbp2 = make_jira_blueprint("https://t2.atlassian.com", "foo2", "bar2", redirect_to="url2") app2.register_blueprint(jbp2) # outside of a request context, referencing functions on the `jira` object # will raise an exception with pytest.raises(RuntimeError): jira.get("https://google.com") # inside of a request context, `jira` should be a proxy to the correct # blueprint session with app1.test_request_context("/"): jbp1.session.auth.client.get_oauth_signature = mock.Mock( return_value="sig1") jbp2.session.auth.client.get_oauth_signature = mock.Mock( return_value="sig2") app1.preprocess_request() jira.get("https://google.com") assert len(responses.calls) > 0 auth_header = dict( parse_authorization_header( responses.calls[0].request.headers["Authorization"].decode( "utf-8"))) assert auth_header["oauth_consumer_key"] == "foo1" assert auth_header["oauth_signature"] == "sig1" with app2.test_request_context("/"): jbp1.session.auth.client.get_oauth_signature = mock.Mock( return_value="sig1") jbp2.session.auth.client.get_oauth_signature = mock.Mock( return_value="sig2") app2.preprocess_request() jira.get("https://google.com") assert len(responses.calls) > 0 auth_header = dict( parse_authorization_header( responses.calls[1].request.headers["Authorization"].decode( "utf-8"))) assert auth_header["oauth_consumer_key"] == "foo2" assert auth_header["oauth_signature"] == "sig2"
def index(): """ Just to verify that things are working """ github_username = None if github_session._client.token: gh_user_resp = github_session.get("/user") if gh_user_resp.ok: github_username = gh_user_resp.json()["login"] jira_username = None if jira_session.auth.client.resource_owner_key: jira_user_resp = jira_session.get("/rest/api/2/myself") if jira_user_resp.ok: jira_username = jira_user_resp.json()["name"] return render_template("main.html", github_username=github_username, jira_username=jira_username, )
def index(): """ Just to verify that things are working """ github_username = None if github_session._client.token: gh_user_resp = github_session.get("/user") if gh_user_resp.ok: github_username = gh_user_resp.json()["login"] jira_username = None if jira_session.auth.client.resource_owner_key: jira_user_resp = jira_session.get("/rest/api/2/myself") if jira_user_resp.ok: jira_username = jira_user_resp.json()["name"] return render_template( "main.html", github_username=github_username, jira_username=jira_username, )
def index(): """ Display an HTML overview page, with links to other functions that this application can perform. """ github_username = None if github_session.authorized: gh_user_resp = github_session.get("/user") if gh_user_resp.ok: github_username = gh_user_resp.json()["login"] jira_username = None if jira_session.authorized: jira_user_resp = jira_session.get("/rest/api/2/myself") if jira_user_resp.ok: jira_username = jira_user_resp.json()["name"] return render_template("main.html", github_username=github_username, jira_username=jira_username, )
def index(): """ Display an HTML overview page, with links to other functions that this application can perform. """ github_username = None if github_session.authorized: gh_user_resp = github_session.get("/user") if gh_user_resp.ok: github_username = gh_user_resp.json()["login"] jira_username = None if jira_session.authorized: jira_user_resp = jira_session.get("/rest/api/2/myself") if jira_user_resp.ok: jira_username = jira_user_resp.json()["name"] return render_template( "main.html", github_username=github_username, jira_username=jira_username, )
def api_request(): jira.get("/") return "success"
def api_request(): jira.get("/") return "success"
def pr_opened(pr, bugsnag_context=None): bugsnag_context = bugsnag_context or {} user = pr["user"]["login"] repo = pr["base"]["repo"]["full_name"] people = get_people_file() if user in people and people[user].get("institution", "") == "edX": # not an open source pull request, don't create an issue for it print( "@{user} opened PR #{num} against {repo} (internal PR)".format( user=user, repo=pr["base"]["repo"]["full_name"], num=pr["number"] ), file=sys.stderr ) return "internal pull request" field_resp = jira.get("/rest/api/2/field") if not field_resp.ok: raise requests.exceptions.RequestException(field_resp.text) field_map = dict(pop_dict_id(f) for f in field_resp.json()) custom_fields = { value["name"]: id for id, value in field_map.items() if value["custom"] } user_resp = github.get(pr["user"]["url"]) if user_resp.ok: user_name = user_resp.json().get("name", user) else: user_name = user # create an issue on JIRA! new_issue = { "fields": { "project": { "key": "OSPR", }, "issuetype": { "name": "Pull Request Review", }, "summary": pr["title"], "description": pr["body"], custom_fields["URL"]: pr["html_url"], custom_fields["PR Number"]: pr["number"], custom_fields["Repo"]: pr["base"]["repo"]["full_name"], custom_fields["Contributor Name"]: user_name, } } institution = people.get(user, {}).get("institution", None) if institution: new_issue["fields"][custom_fields["Customer"]] = [institution] bugsnag_context["new_issue"] = new_issue bugsnag.configure_request(meta_data=bugsnag_context) resp = jira.post("/rest/api/2/issue", data=json.dumps(new_issue)) if not resp.ok: raise requests.exceptions.RequestException(resp.text) new_issue_body = resp.json() bugsnag_context["new_issue"]["key"] = new_issue_body["key"] bugsnag.configure_request(meta_data=bugsnag_context) # add a comment to the Github pull request with a link to the JIRA issue comment = { "body": github_pr_comment(pr, new_issue_body, people), } url = "/repos/{repo}/issues/{num}/comments".format( repo=repo, num=pr["number"], ) comment_resp = github.post(url, data=json.dumps(comment)) if not comment_resp.ok: raise requests.exceptions.RequestException(comment_resp.text) print( "@{user} opened PR #{num} against {repo}, created {issue} to track it".format( user=user, repo=repo, num=pr["number"], issue=new_issue_body["key"] ), file=sys.stderr ) return "created!"
def pr_closed(pr, bugsnag_context=None): bugsnag_context = bugsnag_context or {} repo = pr["base"]["repo"]["full_name"] merged = pr["merged"] issue_key = get_jira_issue_key(pr) if not issue_key: print( "Couldn't find JIRA issue for PR #{num} against {repo}".format( num=pr["number"], repo=repo, ), file=sys.stderr ) return "no JIRA issue :(" bugsnag_context["jira_key"] = issue_key bugsnag.configure_request(meta_data=bugsnag_context) # close the issue on JIRA transition_url = ( "/rest/api/2/issue/{key}/transitions" "?expand=transitions.fields".format(key=issue_key) ) transitions_resp = jira.get(transition_url) if not transitions_resp.ok: raise requests.exceptions.RequestException(transitions_resp.text) transitions = transitions_resp.json()["transitions"] bugsnag_context["transitions"] = transitions bugsnag.configure_request(meta_data=bugsnag_context) transition_name = "Merged" if merged else "Rejected" transition_id = None for t in transitions: if t["to"]["name"] == transition_name: transition_id = t["id"] break if not transition_id: # maybe the issue is *already* in the right status? issue_url = "/rest/api/2/issue/{key}".format(key=issue_key) issue_resp = jira.get(issue_url) if not issue_resp.ok: raise requests.exceptions.RequestException(issue_resp.text) issue = issue_resp.json() bugsnag_context["jira_issue"] = issue bugsnag.configure_request(meta_data=bugsnag_context) if issue["fields"]["status"]["name"] == transition_name: msg = "{key} is already in status {status}".format( key=issue_key, status=transition_name ) print(msg, file=sys.stderr) return "nothing to do!" fail_msg = ( "{key} cannot be transitioned directly to status {status}. " "Valid status transitions are: {valid}".format( key=issue_key, status=transition_name, valid=set(t["to"]["name"] for t in transitions), ) ) assert transition_id, fail_msg transition_resp = jira.post(transition_url, data=json.dumps({ "transition": { "id": transition_id, } })) if not transition_resp.ok: raise requests.exceptions.RequestException(transition_resp.text) print( "PR #{num} against {repo} was {action}, moving {issue} to status {status}".format( num=pr["number"], repo=repo, action="merged" if merged else "closed", issue=issue_key, status="Merged" if merged else "Rejected", ), file=sys.stderr ) return "closed!"
def pr_closed(pr, bugsnag_context=None): bugsnag_context = bugsnag_context or {} repo = pr["base"]["repo"]["full_name"].decode('utf-8') merged = pr["merged"] issue_key = get_jira_issue_key(pr) if not issue_key: print( "Couldn't find JIRA issue for PR #{num} against {repo}".format( num=pr["number"], repo=repo, ), file=sys.stderr ) return "no JIRA issue :(" bugsnag_context["jira_key"] = issue_key bugsnag.configure_request(meta_data=bugsnag_context) # close the issue on JIRA transition_url = ( "/rest/api/2/issue/{key}/transitions" "?expand=transitions.fields".format(key=issue_key) ) transitions_resp = jira.get(transition_url) transitions_resp.raise_for_status() transitions = transitions_resp.json()["transitions"] bugsnag_context["transitions"] = transitions bugsnag.configure_request(meta_data=bugsnag_context) transition_name = "Merged" if merged else "Rejected" transition_id = None for t in transitions: if t["to"]["name"] == transition_name: transition_id = t["id"] break if not transition_id: # maybe the issue is *already* in the right status? issue_url = "/rest/api/2/issue/{key}".format(key=issue_key) issue_resp = jira.get(issue_url) issue_resp.raise_for_status() issue = issue_resp.json() bugsnag_context["jira_issue"] = issue bugsnag.configure_request(meta_data=bugsnag_context) current_status = issue["fields"]["status"]["name"].decode("utf-8") if current_status == transition_name: msg = "{key} is already in status {status}".format( key=issue_key, status=transition_name ) print(msg, file=sys.stderr) return "nothing to do!" # nope, raise an error message fail_msg = ( "{key} cannot be transitioned directly from status {curr_status} " "to status {new_status}. Valid status transitions are: {valid}".format( key=issue_key, new_status=transition_name, curr_status=current_status, valid=", ".join(t["to"]["name"].decode('utf-8') for t in transitions), ) ) raise Exception(fail_msg) transition_resp = jira.post(transition_url, json={ "transition": { "id": transition_id, } }) transition_resp.raise_for_status() print( "PR #{num} against {repo} was {action}, moving {issue} to status {status}".format( num=pr["number"], repo=repo, action="merged" if merged else "closed", issue=issue_key, status="Merged" if merged else "Rejected", ), file=sys.stderr ) return "closed!"