From 2b425c28e39b9619cd23349764d88a2689a4e513 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Tue, 17 Dec 2024 10:51:22 +0200 Subject: [PATCH 1/7] Added options for replacing comment under GitHub issue with customizable 'Synced' label --- README.md | 12 ++++ github_jira_sync_app/main.py | 35 +++++++++- github_jira_sync_app/settings.yaml | 2 + tests/unit/dumm_env | 2 +- tests/unit/test_server.py | 65 +++++++++++++++++++ .../auth_github_responses_sync_label.yaml | 50 ++++++++++++++ ...github_responses_sync_label_not_found.yaml | 41 ++++++++++++ 7 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 tests/unit/url_responses/auth_github_responses_sync_label.yaml create mode 100644 tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml diff --git a/README.md b/README.md index e4c4e68..f99419e 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,18 @@ settings: # (Optional) (Default: false) Add a new comment in GitHub with a link to Jira created issue add_gh_comment: false + + # (Optional) (Default: false) Add a label with name to newly created + # issues when a corresponding ticket is created in Jira. This is meant to replace the comment + # depending on project preferences, but comments will still be added if is true. + add_gh_synced_label: false + + # (Optional) (Default: None) The name of the label to add to GitHub issues. Ignored if + # is false. A label with this name must already be present in the + # repository. If is true, misconfigurations such as the label not existing, or + # being unset when is true will be reported as a + # warning in the comment under the GitHub issue + gh_synced_label_name: None # (Optional) (Default: true) Synchronize issue description from GitHub to Jira sync_description: true diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 89452f6..4b76455 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -14,6 +14,7 @@ from github import GithubException from github import GithubIntegration from github import Issue +from github import UnknownObjectException from jira import JIRA from mistletoe import Document # type: ignore[import] from mistletoe.contrib.jira_renderer import JIRARenderer # type: ignore[import] @@ -293,14 +294,42 @@ async def bot(request: Request, payload: dict = Body(...)): new_issue = jira.create_issue(fields=issue_dict) existing_issues.append(new_issue) + misconfigured_gh_label_reason = "" + + if settings["gh_synced_label_name"]: + gh_synced_label_name = settings["gh_synced_label_name"] + + if gh_synced_label_name: + try: + repo.get_label(gh_synced_label_name) + issue.add_to_labels(gh_synced_label_name) + except UnknownObjectException: + misconfigured_gh_label_reason = ( + " Warning: the specified GitHub label doesn't exist in the repo." + ) + else: + misconfigured_gh_label_reason = ( + " Warning: option gh_synced_label_name has not been set while" + "gh_synced_label_name has." + ) + if settings["add_gh_comment"]: - gh_issue.create_comment( - gh_comment_body_template.format(jira_issue_link=new_issue.permalink()) - ) + gh_comment_body = gh_comment_body_template.format(jira_issue_link=new_issue.permalink()) + + if misconfigured_gh_label_reason: + gh_comment_body += "\n\n" + misconfigured_gh_label_reason + + gh_issue.create_comment(gh_comment_body) # need this since we allow to sync issue on many actions. And if someone commented # we first create a Jira issue, then create a comment msg = "Issue was created in Jira. " + + if misconfigured_gh_label_reason: + msg += ( + "Comment added to GitHub issue because gh_synced_label_name " + "is not set, or does not exist in repo." + ) else: jira_issue = existing_issues[0] if payload["action"] == "closed": diff --git a/github_jira_sync_app/settings.yaml b/github_jira_sync_app/settings.yaml index 96d7129..863d678 100644 --- a/github_jira_sync_app/settings.yaml +++ b/github_jira_sync_app/settings.yaml @@ -2,6 +2,8 @@ settings: components: labels: add_gh_comment: false + add_gh_synced_label: false + gh_synced_label_name: sync_description: true sync_comments: true epic_key: diff --git a/tests/unit/dumm_env b/tests/unit/dumm_env index 0800721..9ba43a2 100644 --- a/tests/unit/dumm_env +++ b/tests/unit/dumm_env @@ -6,5 +6,5 @@ GITHUB_CLIENT_SECRET=rezindkm3dod04h12yt8oktm8if51wtsfgljk04k JIRA_INSTANCE="https://my-jira.atlassian.net" JIRA_USERNAME=maksim.beliaev@canonical.com JIRA_TOKEN=mv38swy07r6ius3v90cffyi4 -DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' +DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "add_gh_synced_label": false, "gh_synced_label_name": null, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' BOT_NAME="syncronize-issues-to-jira[bot]" \ No newline at end of file diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index 6de464a..a94e2e5 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -231,3 +231,68 @@ def test_issue_closed_as_not_planned(signature_mock): assert response.status_code == 200 assert response.json() == {"msg": "Closed existing Jira Issue as not planned"} + + +@responses.activate(assert_all_requests_are_fired=True) +def test_issue_created_and_sync_label_added(signature_mock): + """Test when a bug is created on GitHub with the right label and is set + + Tests the following scenario: + 1. Authenticate in GitHub + 2. Get issue from GitHub + 3. Get content of .jira_sync_config.yaml from GitHub repo + 4. Ensure that the issue on GitHub is label with the approved label + 5. Authenticate in Jira + 6. Validate via JQL that this issue does not exist in Jira + 7. Create new issue in Jira + 8. Validate that label exists in repo + 9. Add label to the issue + """ + responses._add_from_file( + UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label.yaml" + ) + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "issue_labeled_correct.yaml") + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_create_issue.yaml") + response = client.post( + "/", + json=_get_json("issue_created_with_label.json"), + ) + + assert response.status_code == 200 + assert response.json() == {"msg": "Issue was created in Jira. "} + + +@responses.activate(assert_all_requests_are_fired=True) +def test_issue_created_and_sync_label_not_present(signature_mock): + """Test when a bug is created on GitHub with the right label but does not + exist in the repository + + Tests the following scenario: + 1. Authenticate in GitHub + 2. Get issue from GitHub + 3. Get content of .jira_sync_config.yaml from GitHub repo + 4. Ensure that the issue on GitHub is label with the approved label + 5. Authenticate in Jira + 6. Validate via JQL that this issue does not exist in Jira + 7. Create new issue in Jira + 8. Try and validate that label exists in repo + 9. Label doesn't exist, nothing is done on the GitHub issue + """ + responses._add_from_file( + UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label_not_found.yaml" + ) + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "issue_labeled_correct.yaml") + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_create_issue.yaml") + response = client.post( + "/", + json=_get_json("issue_created_with_label.json"), + ) + + assert response.status_code == 200 + assert response.json() == { + "msg": "Issue was created in Jira. Comment added to GitHub issue " + "because gh_synced_label_name is not set, or does not exist" + " in repo." + } diff --git a/tests/unit/url_responses/auth_github_responses_sync_label.yaml b/tests/unit/url_responses/auth_github_responses_sync_label.yaml new file mode 100644 index 0000000..26af07b --- /dev/null +++ b/tests/unit/url_responses/auth_github_responses_sync_label.yaml @@ -0,0 +1,50 @@ +# this file is generated automatically via responses. Use _recorder.record() +responses: +- response: + auto_calculate_content_length: false + body: '{"id":35534068,"account":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"repository_selection":"selected","access_tokens_url":"https://api.github.com/app/installations/35534068/access_tokens","repositories_url":"https://api.github.com/installation/repositories","html_url":"https://github.com/settings/installations/35534068","app_id":308591,"app_slug":"syncronize-issues-to-jira","target_id":51964909,"target_type":"User","permissions":{"issues":"write","contents":"read","metadata":"read"},"events":["issues","issue_comment"],"created_at":"2023-03-22T14:24:41.000Z","updated_at":"2023-03-22T14:25:28.000Z","single_file_name":null,"has_multiple_single_files":false,"single_file_paths":[],"suspended_by":null,"suspended_at":null}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/installation +- response: + auto_calculate_content_length: false + body: '{"token":"ghs_XVo5Hjf","expires_at":"2023-07-05T12:56:03Z","permissions":{"contents":"read","issues":"write","metadata":"read"},"repository_selection":"selected"}' + content_type: text/plain + method: POST + status: 201 + url: https://api.github.com:443/app/installations/35534068/access_tokens +- response: + auto_calculate_content_length: false + body: '{"id":602008644,"node_id":"R_kgDOI-HsRA","name":"test-ci","full_name":"beliaev-maksim/test-ci","private":false,"owner":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"html_url":"https://github.com/beliaev-maksim/test-ci","description":null,"fork":false,"url":"https://api.github.com/repos/beliaev-maksim/test-ci","forks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/forks","keys_url":"https://api.github.com/repos/beliaev-maksim/test-ci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/beliaev-maksim/test-ci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/beliaev-maksim/test-ci/teams","hooks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/hooks","issue_events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/events{/number}","events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/events","assignees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/assignees{/user}","branches_url":"https://api.github.com/repos/beliaev-maksim/test-ci/branches{/branch}","tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/tags","blobs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/refs{/sha}","trees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/beliaev-maksim/test-ci/statuses/{sha}","languages_url":"https://api.github.com/repos/beliaev-maksim/test-ci/languages","stargazers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/stargazers","contributors_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contributors","subscribers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscribers","subscription_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscription","commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/commits{/sha}","git_commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/commits{/sha}","comments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/comments{/number}","issue_comment_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/comments{/number}","contents_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/{+path}","compare_url":"https://api.github.com/repos/beliaev-maksim/test-ci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/beliaev-maksim/test-ci/merges","archive_url":"https://api.github.com/repos/beliaev-maksim/test-ci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/beliaev-maksim/test-ci/downloads","issues_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues{/number}","pulls_url":"https://api.github.com/repos/beliaev-maksim/test-ci/pulls{/number}","milestones_url":"https://api.github.com/repos/beliaev-maksim/test-ci/milestones{/number}","notifications_url":"https://api.github.com/repos/beliaev-maksim/test-ci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/beliaev-maksim/test-ci/labels{/name}","releases_url":"https://api.github.com/repos/beliaev-maksim/test-ci/releases{/id}","deployments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/deployments","created_at":"2023-02-15T09:57:53Z","updated_at":"2023-05-15T09:25:41Z","pushed_at":"2023-05-15T09:29:16Z","git_url":"git://github.com/beliaev-maksim/test-ci.git","ssh_url":"git@github.com:beliaev-maksim/test-ci.git","clone_url":"https://github.com/beliaev-maksim/test-ci.git","svn_url":"https://github.com/beliaev-maksim/test-ci","homepage":null,"size":10,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":1,"watchers":0,"default_branch":"master","permissions":{"admin":false,"maintain":false,"push":false,"triage":false,"pull":false},"temp_clone_token":"","network_count":0,"subscribers_count":1}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci + +# get content of .jira_sync_config.yaml to load the settings for the repo +- response: + auto_calculate_content_length: false + body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgZ2hfc3luY2VkX2xhYmVsX25hbWU6IFN5bmNlZAogIHN5bmNfZGVzY3JpcHRpb246IHRydWUKICBzeW5jX2NvbW1lbnRzOiB0cnVlCiAgZXBpY19rZXk6ICJNVEMtMjk2IgogIGppcmFfcHJvamVjdF9rZXk6ICJNVEMiCiAgc3RhdHVzX21hcHBpbmc6CiAgICBvcGVuZWQ6IFVudHJpYWdlZAogICAgY2xvc2VkOiBkb25lIAogIGxhYmVsX21hcHBpbmc6CiAgICBlbmhhbmNlbWVudDogU3RvcnkK","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml + +# get the label from the repo +- response: + auto_calculate_content_length: false + body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced","name":"Synced","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced + +# add the label to the new issue +- response: + auto_calculate_content_length: false + body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced","name":"Synced","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' + content_type: text/plain + method: POST + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/labels \ No newline at end of file diff --git a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml new file mode 100644 index 0000000..2cec971 --- /dev/null +++ b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml @@ -0,0 +1,41 @@ +# this file is generated automatically via responses. Use _recorder.record() +responses: +- response: + auto_calculate_content_length: false + body: '{"id":35534068,"account":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"repository_selection":"selected","access_tokens_url":"https://api.github.com/app/installations/35534068/access_tokens","repositories_url":"https://api.github.com/installation/repositories","html_url":"https://github.com/settings/installations/35534068","app_id":308591,"app_slug":"syncronize-issues-to-jira","target_id":51964909,"target_type":"User","permissions":{"issues":"write","contents":"read","metadata":"read"},"events":["issues","issue_comment"],"created_at":"2023-03-22T14:24:41.000Z","updated_at":"2023-03-22T14:25:28.000Z","single_file_name":null,"has_multiple_single_files":false,"single_file_paths":[],"suspended_by":null,"suspended_at":null}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/installation +- response: + auto_calculate_content_length: false + body: '{"token":"ghs_XVo5Hjf","expires_at":"2023-07-05T12:56:03Z","permissions":{"contents":"read","issues":"write","metadata":"read"},"repository_selection":"selected"}' + content_type: text/plain + method: POST + status: 201 + url: https://api.github.com:443/app/installations/35534068/access_tokens +- response: + auto_calculate_content_length: false + body: '{"id":602008644,"node_id":"R_kgDOI-HsRA","name":"test-ci","full_name":"beliaev-maksim/test-ci","private":false,"owner":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"html_url":"https://github.com/beliaev-maksim/test-ci","description":null,"fork":false,"url":"https://api.github.com/repos/beliaev-maksim/test-ci","forks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/forks","keys_url":"https://api.github.com/repos/beliaev-maksim/test-ci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/beliaev-maksim/test-ci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/beliaev-maksim/test-ci/teams","hooks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/hooks","issue_events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/events{/number}","events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/events","assignees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/assignees{/user}","branches_url":"https://api.github.com/repos/beliaev-maksim/test-ci/branches{/branch}","tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/tags","blobs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/refs{/sha}","trees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/beliaev-maksim/test-ci/statuses/{sha}","languages_url":"https://api.github.com/repos/beliaev-maksim/test-ci/languages","stargazers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/stargazers","contributors_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contributors","subscribers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscribers","subscription_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscription","commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/commits{/sha}","git_commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/commits{/sha}","comments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/comments{/number}","issue_comment_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/comments{/number}","contents_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/{+path}","compare_url":"https://api.github.com/repos/beliaev-maksim/test-ci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/beliaev-maksim/test-ci/merges","archive_url":"https://api.github.com/repos/beliaev-maksim/test-ci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/beliaev-maksim/test-ci/downloads","issues_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues{/number}","pulls_url":"https://api.github.com/repos/beliaev-maksim/test-ci/pulls{/number}","milestones_url":"https://api.github.com/repos/beliaev-maksim/test-ci/milestones{/number}","notifications_url":"https://api.github.com/repos/beliaev-maksim/test-ci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/beliaev-maksim/test-ci/labels{/name}","releases_url":"https://api.github.com/repos/beliaev-maksim/test-ci/releases{/id}","deployments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/deployments","created_at":"2023-02-15T09:57:53Z","updated_at":"2023-05-15T09:25:41Z","pushed_at":"2023-05-15T09:29:16Z","git_url":"git://github.com/beliaev-maksim/test-ci.git","ssh_url":"git@github.com:beliaev-maksim/test-ci.git","clone_url":"https://github.com/beliaev-maksim/test-ci.git","svn_url":"https://github.com/beliaev-maksim/test-ci","homepage":null,"size":10,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":1,"watchers":0,"default_branch":"master","permissions":{"admin":false,"maintain":false,"push":false,"triage":false,"pull":false},"temp_clone_token":"","network_count":0,"subscribers_count":1}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci + +# get content of .jira_sync_config.yaml to load the settings for the repo +- response: + auto_calculate_content_length: false + body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgZ2hfc3luY2VkX2xhYmVsX25hbWU6IFN5bmNlZAogIHN5bmNfZGVzY3JpcHRpb246IHRydWUKICBzeW5jX2NvbW1lbnRzOiB0cnVlCiAgZXBpY19rZXk6ICJNVEMtMjk2IgogIGppcmFfcHJvamVjdF9rZXk6ICJNVEMiCiAgc3RhdHVzX21hcHBpbmc6CiAgICBvcGVuZWQ6IFVudHJpYWdlZAogICAgY2xvc2VkOiBkb25lIAogIGxhYmVsX21hcHBpbmc6CiAgICBlbmhhbmNlbWVudDogU3RvcnkK","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml + +# get the label from the repo +- response: + auto_calculate_content_length: false + body: '{"message": "Not Found", "documentation_url": "https://docs.github.com/rest/issues/labels#get-a-label", "status": "404"}' + content_type: text/plain + method: GET + status: 404 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced From aa8b6ff856bebc8c2b7082af70373f8673402d79 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Tue, 17 Dec 2024 16:52:36 +0200 Subject: [PATCH 2/7] Removed personalization of issue label name --- README.md | 14 ++----- github_jira_sync_app/main.py | 41 ++++++++----------- github_jira_sync_app/settings.yaml | 1 - tests/unit/dumm_env | 2 +- tests/unit/test_server.py | 15 ++++--- .../auth_github_responses_sync_label.yaml | 12 +++--- ...github_responses_sync_label_not_found.yaml | 6 +-- 7 files changed, 38 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index f99419e..f4067af 100644 --- a/README.md +++ b/README.md @@ -39,17 +39,11 @@ settings: # (Optional) (Default: false) Add a new comment in GitHub with a link to Jira created issue add_gh_comment: false - # (Optional) (Default: false) Add a label with name to newly created - # issues when a corresponding ticket is created in Jira. This is meant to replace the comment - # depending on project preferences, but comments will still be added if is true. + # (Optional) (Default: false) Add a 'synced-to-jira' label to newly created issues when a corresponding + # ticket is created in Jira. This is meant to replace the comment depending on project preferences, + # but comments will still be added if is true. + # The 'synced-to-jira' label must already be present in the GitHub repo and will not be created by the bot. add_gh_synced_label: false - - # (Optional) (Default: None) The name of the label to add to GitHub issues. Ignored if - # is false. A label with this name must already be present in the - # repository. If is true, misconfigurations such as the label not existing, or - # being unset when is true will be reported as a - # warning in the comment under the GitHub issue - gh_synced_label_name: None # (Optional) (Default: true) Synchronize issue description from GitHub to Jira sync_description: true diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 4b76455..ad66db6 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -51,6 +51,10 @@ > This message was autogenerated """ +gh_synced_label_name = "synced-to-jira" + +nonexistent_gh_label_warning = f"'{gh_synced_label_name}' label doesn't exist in the GitHub repo." + def define_logger(): """Define logger to output to the file and to STDOUT.""" @@ -294,30 +298,21 @@ async def bot(request: Request, payload: dict = Body(...)): new_issue = jira.create_issue(fields=issue_dict) existing_issues.append(new_issue) - misconfigured_gh_label_reason = "" - - if settings["gh_synced_label_name"]: - gh_synced_label_name = settings["gh_synced_label_name"] + synced_label_absent_in_repo = False - if gh_synced_label_name: - try: - repo.get_label(gh_synced_label_name) - issue.add_to_labels(gh_synced_label_name) - except UnknownObjectException: - misconfigured_gh_label_reason = ( - " Warning: the specified GitHub label doesn't exist in the repo." - ) - else: - misconfigured_gh_label_reason = ( - " Warning: option gh_synced_label_name has not been set while" - "gh_synced_label_name has." - ) + if settings["add_gh_synced_label"]: + try: + repo.get_label(gh_synced_label_name) + issue.add_to_labels(gh_synced_label_name) + except UnknownObjectException: + logger.warning(nonexistent_gh_label_warning) + synced_label_absent_in_repo = True if settings["add_gh_comment"]: gh_comment_body = gh_comment_body_template.format(jira_issue_link=new_issue.permalink()) - if misconfigured_gh_label_reason: - gh_comment_body += "\n\n" + misconfigured_gh_label_reason + if synced_label_absent_in_repo: + gh_comment_body += "\n\nWarning: " + nonexistent_gh_label_warning gh_issue.create_comment(gh_comment_body) @@ -325,11 +320,9 @@ async def bot(request: Request, payload: dict = Body(...)): # we first create a Jira issue, then create a comment msg = "Issue was created in Jira. " - if misconfigured_gh_label_reason: - msg += ( - "Comment added to GitHub issue because gh_synced_label_name " - "is not set, or does not exist in repo." - ) + # Add warning to response in case of label setting misconfiguration + if synced_label_absent_in_repo: + msg += "Warning: " + nonexistent_gh_label_warning else: jira_issue = existing_issues[0] if payload["action"] == "closed": diff --git a/github_jira_sync_app/settings.yaml b/github_jira_sync_app/settings.yaml index 863d678..37fb375 100644 --- a/github_jira_sync_app/settings.yaml +++ b/github_jira_sync_app/settings.yaml @@ -3,7 +3,6 @@ settings: labels: add_gh_comment: false add_gh_synced_label: false - gh_synced_label_name: sync_description: true sync_comments: true epic_key: diff --git a/tests/unit/dumm_env b/tests/unit/dumm_env index 9ba43a2..0086b7f 100644 --- a/tests/unit/dumm_env +++ b/tests/unit/dumm_env @@ -6,5 +6,5 @@ GITHUB_CLIENT_SECRET=rezindkm3dod04h12yt8oktm8if51wtsfgljk04k JIRA_INSTANCE="https://my-jira.atlassian.net" JIRA_USERNAME=maksim.beliaev@canonical.com JIRA_TOKEN=mv38swy07r6ius3v90cffyi4 -DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "add_gh_synced_label": false, "gh_synced_label_name": null, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' +DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "add_gh_synced_label": false, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' BOT_NAME="syncronize-issues-to-jira[bot]" \ No newline at end of file diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index a94e2e5..448309c 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -245,8 +245,8 @@ def test_issue_created_and_sync_label_added(signature_mock): 5. Authenticate in Jira 6. Validate via JQL that this issue does not exist in Jira 7. Create new issue in Jira - 8. Validate that label exists in repo - 9. Add label to the issue + 8. Validate that synced-to-jira label exists in repo + 9. Add synced-to-jira label to the issue """ responses._add_from_file( UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label.yaml" @@ -265,8 +265,8 @@ def test_issue_created_and_sync_label_added(signature_mock): @responses.activate(assert_all_requests_are_fired=True) def test_issue_created_and_sync_label_not_present(signature_mock): - """Test when a bug is created on GitHub with the right label but does not - exist in the repository + """Test when a bug is created on GitHub with the right label and is set + but the 'synced-to-jira' label does not exist in the repository Tests the following scenario: 1. Authenticate in GitHub @@ -276,7 +276,7 @@ def test_issue_created_and_sync_label_not_present(signature_mock): 5. Authenticate in Jira 6. Validate via JQL that this issue does not exist in Jira 7. Create new issue in Jira - 8. Try and validate that label exists in repo + 8. Try and validate that synced-to-jira label exists in repo 9. Label doesn't exist, nothing is done on the GitHub issue """ responses._add_from_file( @@ -292,7 +292,6 @@ def test_issue_created_and_sync_label_not_present(signature_mock): assert response.status_code == 200 assert response.json() == { - "msg": "Issue was created in Jira. Comment added to GitHub issue " - "because gh_synced_label_name is not set, or does not exist" - " in repo." + "msg": "Issue was created in Jira. " + "Warning: 'synced-to-jira' label doesn't exist in the GitHub repo." } diff --git a/tests/unit/url_responses/auth_github_responses_sync_label.yaml b/tests/unit/url_responses/auth_github_responses_sync_label.yaml index 26af07b..e1ac6df 100644 --- a/tests/unit/url_responses/auth_github_responses_sync_label.yaml +++ b/tests/unit/url_responses/auth_github_responses_sync_label.yaml @@ -25,25 +25,25 @@ responses: # get content of .jira_sync_config.yaml to load the settings for the repo - response: auto_calculate_content_length: false - body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgZ2hfc3luY2VkX2xhYmVsX25hbWU6IFN5bmNlZAogIHN5bmNfZGVzY3JpcHRpb246IHRydWUKICBzeW5jX2NvbW1lbnRzOiB0cnVlCiAgZXBpY19rZXk6ICJNVEMtMjk2IgogIGppcmFfcHJvamVjdF9rZXk6ICJNVEMiCiAgc3RhdHVzX21hcHBpbmc6CiAgICBvcGVuZWQ6IFVudHJpYWdlZAogICAgY2xvc2VkOiBkb25lIAogIGxhYmVsX21hcHBpbmc6CiAgICBlbmhhbmNlbWVudDogU3RvcnkK","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' + body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgc3luY19kZXNjcmlwdGlvbjogdHJ1ZQogIHN5bmNfY29tbWVudHM6IHRydWUKICBlcGljX2tleTogIk1UQy0yOTYiCiAgamlyYV9wcm9qZWN0X2tleTogIk1UQyIKICBzdGF0dXNfbWFwcGluZzoKICAgIG9wZW5lZDogVW50cmlhZ2VkCiAgICBjbG9zZWQ6IGRvbmUgCiAgbGFiZWxfbWFwcGluZzoKICAgIGVuaGFuY2VtZW50OiBTdG9yeQo=","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' content_type: text/plain method: GET status: 200 url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml -# get the label from the repo +# get the synced-to-jira label from the repo - response: auto_calculate_content_length: false - body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced","name":"Synced","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' + body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' content_type: text/plain method: GET status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira -# add the label to the new issue +# add the synced-to-jira label to the new issue - response: auto_calculate_content_length: false - body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced","name":"Synced","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' + body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' content_type: text/plain method: POST status: 200 diff --git a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml index 2cec971..9b5e5db 100644 --- a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml +++ b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml @@ -25,17 +25,17 @@ responses: # get content of .jira_sync_config.yaml to load the settings for the repo - response: auto_calculate_content_length: false - body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgZ2hfc3luY2VkX2xhYmVsX25hbWU6IFN5bmNlZAogIHN5bmNfZGVzY3JpcHRpb246IHRydWUKICBzeW5jX2NvbW1lbnRzOiB0cnVlCiAgZXBpY19rZXk6ICJNVEMtMjk2IgogIGppcmFfcHJvamVjdF9rZXk6ICJNVEMiCiAgc3RhdHVzX21hcHBpbmc6CiAgICBvcGVuZWQ6IFVudHJpYWdlZAogICAgY2xvc2VkOiBkb25lIAogIGxhYmVsX21hcHBpbmc6CiAgICBlbmhhbmNlbWVudDogU3RvcnkK","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' + body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgc3luY19kZXNjcmlwdGlvbjogdHJ1ZQogIHN5bmNfY29tbWVudHM6IHRydWUKICBlcGljX2tleTogIk1UQy0yOTYiCiAgamlyYV9wcm9qZWN0X2tleTogIk1UQyIKICBzdGF0dXNfbWFwcGluZzoKICAgIG9wZW5lZDogVW50cmlhZ2VkCiAgICBjbG9zZWQ6IGRvbmUgCiAgbGFiZWxfbWFwcGluZzoKICAgIGVuaGFuY2VtZW50OiBTdG9yeQo=","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' content_type: text/plain method: GET status: 200 url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml -# get the label from the repo +# get the (nonexistent) synced-to-jira label from the repo - response: auto_calculate_content_length: false body: '{"message": "Not Found", "documentation_url": "https://docs.github.com/rest/issues/labels#get-a-label", "status": "404"}' content_type: text/plain method: GET status: 404 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/Synced + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira From 766304a30a0bcb22810144b5bcbd5d066ca4ded3 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Tue, 17 Dec 2024 17:28:36 +0200 Subject: [PATCH 3/7] Warning comment always added in case of synced-with-jira label not existing --- README.md | 7 +++---- github_jira_sync_app/main.py | 2 +- tests/unit/test_server.py | 3 ++- .../auth_github_responses_sync_label_not_found.yaml | 10 ++++++++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f4067af..fd84593 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,9 @@ settings: # (Optional) (Default: false) Add a new comment in GitHub with a link to Jira created issue add_gh_comment: false - # (Optional) (Default: false) Add a 'synced-to-jira' label to newly created issues when a corresponding - # ticket is created in Jira. This is meant to replace the comment depending on project preferences, - # but comments will still be added if is true. - # The 'synced-to-jira' label must already be present in the GitHub repo and will not be created by the bot. + # (Optional) (Default: false) Add a 'synced-to-jira' label to newly created issues once a + # corresponding ticket is successfully created in Jira. + # This label serves as confirmation that the issue sync process was completed successfully. add_gh_synced_label: false # (Optional) (Default: true) Synchronize issue description from GitHub to Jira diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index ad66db6..26197ee 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -308,7 +308,7 @@ async def bot(request: Request, payload: dict = Body(...)): logger.warning(nonexistent_gh_label_warning) synced_label_absent_in_repo = True - if settings["add_gh_comment"]: + if settings["add_gh_comment"] or synced_label_absent_in_repo: gh_comment_body = gh_comment_body_template.format(jira_issue_link=new_issue.permalink()) if synced_label_absent_in_repo: diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index 448309c..b05fc90 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -277,7 +277,8 @@ def test_issue_created_and_sync_label_not_present(signature_mock): 6. Validate via JQL that this issue does not exist in Jira 7. Create new issue in Jira 8. Try and validate that synced-to-jira label exists in repo - 9. Label doesn't exist, nothing is done on the GitHub issue + 9. Label doesn't exist, warning comment is added to GitHub issue even though + is false """ responses._add_from_file( UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label_not_found.yaml" diff --git a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml index 9b5e5db..e171616 100644 --- a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml +++ b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml @@ -39,3 +39,13 @@ responses: method: GET status: 404 url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira + +# add comment to GitHub issue with warning about misconfiguration +- response: + auto_calculate_content_length: false + body: > + {"id":1,"node_id":"MDEyOklzc3VlQ29tbWVudDE=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/comments/12345","html_url":"https://github.com/beliaev-maksim/test-ci/issues/30#issuecomment-12345","body":"Thank you for reporting your feedback to us!\n\nThe internal ticket has been created:{jira_issue_link}.\n\n>This message was auto generated\n\nWarning: 'synced-to-jira' label doesn't exist in the GitHub repo.","user":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"created_at":"2011-04-14T16:00:49Z","updated_at":"2011-04-14T16:00:49Z","issue_url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30","author_association":"COLLABORATOR"} + content_type: text/plain + method: POST + status: 201 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/comments \ No newline at end of file From 9ca297abe385309f85aab196017d288c67676e31 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Wed, 18 Dec 2024 11:38:06 +0200 Subject: [PATCH 4/7] Adapt tests to new test structure --- ARCHITECTURE.md | 3 +- github_jira_sync_app/main.py | 2 +- tests/unit/test_server.py | 21 +++++--- .../auth_github_responses_sync_label.yaml | 50 ------------------ ...github_responses_sync_label_not_found.yaml | 51 ------------------- .../github_responses_synced_label_exists.yaml | 19 +++++++ ...ithub_responses_synced_label_notfound.yaml | 20 ++++++++ .../github_settings_with_gh_sync_label.yaml | 28 ++++++++++ 8 files changed, 85 insertions(+), 109 deletions(-) delete mode 100644 tests/unit/url_responses/auth_github_responses_sync_label.yaml delete mode 100644 tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml create mode 100644 tests/unit/url_responses/github_responses_synced_label_exists.yaml create mode 100644 tests/unit/url_responses/github_responses_synced_label_notfound.yaml create mode 100644 tests/unit/url_responses/github_settings_with_gh_sync_label.yaml diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 386a21c..0040bb3 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -15,6 +15,7 @@ sequenceDiagram App->>Jira: Searches for existing Jira issues Jira->>App: Provides list of existing issues if any App->>Jira: Creates/updates Jira issue + App->>repo: (Optional) Adds 'synced-to-jira' on the Issue App->>repo: (Optional) Adds a comment on the Issue App->>GH: Returns web response @@ -54,4 +55,4 @@ sequenceDiagram App1->>repo: (Optional) Adds a comment on the Issue App1->>GH: Returns web response -``` \ No newline at end of file +``` diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 26197ee..0299775 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -303,7 +303,7 @@ async def bot(request: Request, payload: dict = Body(...)): if settings["add_gh_synced_label"]: try: repo.get_label(gh_synced_label_name) - issue.add_to_labels(gh_synced_label_name) + gh_issue.add_to_labels(gh_synced_label_name) except UnknownObjectException: logger.warning(nonexistent_gh_label_warning) synced_label_absent_in_repo = True diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index b05fc90..cd07344 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -248,15 +248,20 @@ def test_issue_created_and_sync_label_added(signature_mock): 8. Validate that synced-to-jira label exists in repo 9. Add synced-to-jira label to the issue """ + + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "github_auth.yaml") + responses._add_from_file( + UNITTESTS_DIR / "url_responses" / "github_settings_with_gh_sync_label.yaml" + ) responses._add_from_file( - UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label.yaml" + UNITTESTS_DIR / "url_responses" / "github_responses_synced_label_exists.yaml" ) + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_jql_no_issues.yaml") responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "issue_labeled_correct.yaml") responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_create_issue.yaml") response = client.post( "/", - json=_get_json("issue_created_with_label.json"), + json=_get_json("issue_created_without_label.json"), ) assert response.status_code == 200 @@ -280,15 +285,19 @@ def test_issue_created_and_sync_label_not_present(signature_mock): 9. Label doesn't exist, warning comment is added to GitHub issue even though is false """ + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "github_auth.yaml") + responses._add_from_file( + UNITTESTS_DIR / "url_responses" / "github_settings_with_gh_sync_label.yaml" + ) responses._add_from_file( - UNITTESTS_DIR / "url_responses" / "auth_github_responses_sync_label_not_found.yaml" + UNITTESTS_DIR / "url_responses" / "github_responses_synced_label_notfound.yaml" ) + responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_jql_no_issues.yaml") responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "issue_labeled_correct.yaml") responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_create_issue.yaml") response = client.post( "/", - json=_get_json("issue_created_with_label.json"), + json=_get_json("issue_created_without_label.json"), ) assert response.status_code == 200 diff --git a/tests/unit/url_responses/auth_github_responses_sync_label.yaml b/tests/unit/url_responses/auth_github_responses_sync_label.yaml deleted file mode 100644 index e1ac6df..0000000 --- a/tests/unit/url_responses/auth_github_responses_sync_label.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# this file is generated automatically via responses. Use _recorder.record() -responses: -- response: - auto_calculate_content_length: false - body: '{"id":35534068,"account":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"repository_selection":"selected","access_tokens_url":"https://api.github.com/app/installations/35534068/access_tokens","repositories_url":"https://api.github.com/installation/repositories","html_url":"https://github.com/settings/installations/35534068","app_id":308591,"app_slug":"syncronize-issues-to-jira","target_id":51964909,"target_type":"User","permissions":{"issues":"write","contents":"read","metadata":"read"},"events":["issues","issue_comment"],"created_at":"2023-03-22T14:24:41.000Z","updated_at":"2023-03-22T14:25:28.000Z","single_file_name":null,"has_multiple_single_files":false,"single_file_paths":[],"suspended_by":null,"suspended_at":null}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/installation -- response: - auto_calculate_content_length: false - body: '{"token":"ghs_XVo5Hjf","expires_at":"2023-07-05T12:56:03Z","permissions":{"contents":"read","issues":"write","metadata":"read"},"repository_selection":"selected"}' - content_type: text/plain - method: POST - status: 201 - url: https://api.github.com:443/app/installations/35534068/access_tokens -- response: - auto_calculate_content_length: false - body: '{"id":602008644,"node_id":"R_kgDOI-HsRA","name":"test-ci","full_name":"beliaev-maksim/test-ci","private":false,"owner":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"html_url":"https://github.com/beliaev-maksim/test-ci","description":null,"fork":false,"url":"https://api.github.com/repos/beliaev-maksim/test-ci","forks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/forks","keys_url":"https://api.github.com/repos/beliaev-maksim/test-ci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/beliaev-maksim/test-ci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/beliaev-maksim/test-ci/teams","hooks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/hooks","issue_events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/events{/number}","events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/events","assignees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/assignees{/user}","branches_url":"https://api.github.com/repos/beliaev-maksim/test-ci/branches{/branch}","tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/tags","blobs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/refs{/sha}","trees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/beliaev-maksim/test-ci/statuses/{sha}","languages_url":"https://api.github.com/repos/beliaev-maksim/test-ci/languages","stargazers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/stargazers","contributors_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contributors","subscribers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscribers","subscription_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscription","commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/commits{/sha}","git_commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/commits{/sha}","comments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/comments{/number}","issue_comment_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/comments{/number}","contents_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/{+path}","compare_url":"https://api.github.com/repos/beliaev-maksim/test-ci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/beliaev-maksim/test-ci/merges","archive_url":"https://api.github.com/repos/beliaev-maksim/test-ci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/beliaev-maksim/test-ci/downloads","issues_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues{/number}","pulls_url":"https://api.github.com/repos/beliaev-maksim/test-ci/pulls{/number}","milestones_url":"https://api.github.com/repos/beliaev-maksim/test-ci/milestones{/number}","notifications_url":"https://api.github.com/repos/beliaev-maksim/test-ci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/beliaev-maksim/test-ci/labels{/name}","releases_url":"https://api.github.com/repos/beliaev-maksim/test-ci/releases{/id}","deployments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/deployments","created_at":"2023-02-15T09:57:53Z","updated_at":"2023-05-15T09:25:41Z","pushed_at":"2023-05-15T09:29:16Z","git_url":"git://github.com/beliaev-maksim/test-ci.git","ssh_url":"git@github.com:beliaev-maksim/test-ci.git","clone_url":"https://github.com/beliaev-maksim/test-ci.git","svn_url":"https://github.com/beliaev-maksim/test-ci","homepage":null,"size":10,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":1,"watchers":0,"default_branch":"master","permissions":{"admin":false,"maintain":false,"push":false,"triage":false,"pull":false},"temp_clone_token":"","network_count":0,"subscribers_count":1}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci - -# get content of .jira_sync_config.yaml to load the settings for the repo -- response: - auto_calculate_content_length: false - body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgc3luY19kZXNjcmlwdGlvbjogdHJ1ZQogIHN5bmNfY29tbWVudHM6IHRydWUKICBlcGljX2tleTogIk1UQy0yOTYiCiAgamlyYV9wcm9qZWN0X2tleTogIk1UQyIKICBzdGF0dXNfbWFwcGluZzoKICAgIG9wZW5lZDogVW50cmlhZ2VkCiAgICBjbG9zZWQ6IGRvbmUgCiAgbGFiZWxfbWFwcGluZzoKICAgIGVuaGFuY2VtZW50OiBTdG9yeQo=","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml - -# get the synced-to-jira label from the repo -- response: - auto_calculate_content_length: false - body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira - -# add the synced-to-jira label to the new issue -- response: - auto_calculate_content_length: false - body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' - content_type: text/plain - method: POST - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/labels \ No newline at end of file diff --git a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml b/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml deleted file mode 100644 index e171616..0000000 --- a/tests/unit/url_responses/auth_github_responses_sync_label_not_found.yaml +++ /dev/null @@ -1,51 +0,0 @@ -# this file is generated automatically via responses. Use _recorder.record() -responses: -- response: - auto_calculate_content_length: false - body: '{"id":35534068,"account":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"repository_selection":"selected","access_tokens_url":"https://api.github.com/app/installations/35534068/access_tokens","repositories_url":"https://api.github.com/installation/repositories","html_url":"https://github.com/settings/installations/35534068","app_id":308591,"app_slug":"syncronize-issues-to-jira","target_id":51964909,"target_type":"User","permissions":{"issues":"write","contents":"read","metadata":"read"},"events":["issues","issue_comment"],"created_at":"2023-03-22T14:24:41.000Z","updated_at":"2023-03-22T14:25:28.000Z","single_file_name":null,"has_multiple_single_files":false,"single_file_paths":[],"suspended_by":null,"suspended_at":null}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/installation -- response: - auto_calculate_content_length: false - body: '{"token":"ghs_XVo5Hjf","expires_at":"2023-07-05T12:56:03Z","permissions":{"contents":"read","issues":"write","metadata":"read"},"repository_selection":"selected"}' - content_type: text/plain - method: POST - status: 201 - url: https://api.github.com:443/app/installations/35534068/access_tokens -- response: - auto_calculate_content_length: false - body: '{"id":602008644,"node_id":"R_kgDOI-HsRA","name":"test-ci","full_name":"beliaev-maksim/test-ci","private":false,"owner":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"html_url":"https://github.com/beliaev-maksim/test-ci","description":null,"fork":false,"url":"https://api.github.com/repos/beliaev-maksim/test-ci","forks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/forks","keys_url":"https://api.github.com/repos/beliaev-maksim/test-ci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/beliaev-maksim/test-ci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/beliaev-maksim/test-ci/teams","hooks_url":"https://api.github.com/repos/beliaev-maksim/test-ci/hooks","issue_events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/events{/number}","events_url":"https://api.github.com/repos/beliaev-maksim/test-ci/events","assignees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/assignees{/user}","branches_url":"https://api.github.com/repos/beliaev-maksim/test-ci/branches{/branch}","tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/tags","blobs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/refs{/sha}","trees_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/beliaev-maksim/test-ci/statuses/{sha}","languages_url":"https://api.github.com/repos/beliaev-maksim/test-ci/languages","stargazers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/stargazers","contributors_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contributors","subscribers_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscribers","subscription_url":"https://api.github.com/repos/beliaev-maksim/test-ci/subscription","commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/commits{/sha}","git_commits_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/commits{/sha}","comments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/comments{/number}","issue_comment_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues/comments{/number}","contents_url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/{+path}","compare_url":"https://api.github.com/repos/beliaev-maksim/test-ci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/beliaev-maksim/test-ci/merges","archive_url":"https://api.github.com/repos/beliaev-maksim/test-ci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/beliaev-maksim/test-ci/downloads","issues_url":"https://api.github.com/repos/beliaev-maksim/test-ci/issues{/number}","pulls_url":"https://api.github.com/repos/beliaev-maksim/test-ci/pulls{/number}","milestones_url":"https://api.github.com/repos/beliaev-maksim/test-ci/milestones{/number}","notifications_url":"https://api.github.com/repos/beliaev-maksim/test-ci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/beliaev-maksim/test-ci/labels{/name}","releases_url":"https://api.github.com/repos/beliaev-maksim/test-ci/releases{/id}","deployments_url":"https://api.github.com/repos/beliaev-maksim/test-ci/deployments","created_at":"2023-02-15T09:57:53Z","updated_at":"2023-05-15T09:25:41Z","pushed_at":"2023-05-15T09:29:16Z","git_url":"git://github.com/beliaev-maksim/test-ci.git","ssh_url":"git@github.com:beliaev-maksim/test-ci.git","clone_url":"https://github.com/beliaev-maksim/test-ci.git","svn_url":"https://github.com/beliaev-maksim/test-ci","homepage":null,"size":10,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":1,"watchers":0,"default_branch":"master","permissions":{"admin":false,"maintain":false,"push":false,"triage":false,"pull":false},"temp_clone_token":"","network_count":0,"subscribers_count":1}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci - -# get content of .jira_sync_config.yaml to load the settings for the repo -- response: - auto_calculate_content_length: false - body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgICAtIGJ1ZwogICAgLSBjdXN0b20KICBhZGRfZ2hfY29tbWVudDogZmFsc2UKICBhZGRfZ2hfc3luY2VkX2xhYmVsOiB0cnVlCiAgc3luY19kZXNjcmlwdGlvbjogdHJ1ZQogIHN5bmNfY29tbWVudHM6IHRydWUKICBlcGljX2tleTogIk1UQy0yOTYiCiAgamlyYV9wcm9qZWN0X2tleTogIk1UQyIKICBzdGF0dXNfbWFwcGluZzoKICAgIG9wZW5lZDogVW50cmlhZ2VkCiAgICBjbG9zZWQ6IGRvbmUgCiAgbGFiZWxfbWFwcGluZzoKICAgIGVuaGFuY2VtZW50OiBTdG9yeQo=","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml - -# get the (nonexistent) synced-to-jira label from the repo -- response: - auto_calculate_content_length: false - body: '{"message": "Not Found", "documentation_url": "https://docs.github.com/rest/issues/labels#get-a-label", "status": "404"}' - content_type: text/plain - method: GET - status: 404 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira - -# add comment to GitHub issue with warning about misconfiguration -- response: - auto_calculate_content_length: false - body: > - {"id":1,"node_id":"MDEyOklzc3VlQ29tbWVudDE=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/comments/12345","html_url":"https://github.com/beliaev-maksim/test-ci/issues/30#issuecomment-12345","body":"Thank you for reporting your feedback to us!\n\nThe internal ticket has been created:{jira_issue_link}.\n\n>This message was auto generated\n\nWarning: 'synced-to-jira' label doesn't exist in the GitHub repo.","user":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"created_at":"2011-04-14T16:00:49Z","updated_at":"2011-04-14T16:00:49Z","issue_url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30","author_association":"COLLABORATOR"} - content_type: text/plain - method: POST - status: 201 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/comments \ No newline at end of file diff --git a/tests/unit/url_responses/github_responses_synced_label_exists.yaml b/tests/unit/url_responses/github_responses_synced_label_exists.yaml new file mode 100644 index 0000000..38e9d92 --- /dev/null +++ b/tests/unit/url_responses/github_responses_synced_label_exists.yaml @@ -0,0 +1,19 @@ +# this file is generated automatically via responses. Use _recorder.record() +responses: +# get the synced-to-jira label from the repo +- response: + auto_calculate_content_length: false + body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira + +# add the synced-to-jira label to the new issue +- response: + auto_calculate_content_length: false + body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' + content_type: text/plain + method: POST + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/labels \ No newline at end of file diff --git a/tests/unit/url_responses/github_responses_synced_label_notfound.yaml b/tests/unit/url_responses/github_responses_synced_label_notfound.yaml new file mode 100644 index 0000000..9d4c033 --- /dev/null +++ b/tests/unit/url_responses/github_responses_synced_label_notfound.yaml @@ -0,0 +1,20 @@ +# this file is generated automatically via responses. Use _recorder.record() +responses: +# get the (nonexistent) synced-to-jira label from the repo +- response: + auto_calculate_content_length: false + body: '{"message": "Not Found", "documentation_url": "https://docs.github.com/rest/issues/labels#get-a-label", "status": "404"}' + content_type: text/plain + method: GET + status: 404 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira + +# add comment to GitHub issue with warning about misconfiguration +- response: + auto_calculate_content_length: false + body: > + {"id":1,"node_id":"MDEyOklzc3VlQ29tbWVudDE=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/comments/12345","html_url":"https://github.com/beliaev-maksim/test-ci/issues/30#issuecomment-12345","body":"Thank you for reporting your feedback to us!\n\nThe internal ticket has been created:{jira_issue_link}.\n\n>This message was auto generated\n\nWarning: 'synced-to-jira' label doesn't exist in the GitHub repo.","user":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"created_at":"2011-04-14T16:00:49Z","updated_at":"2011-04-14T16:00:49Z","issue_url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30","author_association":"COLLABORATOR"} + content_type: text/plain + method: POST + status: 201 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/comments \ No newline at end of file diff --git a/tests/unit/url_responses/github_settings_with_gh_sync_label.yaml b/tests/unit/url_responses/github_settings_with_gh_sync_label.yaml new file mode 100644 index 0000000..114a2cb --- /dev/null +++ b/tests/unit/url_responses/github_settings_with_gh_sync_label.yaml @@ -0,0 +1,28 @@ +# get content of .jira_sync_config.yaml to load the settings for the repo +responses: +- response: + auto_calculate_content_length: false + body: '{"name":".jira_sync_config.yaml","path":".github/.jira_sync_config.yaml","sha":"a1a8aab6de92fc3eed4211350200ada4a2405b9c","size":297,"url":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","html_url":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml","git_url":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","download_url":"https://raw.githubusercontent.com/beliaev-maksim/test-ci/master/.github/.jira_sync_config.yaml","type":"file","content":"c2V0dGluZ3M6CiAgY29tcG9uZW50czoKICAgIC0gSW9UCiAgICAtIERBQ0ggVFQKICBsYWJlbHM6CiAgYWRkX2doX2NvbW1lbnQ6IGZhbHNlCiAgYWRkX2doX3N5bmNlZF9sYWJlbDogdHJ1ZQogIHN5bmNfZGVzY3JpcHRpb246IHRydWUKICBzeW5jX2NvbW1lbnRzOiB0cnVlCiAgZXBpY19rZXk6ICJNVEMtMjk2IgogIGppcmFfcHJvamVjdF9rZXk6ICJNVEMiCiAgc3RhdHVzX21hcHBpbmc6CiAgICBvcGVuZWQ6IFVudHJpYWdlZAogICAgY2xvc2VkOiBkb25lCiAgbGFiZWxfbWFwcGluZzoKICAgIGVuaGFuY2VtZW50OiBTdG9yeQo=","encoding":"base64","_links":{"self":"https://api.github.com/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml?ref=master","git":"https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs/a1a8aab6de92fc3eed4211350200ada4a2405b9c","html":"https://github.com/beliaev-maksim/test-ci/blob/master/.github/.jira_sync_config.yaml"}}' + content_type: text/plain + method: GET + status: 200 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/contents/.github/.jira_sync_config.yaml + + +# That is the base64 encoded content +#settings: +# components: +# - IoT +# - DACH TT +# labels: +# add_gh_comment: false +# add_gh_synced_label: true +# sync_description: true +# sync_comments: true +# epic_key: "MTC-296" +# jira_project_key: "MTC" +# status_mapping: +# opened: Untriaged +# closed: done +# label_mapping: +# enhancement: Story \ No newline at end of file From 37f399455a77a20f7a1f656f49231957edc4d921 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Wed, 18 Dec 2024 16:19:13 +0200 Subject: [PATCH 5/7] WIP: Removed extra API call and simplified tests --- github_jira_sync_app/main.py | 6 ++---- tests/unit/dumm_env | 2 +- .../github_responses_synced_label_exists.yaml | 9 --------- .../github_responses_synced_label_notfound.yaml | 12 ++++++------ 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 0299775..0c7c2f1 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -14,7 +14,6 @@ from github import GithubException from github import GithubIntegration from github import Issue -from github import UnknownObjectException from jira import JIRA from mistletoe import Document # type: ignore[import] from mistletoe.contrib.jira_renderer import JIRARenderer # type: ignore[import] @@ -300,11 +299,10 @@ async def bot(request: Request, payload: dict = Body(...)): synced_label_absent_in_repo = False - if settings["add_gh_synced_label"]: + if settings.get("add_gh_synced_label", False): try: - repo.get_label(gh_synced_label_name) gh_issue.add_to_labels(gh_synced_label_name) - except UnknownObjectException: + except GithubException: logger.warning(nonexistent_gh_label_warning) synced_label_absent_in_repo = True diff --git a/tests/unit/dumm_env b/tests/unit/dumm_env index 0086b7f..0800721 100644 --- a/tests/unit/dumm_env +++ b/tests/unit/dumm_env @@ -6,5 +6,5 @@ GITHUB_CLIENT_SECRET=rezindkm3dod04h12yt8oktm8if51wtsfgljk04k JIRA_INSTANCE="https://my-jira.atlassian.net" JIRA_USERNAME=maksim.beliaev@canonical.com JIRA_TOKEN=mv38swy07r6ius3v90cffyi4 -DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "add_gh_synced_label": false, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' +DEFAULT_BOT_CONFIG='{"settings": {"components": null, "labels": ["jira"], "add_gh_comment": false, "sync_description": true, "sync_comments": true, "epic_key": null, "jira_project_key": null, "label_mapping": null, "status_mapping": null}}' BOT_NAME="syncronize-issues-to-jira[bot]" \ No newline at end of file diff --git a/tests/unit/url_responses/github_responses_synced_label_exists.yaml b/tests/unit/url_responses/github_responses_synced_label_exists.yaml index 38e9d92..b2384d0 100644 --- a/tests/unit/url_responses/github_responses_synced_label_exists.yaml +++ b/tests/unit/url_responses/github_responses_synced_label_exists.yaml @@ -1,14 +1,5 @@ # this file is generated automatically via responses. Use _recorder.record() responses: -# get the synced-to-jira label from the repo -- response: - auto_calculate_content_length: false - body: '{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}' - content_type: text/plain - method: GET - status: 200 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira - # add the synced-to-jira label to the new issue - response: auto_calculate_content_length: false diff --git a/tests/unit/url_responses/github_responses_synced_label_notfound.yaml b/tests/unit/url_responses/github_responses_synced_label_notfound.yaml index 9d4c033..c099b68 100644 --- a/tests/unit/url_responses/github_responses_synced_label_notfound.yaml +++ b/tests/unit/url_responses/github_responses_synced_label_notfound.yaml @@ -1,14 +1,14 @@ # this file is generated automatically via responses. Use _recorder.record() responses: -# get the (nonexistent) synced-to-jira label from the repo - response: auto_calculate_content_length: false - body: '{"message": "Not Found", "documentation_url": "https://docs.github.com/rest/issues/labels#get-a-label", "status": "404"}' + # this body is not accurate and requires capturing a real call + body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' content_type: text/plain - method: GET - status: 404 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira - + method: POST + # this error code is provisional + status: 422 + url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/labels # add comment to GitHub issue with warning about misconfiguration - response: auto_calculate_content_length: false From a83b43324f35f205246fc2f42e9d5bf3fded0f6b Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Thu, 19 Dec 2024 17:25:27 +0200 Subject: [PATCH 6/7] Add synced-to-jira without checking its existence in repo --- github_jira_sync_app/main.py | 19 +------- tests/unit/test_server.py | 47 ++----------------- ...=> github_responses_add_synced_label.yaml} | 0 ...ithub_responses_synced_label_notfound.yaml | 20 -------- 4 files changed, 6 insertions(+), 80 deletions(-) rename tests/unit/url_responses/{github_responses_synced_label_exists.yaml => github_responses_add_synced_label.yaml} (100%) delete mode 100644 tests/unit/url_responses/github_responses_synced_label_notfound.yaml diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 0c7c2f1..3817742 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -52,8 +52,6 @@ gh_synced_label_name = "synced-to-jira" -nonexistent_gh_label_warning = f"'{gh_synced_label_name}' label doesn't exist in the GitHub repo." - def define_logger(): """Define logger to output to the file and to STDOUT.""" @@ -297,30 +295,17 @@ async def bot(request: Request, payload: dict = Body(...)): new_issue = jira.create_issue(fields=issue_dict) existing_issues.append(new_issue) - synced_label_absent_in_repo = False - if settings.get("add_gh_synced_label", False): - try: - gh_issue.add_to_labels(gh_synced_label_name) - except GithubException: - logger.warning(nonexistent_gh_label_warning) - synced_label_absent_in_repo = True + gh_issue.add_to_labels(gh_synced_label_name) - if settings["add_gh_comment"] or synced_label_absent_in_repo: + if settings["add_gh_comment"]: gh_comment_body = gh_comment_body_template.format(jira_issue_link=new_issue.permalink()) - if synced_label_absent_in_repo: - gh_comment_body += "\n\nWarning: " + nonexistent_gh_label_warning - gh_issue.create_comment(gh_comment_body) # need this since we allow to sync issue on many actions. And if someone commented # we first create a Jira issue, then create a comment msg = "Issue was created in Jira. " - - # Add warning to response in case of label setting misconfiguration - if synced_label_absent_in_repo: - msg += "Warning: " + nonexistent_gh_label_warning else: jira_issue = existing_issues[0] if payload["action"] == "closed": diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index cd07344..aa6b584 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -234,7 +234,7 @@ def test_issue_closed_as_not_planned(signature_mock): @responses.activate(assert_all_requests_are_fired=True) -def test_issue_created_and_sync_label_added(signature_mock): +def test_issue_created_and_synced_label(signature_mock): """Test when a bug is created on GitHub with the right label and is set Tests the following scenario: @@ -245,8 +245,8 @@ def test_issue_created_and_sync_label_added(signature_mock): 5. Authenticate in Jira 6. Validate via JQL that this issue does not exist in Jira 7. Create new issue in Jira - 8. Validate that synced-to-jira label exists in repo - 9. Add synced-to-jira label to the issue + 8. Add synced-to-jira label to the issue. If it doesn't exist it is created + automatically by GitHub and then added """ responses._add_from_file(UNITTESTS_DIR / "url_responses" / "github_auth.yaml") @@ -254,7 +254,7 @@ def test_issue_created_and_sync_label_added(signature_mock): UNITTESTS_DIR / "url_responses" / "github_settings_with_gh_sync_label.yaml" ) responses._add_from_file( - UNITTESTS_DIR / "url_responses" / "github_responses_synced_label_exists.yaml" + UNITTESTS_DIR / "url_responses" / "github_responses_add_synced_label.yaml" ) responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_jql_no_issues.yaml") responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") @@ -266,42 +266,3 @@ def test_issue_created_and_sync_label_added(signature_mock): assert response.status_code == 200 assert response.json() == {"msg": "Issue was created in Jira. "} - - -@responses.activate(assert_all_requests_are_fired=True) -def test_issue_created_and_sync_label_not_present(signature_mock): - """Test when a bug is created on GitHub with the right label and is set - but the 'synced-to-jira' label does not exist in the repository - - Tests the following scenario: - 1. Authenticate in GitHub - 2. Get issue from GitHub - 3. Get content of .jira_sync_config.yaml from GitHub repo - 4. Ensure that the issue on GitHub is label with the approved label - 5. Authenticate in Jira - 6. Validate via JQL that this issue does not exist in Jira - 7. Create new issue in Jira - 8. Try and validate that synced-to-jira label exists in repo - 9. Label doesn't exist, warning comment is added to GitHub issue even though - is false - """ - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "github_auth.yaml") - responses._add_from_file( - UNITTESTS_DIR / "url_responses" / "github_settings_with_gh_sync_label.yaml" - ) - responses._add_from_file( - UNITTESTS_DIR / "url_responses" / "github_responses_synced_label_notfound.yaml" - ) - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_jql_no_issues.yaml") - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_auth_responses.yaml") - responses._add_from_file(UNITTESTS_DIR / "url_responses" / "jira_create_issue.yaml") - response = client.post( - "/", - json=_get_json("issue_created_without_label.json"), - ) - - assert response.status_code == 200 - assert response.json() == { - "msg": "Issue was created in Jira. " - "Warning: 'synced-to-jira' label doesn't exist in the GitHub repo." - } diff --git a/tests/unit/url_responses/github_responses_synced_label_exists.yaml b/tests/unit/url_responses/github_responses_add_synced_label.yaml similarity index 100% rename from tests/unit/url_responses/github_responses_synced_label_exists.yaml rename to tests/unit/url_responses/github_responses_add_synced_label.yaml diff --git a/tests/unit/url_responses/github_responses_synced_label_notfound.yaml b/tests/unit/url_responses/github_responses_synced_label_notfound.yaml deleted file mode 100644 index c099b68..0000000 --- a/tests/unit/url_responses/github_responses_synced_label_notfound.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# this file is generated automatically via responses. Use _recorder.record() -responses: -- response: - auto_calculate_content_length: false - # this body is not accurate and requires capturing a real call - body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' - content_type: text/plain - method: POST - # this error code is provisional - status: 422 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/labels -# add comment to GitHub issue with warning about misconfiguration -- response: - auto_calculate_content_length: false - body: > - {"id":1,"node_id":"MDEyOklzc3VlQ29tbWVudDE=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/comments/12345","html_url":"https://github.com/beliaev-maksim/test-ci/issues/30#issuecomment-12345","body":"Thank you for reporting your feedback to us!\n\nThe internal ticket has been created:{jira_issue_link}.\n\n>This message was auto generated\n\nWarning: 'synced-to-jira' label doesn't exist in the GitHub repo.","user":{"login":"beliaev-maksim","id":51964909,"node_id":"MDQ6VXNlcjUxOTY0OTA5","avatar_url":"https://avatars.githubusercontent.com/u/51964909?v=4","gravatar_id":"","url":"https://api.github.com/users/beliaev-maksim","html_url":"https://github.com/beliaev-maksim","followers_url":"https://api.github.com/users/beliaev-maksim/followers","following_url":"https://api.github.com/users/beliaev-maksim/following{/other_user}","gists_url":"https://api.github.com/users/beliaev-maksim/gists{/gist_id}","starred_url":"https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beliaev-maksim/subscriptions","organizations_url":"https://api.github.com/users/beliaev-maksim/orgs","repos_url":"https://api.github.com/users/beliaev-maksim/repos","events_url":"https://api.github.com/users/beliaev-maksim/events{/privacy}","received_events_url":"https://api.github.com/users/beliaev-maksim/received_events","type":"User","site_admin":false},"created_at":"2011-04-14T16:00:49Z","updated_at":"2011-04-14T16:00:49Z","issue_url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30","author_association":"COLLABORATOR"} - content_type: text/plain - method: POST - status: 201 - url: https://api.github.com:443/repos/beliaev-maksim/test-ci/issues/30/comments \ No newline at end of file From 22ad5e05a58abe9af3b6d91ef4efc8fba7760820 Mon Sep 17 00:00:00 2001 From: Lorenzo Medici Date: Thu, 19 Dec 2024 17:42:53 +0200 Subject: [PATCH 7/7] Actions from labeling issues with synced-to-jira are ignored --- github_jira_sync_app/main.py | 9 + .../issue_labeled_synced_to_jira.json | 210 ++++++++++++++++++ tests/unit/test_server.py | 12 + .../github_responses_add_synced_label.yaml | 2 +- 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 tests/unit/payloads/issue_labeled_synced_to_jira.json diff --git a/github_jira_sync_app/main.py b/github_jira_sync_app/main.py index 3817742..a6f8ff5 100644 --- a/github_jira_sync_app/main.py +++ b/github_jira_sync_app/main.py @@ -189,6 +189,15 @@ async def bot(request: Request, payload: dict = Body(...)): ) } + if payload["action"] == "labeled": + if payload["label"]["name"] == gh_synced_label_name: + return { + "msg": ( + f"Action was triggered by Issue being labeled with {gh_synced_label_name}." + " Purposefully ignored as caused by this bot." + ) + } + owner = payload["repository"]["owner"]["login"] repo_name = payload["repository"]["name"] diff --git a/tests/unit/payloads/issue_labeled_synced_to_jira.json b/tests/unit/payloads/issue_labeled_synced_to_jira.json new file mode 100644 index 0000000..c9f1fe1 --- /dev/null +++ b/tests/unit/payloads/issue_labeled_synced_to_jira.json @@ -0,0 +1,210 @@ +{ + "action": "labeled", + "issue": { + "url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30", + "repository_url": "https://api.github.com/repos/beliaev-maksim/test-ci", + "labels_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30/labels{/name}", + "comments_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30/comments", + "events_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30/events", + "html_url": "https://github.com/beliaev-maksim/test-ci/issues/30", + "id": 1745060534, + "node_id": "I_kwDOI-HsRM5oA4K2", + "number": 30, + "title": "day after", + "user": { + "login": "beliaev-maksim", + "id": 51964909, + "node_id": "MDQ6VXNlcjUxOTY0OTA5", + "avatar_url": "https://avatars.githubusercontent.com/u/51964909?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/beliaev-maksim", + "html_url": "https://github.com/beliaev-maksim", + "followers_url": "https://api.github.com/users/beliaev-maksim/followers", + "following_url": "https://api.github.com/users/beliaev-maksim/following{/other_user}", + "gists_url": "https://api.github.com/users/beliaev-maksim/gists{/gist_id}", + "starred_url": "https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/beliaev-maksim/subscriptions", + "organizations_url": "https://api.github.com/users/beliaev-maksim/orgs", + "repos_url": "https://api.github.com/users/beliaev-maksim/repos", + "events_url": "https://api.github.com/users/beliaev-maksim/events{/privacy}", + "received_events_url": "https://api.github.com/users/beliaev-maksim/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 5157325446, + "node_id": "LA_kwDOI-HsRM8AAAABM2aKhg", + "url": "https://api.github.com/repos/beliaev-maksim/test-ci/labels/bug", + "name": "bug", + "color": "d73a4a", + "default": true, + "description": "Something isn't working" + } + ], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [ + + ], + "milestone": null, + "comments": 0, + "created_at": "2023-06-07T05:19:14Z", + "updated_at": "2023-06-07T05:19:14Z", + "closed_at": null, + "author_association": "OWNER", + "active_lock_reason": null, + "body": null, + "reactions": { + "url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/30/timeline", + "performed_via_github_app": null, + "state_reason": null + }, + "label": { + "id": 5157325446, + "node_id": "LA_kwDOI-HsRM8AAAABM2aKhg", + "url": "https://api.github.com/repos/beliaev-maksim/test-ci/labels/synced-to-jira", + "name": "synced-to-jira", + "color": "d73a4a", + "default": false, + "description": "Ticket in Jira has been created for this issue" + }, + "repository": { + "id": 602008644, + "node_id": "R_kgDOI-HsRA", + "name": "test-ci", + "full_name": "beliaev-maksim/test-ci", + "private": false, + "owner": { + "login": "beliaev-maksim", + "id": 51964909, + "node_id": "MDQ6VXNlcjUxOTY0OTA5", + "avatar_url": "https://avatars.githubusercontent.com/u/51964909?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/beliaev-maksim", + "html_url": "https://github.com/beliaev-maksim", + "followers_url": "https://api.github.com/users/beliaev-maksim/followers", + "following_url": "https://api.github.com/users/beliaev-maksim/following{/other_user}", + "gists_url": "https://api.github.com/users/beliaev-maksim/gists{/gist_id}", + "starred_url": "https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/beliaev-maksim/subscriptions", + "organizations_url": "https://api.github.com/users/beliaev-maksim/orgs", + "repos_url": "https://api.github.com/users/beliaev-maksim/repos", + "events_url": "https://api.github.com/users/beliaev-maksim/events{/privacy}", + "received_events_url": "https://api.github.com/users/beliaev-maksim/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/beliaev-maksim/test-ci", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/beliaev-maksim/test-ci", + "forks_url": "https://api.github.com/repos/beliaev-maksim/test-ci/forks", + "keys_url": "https://api.github.com/repos/beliaev-maksim/test-ci/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/beliaev-maksim/test-ci/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/beliaev-maksim/test-ci/teams", + "hooks_url": "https://api.github.com/repos/beliaev-maksim/test-ci/hooks", + "issue_events_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/events{/number}", + "events_url": "https://api.github.com/repos/beliaev-maksim/test-ci/events", + "assignees_url": "https://api.github.com/repos/beliaev-maksim/test-ci/assignees{/user}", + "branches_url": "https://api.github.com/repos/beliaev-maksim/test-ci/branches{/branch}", + "tags_url": "https://api.github.com/repos/beliaev-maksim/test-ci/tags", + "blobs_url": "https://api.github.com/repos/beliaev-maksim/test-ci/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/beliaev-maksim/test-ci/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/beliaev-maksim/test-ci/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/beliaev-maksim/test-ci/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/beliaev-maksim/test-ci/statuses/{sha}", + "languages_url": "https://api.github.com/repos/beliaev-maksim/test-ci/languages", + "stargazers_url": "https://api.github.com/repos/beliaev-maksim/test-ci/stargazers", + "contributors_url": "https://api.github.com/repos/beliaev-maksim/test-ci/contributors", + "subscribers_url": "https://api.github.com/repos/beliaev-maksim/test-ci/subscribers", + "subscription_url": "https://api.github.com/repos/beliaev-maksim/test-ci/subscription", + "commits_url": "https://api.github.com/repos/beliaev-maksim/test-ci/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/beliaev-maksim/test-ci/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/beliaev-maksim/test-ci/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/beliaev-maksim/test-ci/contents/{+path}", + "compare_url": "https://api.github.com/repos/beliaev-maksim/test-ci/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/beliaev-maksim/test-ci/merges", + "archive_url": "https://api.github.com/repos/beliaev-maksim/test-ci/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/beliaev-maksim/test-ci/downloads", + "issues_url": "https://api.github.com/repos/beliaev-maksim/test-ci/issues{/number}", + "pulls_url": "https://api.github.com/repos/beliaev-maksim/test-ci/pulls{/number}", + "milestones_url": "https://api.github.com/repos/beliaev-maksim/test-ci/milestones{/number}", + "notifications_url": "https://api.github.com/repos/beliaev-maksim/test-ci/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/beliaev-maksim/test-ci/labels{/name}", + "releases_url": "https://api.github.com/repos/beliaev-maksim/test-ci/releases{/id}", + "deployments_url": "https://api.github.com/repos/beliaev-maksim/test-ci/deployments", + "created_at": "2023-02-15T09:57:53Z", + "updated_at": "2023-05-15T09:25:41Z", + "pushed_at": "2023-05-15T09:29:16Z", + "git_url": "git://github.com/beliaev-maksim/test-ci.git", + "ssh_url": "git@github.com:beliaev-maksim/test-ci.git", + "clone_url": "https://github.com/beliaev-maksim/test-ci.git", + "svn_url": "https://github.com/beliaev-maksim/test-ci", + "homepage": null, + "size": 10, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Python", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "visibility": "public", + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "beliaev-maksim", + "id": 51964909, + "node_id": "MDQ6VXNlcjUxOTY0OTA5", + "avatar_url": "https://avatars.githubusercontent.com/u/51964909?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/beliaev-maksim", + "html_url": "https://github.com/beliaev-maksim", + "followers_url": "https://api.github.com/users/beliaev-maksim/followers", + "following_url": "https://api.github.com/users/beliaev-maksim/following{/other_user}", + "gists_url": "https://api.github.com/users/beliaev-maksim/gists{/gist_id}", + "starred_url": "https://api.github.com/users/beliaev-maksim/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/beliaev-maksim/subscriptions", + "organizations_url": "https://api.github.com/users/beliaev-maksim/orgs", + "repos_url": "https://api.github.com/users/beliaev-maksim/repos", + "events_url": "https://api.github.com/users/beliaev-maksim/events{/privacy}", + "received_events_url": "https://api.github.com/users/beliaev-maksim/received_events", + "type": "User", + "site_admin": false + }, + "installation": { + "id": 35534068, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzU1MzQwNjg=" + } +} diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index aa6b584..cac61ba 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -247,6 +247,8 @@ def test_issue_created_and_synced_label(signature_mock): 7. Create new issue in Jira 8. Add synced-to-jira label to the issue. If it doesn't exist it is created automatically by GitHub and then added + 9. The new webhook sent by GitHub for labeling the Issue with synced-to-jira + is immediately ignored """ responses._add_from_file(UNITTESTS_DIR / "url_responses" / "github_auth.yaml") @@ -266,3 +268,13 @@ def test_issue_created_and_synced_label(signature_mock): assert response.status_code == 200 assert response.json() == {"msg": "Issue was created in Jira. "} + + response = client.post("/", json=_get_json("issue_labeled_synced_to_jira.json")) + + assert response.status_code == 200 + assert response.json() == { + "msg": ( + "Action was triggered by Issue being labeled with synced-to-jira. " + "Purposefully ignored as caused by this bot." + ) + } diff --git a/tests/unit/url_responses/github_responses_add_synced_label.yaml b/tests/unit/url_responses/github_responses_add_synced_label.yaml index b2384d0..7d8e4e0 100644 --- a/tests/unit/url_responses/github_responses_add_synced_label.yaml +++ b/tests/unit/url_responses/github_responses_add_synced_label.yaml @@ -3,7 +3,7 @@ responses: # add the synced-to-jira label to the new issue - response: auto_calculate_content_length: false - body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"TicketinJirahasbeencreatedforthisissue","color":"f29513","default":false}]' + body: '[{"id":208045946,"node_id":"MDU6TGFiZWwyMDgwNDU5NDY=","url":"https://api.github.com:443/repos/beliaev-maksim/test-ci/labels/synced-to-jira","name":"synced-to-jira","description":"Ticket in Jira has been created for this issue","color":"f29513","default":false}]' content_type: text/plain method: POST status: 200