From 092d254151c1bdba321ac9e9cf63059d598228f2 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 20 Mar 2024 19:42:28 +0100 Subject: [PATCH] Be a lot more flexible as for GHMemberChanges values Unfortunately, things are not consistent between added and edited. added provide a permission of some sort and a role name (sometimes...) edited only provides permission and it's not exactly the same ones For now, I think we need to return strings to avoid issues until GitHub adjusts the API. --- .../org/kohsuke/github/GHMemberChanges.java | 60 ++++++- .../org/kohsuke/github/BridgeMethodTest.java | 9 + .../kohsuke/github/GHEventPayloadTest.java | 33 +++- .../member_added_role_name.json | 169 ++++++++++++++++++ 4 files changed, 261 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/member_added_role_name.json diff --git a/src/main/java/org/kohsuke/github/GHMemberChanges.java b/src/main/java/org/kohsuke/github/GHMemberChanges.java index 9f0e5d572f..6de93c5dc4 100644 --- a/src/main/java/org/kohsuke/github/GHMemberChanges.java +++ b/src/main/java/org/kohsuke/github/GHMemberChanges.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.kohsuke.github.internal.EnumUtils; @@ -11,6 +12,8 @@ public class GHMemberChanges { private FromToPermission permission; + private FromRoleName roleName; + /** * Get changes to permission. * @@ -20,6 +23,18 @@ public FromToPermission getPermission() { return permission; } + /** + * Get changes to the role name. + *

+ * Apparently, it is recommended to use this rather than permission if defined. But it will only be defined when + * adding and not when editing. + * + * @return changes to role name + */ + public FromRoleName getRoleName() { + return roleName; + } + /** * Changes to permission. */ @@ -34,9 +49,9 @@ public static class FromToPermission { * * @return the from */ - public GHOrganization.Permission getFrom() { - return EnumUtils - .getNullableEnumOrDefault(GHOrganization.Permission.class, from, GHOrganization.Permission.UNKNOWN); + @WithBridgeMethods(value = GHOrganization.Permission.class, adapterMethod = "stringToOrgPermission") + public String getFrom() { + return from; } /** @@ -44,9 +59,42 @@ public GHOrganization.Permission getFrom() { * * @return the to */ - public GHOrganization.Permission getTo() { - return EnumUtils - .getNullableEnumOrDefault(GHOrganization.Permission.class, to, GHOrganization.Permission.UNKNOWN); + @WithBridgeMethods(value = GHOrganization.Permission.class, adapterMethod = "stringToOrgPermission") + public String getTo() { + return to; + } + + @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getFrom and getTo") + private Object stringToOrgPermission(String permissionType, Class type) { + switch (permissionType) { + case "admin" : + return GHOrganization.Permission.ADMIN; + case "none" : + return GHOrganization.Permission.UNKNOWN; + case "read" : + return GHOrganization.Permission.PULL; + case "write" : + return GHOrganization.Permission.PUSH; + default : + return EnumUtils.getNullableEnumOrDefault(GHPermissionType.class, to, GHPermissionType.UNKNOWN); + } + } + } + + /** + * Changes to role name. + */ + public static class FromRoleName { + + private String to; + + /** + * Gets the to. + * + * @return the to + */ + public String getTo() { + return to; } } } diff --git a/src/test/java/org/kohsuke/github/BridgeMethodTest.java b/src/test/java/org/kohsuke/github/BridgeMethodTest.java index eb9138eda4..f30aea7f8f 100644 --- a/src/test/java/org/kohsuke/github/BridgeMethodTest.java +++ b/src/test/java/org/kohsuke/github/BridgeMethodTest.java @@ -60,6 +60,15 @@ public void testBridgeMethods() throws IOException { verifyBridgeMethods(GHTeam.class, "getId", int.class, long.class, String.class); + verifyBridgeMethods(GHMemberChanges.FromToPermission.class, + "getTo", + String.class, + GHOrganization.Permission.class); + verifyBridgeMethods(GHMemberChanges.FromToPermission.class, + "getFrom", + String.class, + GHOrganization.Permission.class); + // verifyBridgeMethods(GitHub.class, "getMyself", GHMyself.class, GHUser.class); } diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 937e6d8e01..c346d368d5 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -4,7 +4,6 @@ import org.junit.Test; import org.kohsuke.github.GHCheckRun.Conclusion; import org.kohsuke.github.GHCheckRun.Status; -import org.kohsuke.github.GHOrganization.Permission; import org.kohsuke.github.GHProjectsV2Item.ContentType; import org.kohsuke.github.GHProjectsV2ItemChanges.FieldType; import org.kohsuke.github.GHTeam.Privacy; @@ -1715,8 +1714,8 @@ public void member_edited() throws Exception { assertThat(member.getLogin(), is("yrodiere")); GHMemberChanges changes = memberPayload.getChanges(); - assertThat(changes.getPermission().getFrom(), is(Permission.ADMIN)); - assertThat(changes.getPermission().getTo(), is(Permission.TRIAGE)); + assertThat(changes.getPermission().getFrom(), is("admin")); + assertThat(changes.getPermission().getTo(), is("triage")); } /** @@ -1741,7 +1740,33 @@ public void member_added() throws Exception { GHMemberChanges changes = memberPayload.getChanges(); assertThat(changes.getPermission().getFrom(), is(nullValue())); - assertThat(changes.getPermission().getTo(), is(Permission.ADMIN)); + assertThat(changes.getPermission().getTo(), is("admin")); + } + + /** + * Member added with role name defined. + * + * @throws Exception + * the exception + */ + @Test + public void member_added_role_name() throws Exception { + final GHEventPayload.Member memberPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); + + assertThat(memberPayload.getAction(), is("added")); + + assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); + + GHUser member = memberPayload.getMember(); + assertThat(member.getId(), is(412878L)); + assertThat(member.getLogin(), is("yrodiere")); + + GHMemberChanges changes = memberPayload.getChanges(); + assertThat(changes.getPermission().getFrom(), is(nullValue())); + assertThat(changes.getPermission().getTo(), is("write")); + assertThat(changes.getRoleName().getTo(), is("maintain")); } /** diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member_added_role_name.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member_added_role_name.json new file mode 100644 index 0000000000..f5ab1a007f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member_added_role_name.json @@ -0,0 +1,169 @@ +{ + "action": "added", + "member": { + "login": "yrodiere", + "id": 412878, + "node_id": "MDQ6VXNlcjQxMjg3OA==", + "avatar_url": "https://avatars.githubusercontent.com/u/412878?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/yrodiere", + "html_url": "https://github.com/yrodiere", + "followers_url": "https://api.github.com/users/yrodiere/followers", + "following_url": "https://api.github.com/users/yrodiere/following{/other_user}", + "gists_url": "https://api.github.com/users/yrodiere/gists{/gist_id}", + "starred_url": "https://api.github.com/users/yrodiere/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/yrodiere/subscriptions", + "organizations_url": "https://api.github.com/users/yrodiere/orgs", + "repos_url": "https://api.github.com/users/yrodiere/repos", + "events_url": "https://api.github.com/users/yrodiere/events{/privacy}", + "received_events_url": "https://api.github.com/users/yrodiere/received_events", + "type": "User", + "site_admin": false + }, + "changes": { "permission": { "to": "write" }, "role_name": { "to": "maintain" } }, + "repository": { + "id": 493568123, + "node_id": "R_kgDOHWtAew", + "name": "github-automation-with-quarkus-demo-playground", + "full_name": "gsmet-bot-playground/github-automation-with-quarkus-demo-playground", + "private": false, + "owner": { + "login": "gsmet-bot-playground", + "id": 81260024, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/81260024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gsmet-bot-playground", + "html_url": "https://github.com/gsmet-bot-playground", + "followers_url": "https://api.github.com/users/gsmet-bot-playground/followers", + "following_url": "https://api.github.com/users/gsmet-bot-playground/following{/other_user}", + "gists_url": "https://api.github.com/users/gsmet-bot-playground/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gsmet-bot-playground/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gsmet-bot-playground/subscriptions", + "organizations_url": "https://api.github.com/users/gsmet-bot-playground/orgs", + "repos_url": "https://api.github.com/users/gsmet-bot-playground/repos", + "events_url": "https://api.github.com/users/gsmet-bot-playground/events{/privacy}", + "received_events_url": "https://api.github.com/users/gsmet-bot-playground/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/gsmet-bot-playground/github-automation-with-quarkus-demo-playground", + "description": "Example repository with a demo GitHub app (github-automation-with-quarkus-demo-app) installed", + "fork": false, + "url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground", + "forks_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/forks", + "keys_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/teams", + "hooks_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/hooks", + "issue_events_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/issues/events{/number}", + "events_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/events", + "assignees_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/assignees{/user}", + "branches_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/branches{/branch}", + "tags_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/tags", + "blobs_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/statuses/{sha}", + "languages_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/languages", + "stargazers_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/stargazers", + "contributors_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/contributors", + "subscribers_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/subscribers", + "subscription_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/subscription", + "commits_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/contents/{+path}", + "compare_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/merges", + "archive_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/downloads", + "issues_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/issues{/number}", + "pulls_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/pulls{/number}", + "milestones_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/milestones{/number}", + "notifications_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/labels{/name}", + "releases_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/releases{/id}", + "deployments_url": "https://api.github.com/repos/gsmet-bot-playground/github-automation-with-quarkus-demo-playground/deployments", + "created_at": "2022-05-18T08:07:30Z", + "updated_at": "2022-05-19T10:46:46Z", + "pushed_at": "2023-07-07T08:22:15Z", + "git_url": "git://github.com/gsmet-bot-playground/github-automation-with-quarkus-demo-playground.git", + "ssh_url": "git@github.com:gsmet-bot-playground/github-automation-with-quarkus-demo-playground.git", + "clone_url": "https://github.com/gsmet-bot-playground/github-automation-with-quarkus-demo-playground.git", + "svn_url": "https://github.com/gsmet-bot-playground/github-automation-with-quarkus-demo-playground", + "homepage": null, + "size": 5, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "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": 0, + "license": { + "key": "apache-2.0", + "name": "Apache License 2.0", + "spdx_id": "Apache-2.0", + "url": "https://api.github.com/licenses/apache-2.0", + "node_id": "MDc6TGljZW5zZTI=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "main", + "custom_properties": {} + }, + "organization": { + "login": "gsmet-bot-playground", + "id": 81260024, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0", + "url": "https://api.github.com/orgs/gsmet-bot-playground", + "repos_url": "https://api.github.com/orgs/gsmet-bot-playground/repos", + "events_url": "https://api.github.com/orgs/gsmet-bot-playground/events", + "hooks_url": "https://api.github.com/orgs/gsmet-bot-playground/hooks", + "issues_url": "https://api.github.com/orgs/gsmet-bot-playground/issues", + "members_url": "https://api.github.com/orgs/gsmet-bot-playground/members{/member}", + "public_members_url": "https://api.github.com/orgs/gsmet-bot-playground/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/81260024?v=4", + "description": null + }, + "sender": { + "login": "gsmet", + "id": 1279749, + "node_id": "MDQ6VXNlcjEyNzk3NDk=", + "avatar_url": "https://avatars.githubusercontent.com/u/1279749?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gsmet", + "html_url": "https://github.com/gsmet", + "followers_url": "https://api.github.com/users/gsmet/followers", + "following_url": "https://api.github.com/users/gsmet/following{/other_user}", + "gists_url": "https://api.github.com/users/gsmet/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gsmet/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gsmet/subscriptions", + "organizations_url": "https://api.github.com/users/gsmet/orgs", + "repos_url": "https://api.github.com/users/gsmet/repos", + "events_url": "https://api.github.com/users/gsmet/events{/privacy}", + "received_events_url": "https://api.github.com/users/gsmet/received_events", + "type": "User", + "site_admin": false + }, + "installation": { + "id": 16779846, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY3Nzk4NDY=" + } +} \ No newline at end of file