diff options
author | Aurelien Poscia <aurelien.poscia@sonarsource.com> | 2023-10-11 08:46:26 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-10-20 20:02:40 +0000 |
commit | 6a8aa6c62e0ccf8918f76885796bd550665286de (patch) | |
tree | 3f6ca755b290cfb7348ba188f307ac93008194b0 /server/sonar-alm-client/src/test/java | |
parent | 4670e9985e7b7bedf952c99a498a3a1c13912dd0 (diff) | |
download | sonarqube-6a8aa6c62e0ccf8918f76885796bd550665286de.tar.gz sonarqube-6a8aa6c62e0ccf8918f76885796bd550665286de.zip |
SONAR-20699 Auto-bind project to GitHub DevOps config
Diffstat (limited to 'server/sonar-alm-client/src/test/java')
2 files changed, 463 insertions, 347 deletions
diff --git a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/AppInstallationTokenTest.java b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/AppInstallationTokenTest.java new file mode 100644 index 00000000000..0f4bd9ae3f3 --- /dev/null +++ b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/AppInstallationTokenTest.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.alm.client.github; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AppInstallationTokenTest { + + @Test + public void test_value() { + AppInstallationToken underTest = new AppInstallationToken("foo"); + + assertThat(underTest.toString()) + .isEqualTo(underTest.getValue()) + .isEqualTo("foo"); + assertThat(underTest.getAuthorizationHeaderPrefix()).isEqualTo("Token"); + } + + @Test + public void test_equals_hashCode() { + AppInstallationToken foo = new AppInstallationToken("foo"); + + assertThat(foo.equals(foo)).isTrue(); + assertThat(foo.equals(null)).isFalse(); + assertThat(foo.equals(new AppInstallationToken("foo"))).isTrue(); + assertThat(foo.equals(new AppInstallationToken("bar"))).isFalse(); + assertThat(foo.equals("foo")).isFalse(); + + assertThat(foo).hasSameHashCodeAs(new AppInstallationToken("foo")); + } +} diff --git a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationClientImplTest.java b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationClientImplTest.java index 855f8f66e7c..0429beebdc5 100644 --- a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationClientImplTest.java +++ b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationClientImplTest.java @@ -32,6 +32,7 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.event.Level; import org.sonar.alm.client.github.GithubApplicationHttpClient.RateLimit; import org.sonar.alm.client.github.config.GithubAppConfiguration; import org.sonar.alm.client.github.config.GithubAppInstallation; @@ -39,11 +40,13 @@ import org.sonar.alm.client.github.security.AccessToken; import org.sonar.alm.client.github.security.AppToken; import org.sonar.alm.client.github.security.GithubAppSecurity; import org.sonar.alm.client.github.security.UserAccessToken; +import org.sonar.api.testfixtures.log.LogAndArguments; import org.sonar.api.testfixtures.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.auth.github.GitHubSettings; import org.sonarqube.ws.client.HttpException; +import static java.net.HttpURLConnection.HTTP_CREATED; import static java.net.HttpURLConnection.HTTP_FORBIDDEN; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; @@ -53,6 +56,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.groups.Tuple.tuple; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -62,6 +66,7 @@ import static org.sonar.alm.client.github.GithubApplicationHttpClient.GetRespons @RunWith(DataProviderRunner.class) public class GithubApplicationClientImplTest { + private static final int INSTALLATION_ID = 1; private static final String APP_JWT_TOKEN = "APP_TOKEN_JWT"; private static final String PAYLOAD_2_ORGS = """ [ @@ -204,12 +209,12 @@ public class GithubApplicationClientImplTest { AppToken appToken = mockAppToken(); String json = "{" - + " \"permissions\": {\n" - + " \"checks\": \"read\",\n" - + " \"metadata\": \"read\",\n" - + " \"pull_requests\": \"read\"\n" - + " }\n" - + "}"; + + " \"permissions\": {\n" + + " \"checks\": \"read\",\n" + + " \"metadata\": \"read\",\n" + + " \"pull_requests\": \"read\"\n" + + " }\n" + + "}"; when(httpClient.get(appUrl, appToken, "/app")).thenReturn(new OkGetResponse(json)); @@ -223,12 +228,12 @@ public class GithubApplicationClientImplTest { AppToken appToken = mockAppToken(); String json = "{" - + " \"permissions\": {\n" - + " \"checks\": \"write\",\n" - + " \"metadata\": \"read\",\n" - + " \"pull_requests\": \"write\"\n" - + " }\n" - + "}"; + + " \"permissions\": {\n" + + " \"checks\": \"write\",\n" + + " \"metadata\": \"read\",\n" + + " \"pull_requests\": \"write\"\n" + + " }\n" + + "}"; when(httpClient.get(appUrl, appToken, "/app")).thenReturn(new OkGetResponse(json)); @@ -391,8 +396,8 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"total_count\": 0\n" - + "} "; + + " \"total_count\": 0\n" + + "} "; when(httpClient.get(appUrl, accessToken, String.format("/user/installations?page=%s&per_page=%s", 1, 100))) .thenReturn(new OkGetResponse(responseJson)); @@ -408,82 +413,82 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"total_count\": 2,\n" - + " \"installations\": [\n" - + " {\n" - + " \"id\": 1,\n" - + " \"account\": {\n" - + " \"login\": \"github\",\n" - + " \"id\": 1,\n" - + " \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjE=\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/orgs/github\",\n" - + " \"repos_url\": \"https://github.sonarsource.com/api/v3/orgs/github/repos\",\n" - + " \"events_url\": \"https://github.sonarsource.com/api/v3/orgs/github/events\",\n" - + " \"hooks_url\": \"https://github.sonarsource.com/api/v3/orgs/github/hooks\",\n" - + " \"issues_url\": \"https://github.sonarsource.com/api/v3/orgs/github/issues\",\n" - + " \"members_url\": \"https://github.sonarsource.com/api/v3/orgs/github/members{/member}\",\n" - + " \"public_members_url\": \"https://github.sonarsource.com/api/v3/orgs/github/public_members{/member}\",\n" - + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" - + " \"description\": \"A great organization\"\n" - + " },\n" - + " \"access_tokens_url\": \"https://github.sonarsource.com/api/v3/app/installations/1/access_tokens\",\n" - + " \"repositories_url\": \"https://github.sonarsource.com/api/v3/installation/repositories\",\n" - + " \"html_url\": \"https://github.com/organizations/github/settings/installations/1\",\n" - + " \"app_id\": 1,\n" - + " \"target_id\": 1,\n" - + " \"target_type\": \"Organization\",\n" - + " \"permissions\": {\n" - + " \"checks\": \"write\",\n" - + " \"metadata\": \"read\",\n" - + " \"contents\": \"read\"\n" - + " },\n" - + " \"events\": [\n" - + " \"push\",\n" - + " \"pull_request\"\n" - + " ],\n" - + " \"single_file_name\": \"config.yml\"\n" - + " },\n" - + " {\n" - + " \"id\": 3,\n" - + " \"account\": {\n" - + " \"login\": \"octocat\",\n" - + " \"id\": 2,\n" - + " \"node_id\": \"MDQ6VXNlcjE=\",\n" - + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" - + " \"html_url\": \"https://github.com/octocat\",\n" - + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" - + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" - + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" - + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" - + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" - + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" - + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" - + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" - + " \"type\": \"User\",\n" - + " \"site_admin\": false\n" - + " },\n" - + " \"access_tokens_url\": \"https://github.sonarsource.com/api/v3/app/installations/1/access_tokens\",\n" - + " \"repositories_url\": \"https://github.sonarsource.com/api/v3/installation/repositories\",\n" - + " \"html_url\": \"https://github.com/organizations/github/settings/installations/1\",\n" - + " \"app_id\": 1,\n" - + " \"target_id\": 1,\n" - + " \"target_type\": \"Organization\",\n" - + " \"permissions\": {\n" - + " \"checks\": \"write\",\n" - + " \"metadata\": \"read\",\n" - + " \"contents\": \"read\"\n" - + " },\n" - + " \"events\": [\n" - + " \"push\",\n" - + " \"pull_request\"\n" - + " ],\n" - + " \"single_file_name\": \"config.yml\"\n" - + " }\n" - + " ]\n" - + "} "; + + " \"total_count\": 2,\n" + + " \"installations\": [\n" + + " {\n" + + " \"id\": 1,\n" + + " \"account\": {\n" + + " \"login\": \"github\",\n" + + " \"id\": 1,\n" + + " \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjE=\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/orgs/github\",\n" + + " \"repos_url\": \"https://github.sonarsource.com/api/v3/orgs/github/repos\",\n" + + " \"events_url\": \"https://github.sonarsource.com/api/v3/orgs/github/events\",\n" + + " \"hooks_url\": \"https://github.sonarsource.com/api/v3/orgs/github/hooks\",\n" + + " \"issues_url\": \"https://github.sonarsource.com/api/v3/orgs/github/issues\",\n" + + " \"members_url\": \"https://github.sonarsource.com/api/v3/orgs/github/members{/member}\",\n" + + " \"public_members_url\": \"https://github.sonarsource.com/api/v3/orgs/github/public_members{/member}\",\n" + + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" + + " \"description\": \"A great organization\"\n" + + " },\n" + + " \"access_tokens_url\": \"https://github.sonarsource.com/api/v3/app/installations/1/access_tokens\",\n" + + " \"repositories_url\": \"https://github.sonarsource.com/api/v3/installation/repositories\",\n" + + " \"html_url\": \"https://github.com/organizations/github/settings/installations/1\",\n" + + " \"app_id\": 1,\n" + + " \"target_id\": 1,\n" + + " \"target_type\": \"Organization\",\n" + + " \"permissions\": {\n" + + " \"checks\": \"write\",\n" + + " \"metadata\": \"read\",\n" + + " \"contents\": \"read\"\n" + + " },\n" + + " \"events\": [\n" + + " \"push\",\n" + + " \"pull_request\"\n" + + " ],\n" + + " \"single_file_name\": \"config.yml\"\n" + + " },\n" + + " {\n" + + " \"id\": 3,\n" + + " \"account\": {\n" + + " \"login\": \"octocat\",\n" + + " \"id\": 2,\n" + + " \"node_id\": \"MDQ6VXNlcjE=\",\n" + + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" + + " \"html_url\": \"https://github.com/octocat\",\n" + + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" + + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" + + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" + + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" + + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" + + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" + + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" + + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" + + " \"type\": \"User\",\n" + + " \"site_admin\": false\n" + + " },\n" + + " \"access_tokens_url\": \"https://github.sonarsource.com/api/v3/app/installations/1/access_tokens\",\n" + + " \"repositories_url\": \"https://github.sonarsource.com/api/v3/installation/repositories\",\n" + + " \"html_url\": \"https://github.com/organizations/github/settings/installations/1\",\n" + + " \"app_id\": 1,\n" + + " \"target_id\": 1,\n" + + " \"target_type\": \"Organization\",\n" + + " \"permissions\": {\n" + + " \"checks\": \"write\",\n" + + " \"metadata\": \"read\",\n" + + " \"contents\": \"read\"\n" + + " },\n" + + " \"events\": [\n" + + " \"push\",\n" + + " \"pull_request\"\n" + + " ],\n" + + " \"single_file_name\": \"config.yml\"\n" + + " }\n" + + " ]\n" + + "} "; when(httpClient.get(appUrl, accessToken, String.format("/user/installations?page=%s&per_page=%s", 1, 100))) .thenReturn(new OkGetResponse(responseJson)); @@ -565,12 +570,12 @@ public class GithubApplicationClientImplTest { public void getWhitelistedGithubAppInstallations_whenGithubReturnsError_shouldThrow() throws IOException { AppToken appToken = new AppToken(APP_JWT_TOKEN); when(appSecurity.createAppToken(githubAppConfiguration.getId(), githubAppConfiguration.getPrivateKey())).thenReturn(appToken); - when(githubPaginatedHttpClient.get(any(),any(),any(),any())).thenThrow(new IOException("io exception")); + when(githubPaginatedHttpClient.get(any(), any(), any(), any())).thenThrow(new IOException("io exception")); assertThatThrownBy(() -> underTest.getWhitelistedGithubAppInstallations(githubAppConfiguration)) .isInstanceOf(IllegalStateException.class) .hasMessage("An error occurred when retrieving your GitHup App installations. " - + "It might be related to your GitHub App configuration or a connectivity problem."); + + "It might be related to your GitHub App configuration or a connectivity problem."); } @Test @@ -610,8 +615,8 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"total_count\": 0\n" - + "}"; + + " \"total_count\": 0\n" + + "}"; when(httpClient.get(appUrl, accessToken, String.format("/search/repositories?q=%s&page=%s&per_page=%s", "fork:true+org:github", 1, 100))) .thenReturn(new OkGetResponse(responseJson)); @@ -627,79 +632,79 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"total_count\": 2,\n" - + " \"incomplete_results\": false,\n" - + " \"items\": [\n" - + " {\n" - + " \"id\": 3081286,\n" - + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" - + " \"name\": \"HelloWorld\",\n" - + " \"full_name\": \"github/HelloWorld\",\n" - + " \"owner\": {\n" - + " \"login\": \"github\",\n" - + " \"id\": 872147,\n" - + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" - + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" - + " \"type\": \"User\"\n" - + " },\n" - + " \"private\": false,\n" - + " \"html_url\": \"https://github.com/github/HelloWorld\",\n" - + " \"description\": \"A C implementation of HelloWorld\",\n" - + " \"fork\": false,\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloWorld\",\n" - + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" - + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" - + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" - + " \"homepage\": \"\",\n" - + " \"size\": 524,\n" - + " \"stargazers_count\": 1,\n" - + " \"watchers_count\": 1,\n" - + " \"language\": \"Assembly\",\n" - + " \"forks_count\": 0,\n" - + " \"open_issues_count\": 0,\n" - + " \"master_branch\": \"master\",\n" - + " \"default_branch\": \"master\",\n" - + " \"score\": 1.0\n" - + " },\n" - + " {\n" - + " \"id\": 3081286,\n" - + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" - + " \"name\": \"HelloUniverse\",\n" - + " \"full_name\": \"github/HelloUniverse\",\n" - + " \"owner\": {\n" - + " \"login\": \"github\",\n" - + " \"id\": 872147,\n" - + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" - + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" - + " \"type\": \"User\"\n" - + " },\n" - + " \"private\": false,\n" - + " \"html_url\": \"https://github.com/github/HelloUniverse\",\n" - + " \"description\": \"A C implementation of HelloUniverse\",\n" - + " \"fork\": false,\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloUniverse\",\n" - + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" - + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" - + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" - + " \"homepage\": \"\",\n" - + " \"size\": 524,\n" - + " \"stargazers_count\": 1,\n" - + " \"watchers_count\": 1,\n" - + " \"language\": \"Assembly\",\n" - + " \"forks_count\": 0,\n" - + " \"open_issues_count\": 0,\n" - + " \"master_branch\": \"master\",\n" - + " \"default_branch\": \"master\",\n" - + " \"score\": 1.0\n" - + " }\n" - + " ]\n" - + "}"; + + " \"total_count\": 2,\n" + + " \"incomplete_results\": false,\n" + + " \"items\": [\n" + + " {\n" + + " \"id\": 3081286,\n" + + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" + + " \"name\": \"HelloWorld\",\n" + + " \"full_name\": \"github/HelloWorld\",\n" + + " \"owner\": {\n" + + " \"login\": \"github\",\n" + + " \"id\": 872147,\n" + + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" + + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" + + " \"type\": \"User\"\n" + + " },\n" + + " \"private\": false,\n" + + " \"html_url\": \"https://github.com/github/HelloWorld\",\n" + + " \"description\": \"A C implementation of HelloWorld\",\n" + + " \"fork\": false,\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloWorld\",\n" + + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" + + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" + + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" + + " \"homepage\": \"\",\n" + + " \"size\": 524,\n" + + " \"stargazers_count\": 1,\n" + + " \"watchers_count\": 1,\n" + + " \"language\": \"Assembly\",\n" + + " \"forks_count\": 0,\n" + + " \"open_issues_count\": 0,\n" + + " \"master_branch\": \"master\",\n" + + " \"default_branch\": \"master\",\n" + + " \"score\": 1.0\n" + + " },\n" + + " {\n" + + " \"id\": 3081286,\n" + + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" + + " \"name\": \"HelloUniverse\",\n" + + " \"full_name\": \"github/HelloUniverse\",\n" + + " \"owner\": {\n" + + " \"login\": \"github\",\n" + + " \"id\": 872147,\n" + + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" + + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" + + " \"type\": \"User\"\n" + + " },\n" + + " \"private\": false,\n" + + " \"html_url\": \"https://github.com/github/HelloUniverse\",\n" + + " \"description\": \"A C implementation of HelloUniverse\",\n" + + " \"fork\": false,\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloUniverse\",\n" + + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" + + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" + + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" + + " \"homepage\": \"\",\n" + + " \"size\": 524,\n" + + " \"stargazers_count\": 1,\n" + + " \"watchers_count\": 1,\n" + + " \"language\": \"Assembly\",\n" + + " \"forks_count\": 0,\n" + + " \"open_issues_count\": 0,\n" + + " \"master_branch\": \"master\",\n" + + " \"default_branch\": \"master\",\n" + + " \"score\": 1.0\n" + + " }\n" + + " ]\n" + + "}"; when(httpClient.get(appUrl, accessToken, String.format("/search/repositories?q=%s&page=%s&per_page=%s", "fork:true+org:github", 1, 100))) .thenReturn(new OkGetResponse(responseJson)); @@ -716,45 +721,45 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"total_count\": 2,\n" - + " \"incomplete_results\": false,\n" - + " \"items\": [\n" - + " {\n" - + " \"id\": 3081286,\n" - + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" - + " \"name\": \"HelloWorld\",\n" - + " \"full_name\": \"github/HelloWorld\",\n" - + " \"owner\": {\n" - + " \"login\": \"github\",\n" - + " \"id\": 872147,\n" - + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" - + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" - + " \"type\": \"User\"\n" - + " },\n" - + " \"private\": false,\n" - + " \"html_url\": \"https://github.com/github/HelloWorld\",\n" - + " \"description\": \"A C implementation of HelloWorld\",\n" - + " \"fork\": false,\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloWorld\",\n" - + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" - + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" - + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" - + " \"homepage\": \"\",\n" - + " \"size\": 524,\n" - + " \"stargazers_count\": 1,\n" - + " \"watchers_count\": 1,\n" - + " \"language\": \"Assembly\",\n" - + " \"forks_count\": 0,\n" - + " \"open_issues_count\": 0,\n" - + " \"master_branch\": \"master\",\n" - + " \"default_branch\": \"master\",\n" - + " \"score\": 1.0\n" - + " }\n" - + " ]\n" - + "}"; + + " \"total_count\": 2,\n" + + " \"incomplete_results\": false,\n" + + " \"items\": [\n" + + " {\n" + + " \"id\": 3081286,\n" + + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkzMDgxMjg2\",\n" + + " \"name\": \"HelloWorld\",\n" + + " \"full_name\": \"github/HelloWorld\",\n" + + " \"owner\": {\n" + + " \"login\": \"github\",\n" + + " \"id\": 872147,\n" + + " \"node_id\": \"MDQ6VXNlcjg3MjE0Nw==\",\n" + + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/github\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/github/received_events\",\n" + + " \"type\": \"User\"\n" + + " },\n" + + " \"private\": false,\n" + + " \"html_url\": \"https://github.com/github/HelloWorld\",\n" + + " \"description\": \"A C implementation of HelloWorld\",\n" + + " \"fork\": false,\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/repos/github/HelloWorld\",\n" + + " \"created_at\": \"2012-01-01T00:31:50Z\",\n" + + " \"updated_at\": \"2013-01-05T17:58:47Z\",\n" + + " \"pushed_at\": \"2012-01-01T00:37:02Z\",\n" + + " \"homepage\": \"\",\n" + + " \"size\": 524,\n" + + " \"stargazers_count\": 1,\n" + + " \"watchers_count\": 1,\n" + + " \"language\": \"Assembly\",\n" + + " \"forks_count\": 0,\n" + + " \"open_issues_count\": 0,\n" + + " \"master_branch\": \"master\",\n" + + " \"default_branch\": \"master\",\n" + + " \"score\": 1.0\n" + + " }\n" + + " ]\n" + + "}"; when(httpClient.get(appUrl, accessToken, String.format("/search/repositories?q=%s&page=%s&per_page=%s", "world+fork:true+org:github", 1, 100))) .thenReturn(new GetResponse() { @@ -792,7 +797,7 @@ public class GithubApplicationClientImplTest { when(httpClient.get(any(), any(), any())) .thenReturn(new Response(404, null)); - Optional<GithubApplicationClient.Repository> repository = underTest.getRepository(appUrl, new UserAccessToken("temp"), "octocat", "octocat/Hello-World"); + Optional<GithubApplicationClient.Repository> repository = underTest.getRepository(appUrl, new UserAccessToken("temp"), "octocat/Hello-World"); assertThat(repository).isEmpty(); } @@ -800,15 +805,14 @@ public class GithubApplicationClientImplTest { @Test public void getRepository_fails_on_failure() throws IOException { String repositoryKey = "octocat/Hello-World"; - String organization = "octocat"; when(httpClient.get(any(), any(), any())) .thenThrow(new IOException("OOPS")); UserAccessToken token = new UserAccessToken("temp"); - assertThatThrownBy(() -> underTest.getRepository(appUrl, token, organization, repositoryKey)) + assertThatThrownBy(() -> underTest.getRepository(appUrl, token, repositoryKey)) .isInstanceOf(IllegalStateException.class) - .hasMessage("Failed to get repository '%s' of '%s' accessible by user access token on '%s'", repositoryKey, organization, appUrl); + .hasMessage("Failed to get repository 'octocat/Hello-World' on 'Any URL' (this might be related to the GitHub App installation scope)"); } @Test @@ -816,142 +820,142 @@ public class GithubApplicationClientImplTest { String appUrl = "https://github.sonarsource.com"; AccessToken accessToken = new UserAccessToken(randomAlphanumeric(10)); String responseJson = "{\n" - + " \"id\": 1296269,\n" - + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMjk2MjY5\",\n" - + " \"name\": \"Hello-World\",\n" - + " \"full_name\": \"octocat/Hello-World\",\n" - + " \"owner\": {\n" - + " \"login\": \"octocat\",\n" - + " \"id\": 1,\n" - + " \"node_id\": \"MDQ6VXNlcjE=\",\n" - + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" - + " \"html_url\": \"https://github.com/octocat\",\n" - + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" - + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" - + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" - + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" - + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" - + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" - + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" - + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" - + " \"type\": \"User\",\n" - + " \"site_admin\": false\n" - + " },\n" - + " \"private\": false,\n" - + " \"html_url\": \"https://github.com/octocat/Hello-World\",\n" - + " \"description\": \"This your first repo!\",\n" - + " \"fork\": false,\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World\",\n" - + " \"archive_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/{archive_format}{/ref}\",\n" - + " \"assignees_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/assignees{/user}\",\n" - + " \"blobs_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/blobs{/sha}\",\n" - + " \"branches_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/branches{/branch}\",\n" - + " \"collaborators_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/collaborators{/collaborator}\",\n" - + " \"comments_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/comments{/number}\",\n" - + " \"commits_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/commits{/sha}\",\n" - + " \"compare_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/compare/{base}...{head}\",\n" - + " \"contents_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/contents/{+path}\",\n" - + " \"contributors_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/contributors\",\n" - + " \"deployments_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/deployments\",\n" - + " \"downloads_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/downloads\",\n" - + " \"events_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/events\",\n" - + " \"forks_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/forks\",\n" - + " \"git_commits_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/commits{/sha}\",\n" - + " \"git_refs_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/refs{/sha}\",\n" - + " \"git_tags_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/tags{/sha}\",\n" - + " \"git_url\": \"git:github.com/octocat/Hello-World.git\",\n" - + " \"issue_comment_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues/comments{/number}\",\n" - + " \"issue_events_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues/events{/number}\",\n" - + " \"issues_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues{/number}\",\n" - + " \"keys_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/keys{/key_id}\",\n" - + " \"labels_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/labels{/name}\",\n" - + " \"languages_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/languages\",\n" - + " \"merges_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/merges\",\n" - + " \"milestones_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/milestones{/number}\",\n" - + " \"notifications_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/notifications{?since,all,participating}\",\n" - + " \"pulls_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/pulls{/number}\",\n" - + " \"releases_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/releases{/id}\",\n" - + " \"ssh_url\": \"git@github.com:octocat/Hello-World.git\",\n" - + " \"stargazers_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/stargazers\",\n" - + " \"statuses_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/statuses/{sha}\",\n" - + " \"subscribers_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/subscribers\",\n" - + " \"subscription_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/subscription\",\n" - + " \"tags_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/tags\",\n" - + " \"teams_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/teams\",\n" - + " \"trees_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/trees{/sha}\",\n" - + " \"clone_url\": \"https://github.com/octocat/Hello-World.git\",\n" - + " \"mirror_url\": \"git:git.example.com/octocat/Hello-World\",\n" - + " \"hooks_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/hooks\",\n" - + " \"svn_url\": \"https://svn.github.com/octocat/Hello-World\",\n" - + " \"homepage\": \"https://github.com\",\n" - + " \"language\": null,\n" - + " \"forks_count\": 9,\n" - + " \"stargazers_count\": 80,\n" - + " \"watchers_count\": 80,\n" - + " \"size\": 108,\n" - + " \"default_branch\": \"master\",\n" - + " \"open_issues_count\": 0,\n" - + " \"is_template\": true,\n" - + " \"topics\": [\n" - + " \"octocat\",\n" - + " \"atom\",\n" - + " \"electron\",\n" - + " \"api\"\n" - + " ],\n" - + " \"has_issues\": true,\n" - + " \"has_projects\": true,\n" - + " \"has_wiki\": true,\n" - + " \"has_pages\": false,\n" - + " \"has_downloads\": true,\n" - + " \"archived\": false,\n" - + " \"disabled\": false,\n" - + " \"visibility\": \"public\",\n" - + " \"pushed_at\": \"2011-01-26T19:06:43Z\",\n" - + " \"created_at\": \"2011-01-26T19:01:12Z\",\n" - + " \"updated_at\": \"2011-01-26T19:14:43Z\",\n" - + " \"permissions\": {\n" - + " \"admin\": false,\n" - + " \"push\": false,\n" - + " \"pull\": true\n" - + " },\n" - + " \"allow_rebase_merge\": true,\n" - + " \"template_repository\": null,\n" - + " \"allow_squash_merge\": true,\n" - + " \"allow_merge_commit\": true,\n" - + " \"subscribers_count\": 42,\n" - + " \"network_count\": 0,\n" - + " \"anonymous_access_enabled\": false,\n" - + " \"license\": {\n" - + " \"key\": \"mit\",\n" - + " \"name\": \"MIT License\",\n" - + " \"spdx_id\": \"MIT\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/licenses/mit\",\n" - + " \"node_id\": \"MDc6TGljZW5zZW1pdA==\"\n" - + " },\n" - + " \"organization\": {\n" - + " \"login\": \"octocat\",\n" - + " \"id\": 1,\n" - + " \"node_id\": \"MDQ6VXNlcjE=\",\n" - + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" - + " \"gravatar_id\": \"\",\n" - + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" - + " \"html_url\": \"https://github.com/octocat\",\n" - + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" - + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" - + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" - + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" - + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" - + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" - + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" - + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" - + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" - + " \"type\": \"Organization\",\n" - + " \"site_admin\": false\n" - + " }" - + "}"; + + " \"id\": 1296269,\n" + + " \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMjk2MjY5\",\n" + + " \"name\": \"Hello-World\",\n" + + " \"full_name\": \"octocat/Hello-World\",\n" + + " \"owner\": {\n" + + " \"login\": \"octocat\",\n" + + " \"id\": 1,\n" + + " \"node_id\": \"MDQ6VXNlcjE=\",\n" + + " \"avatar_url\": \"https://github.sonarsource.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" + + " \"html_url\": \"https://github.com/octocat\",\n" + + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" + + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" + + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" + + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" + + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" + + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" + + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" + + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" + + " \"type\": \"User\",\n" + + " \"site_admin\": false\n" + + " },\n" + + " \"private\": false,\n" + + " \"html_url\": \"https://github.com/octocat/Hello-World\",\n" + + " \"description\": \"This your first repo!\",\n" + + " \"fork\": false,\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World\",\n" + + " \"archive_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/{archive_format}{/ref}\",\n" + + " \"assignees_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/assignees{/user}\",\n" + + " \"blobs_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/blobs{/sha}\",\n" + + " \"branches_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/branches{/branch}\",\n" + + " \"collaborators_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/collaborators{/collaborator}\",\n" + + " \"comments_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/comments{/number}\",\n" + + " \"commits_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/commits{/sha}\",\n" + + " \"compare_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/compare/{base}...{head}\",\n" + + " \"contents_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/contents/{+path}\",\n" + + " \"contributors_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/contributors\",\n" + + " \"deployments_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/deployments\",\n" + + " \"downloads_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/downloads\",\n" + + " \"events_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/events\",\n" + + " \"forks_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/forks\",\n" + + " \"git_commits_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/commits{/sha}\",\n" + + " \"git_refs_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/refs{/sha}\",\n" + + " \"git_tags_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/tags{/sha}\",\n" + + " \"git_url\": \"git:github.com/octocat/Hello-World.git\",\n" + + " \"issue_comment_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues/comments{/number}\",\n" + + " \"issue_events_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues/events{/number}\",\n" + + " \"issues_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/issues{/number}\",\n" + + " \"keys_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/keys{/key_id}\",\n" + + " \"labels_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/labels{/name}\",\n" + + " \"languages_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/languages\",\n" + + " \"merges_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/merges\",\n" + + " \"milestones_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/milestones{/number}\",\n" + + " \"notifications_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/notifications{?since,all,participating}\",\n" + + " \"pulls_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/pulls{/number}\",\n" + + " \"releases_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/releases{/id}\",\n" + + " \"ssh_url\": \"git@github.com:octocat/Hello-World.git\",\n" + + " \"stargazers_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/stargazers\",\n" + + " \"statuses_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/statuses/{sha}\",\n" + + " \"subscribers_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/subscribers\",\n" + + " \"subscription_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/subscription\",\n" + + " \"tags_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/tags\",\n" + + " \"teams_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/teams\",\n" + + " \"trees_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/git/trees{/sha}\",\n" + + " \"clone_url\": \"https://github.com/octocat/Hello-World.git\",\n" + + " \"mirror_url\": \"git:git.example.com/octocat/Hello-World\",\n" + + " \"hooks_url\": \"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World/hooks\",\n" + + " \"svn_url\": \"https://svn.github.com/octocat/Hello-World\",\n" + + " \"homepage\": \"https://github.com\",\n" + + " \"language\": null,\n" + + " \"forks_count\": 9,\n" + + " \"stargazers_count\": 80,\n" + + " \"watchers_count\": 80,\n" + + " \"size\": 108,\n" + + " \"default_branch\": \"master\",\n" + + " \"open_issues_count\": 0,\n" + + " \"is_template\": true,\n" + + " \"topics\": [\n" + + " \"octocat\",\n" + + " \"atom\",\n" + + " \"electron\",\n" + + " \"api\"\n" + + " ],\n" + + " \"has_issues\": true,\n" + + " \"has_projects\": true,\n" + + " \"has_wiki\": true,\n" + + " \"has_pages\": false,\n" + + " \"has_downloads\": true,\n" + + " \"archived\": false,\n" + + " \"disabled\": false,\n" + + " \"visibility\": \"public\",\n" + + " \"pushed_at\": \"2011-01-26T19:06:43Z\",\n" + + " \"created_at\": \"2011-01-26T19:01:12Z\",\n" + + " \"updated_at\": \"2011-01-26T19:14:43Z\",\n" + + " \"permissions\": {\n" + + " \"admin\": false,\n" + + " \"push\": false,\n" + + " \"pull\": true\n" + + " },\n" + + " \"allow_rebase_merge\": true,\n" + + " \"template_repository\": null,\n" + + " \"allow_squash_merge\": true,\n" + + " \"allow_merge_commit\": true,\n" + + " \"subscribers_count\": 42,\n" + + " \"network_count\": 0,\n" + + " \"anonymous_access_enabled\": false,\n" + + " \"license\": {\n" + + " \"key\": \"mit\",\n" + + " \"name\": \"MIT License\",\n" + + " \"spdx_id\": \"MIT\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/licenses/mit\",\n" + + " \"node_id\": \"MDc6TGljZW5zZW1pdA==\"\n" + + " },\n" + + " \"organization\": {\n" + + " \"login\": \"octocat\",\n" + + " \"id\": 1,\n" + + " \"node_id\": \"MDQ6VXNlcjE=\",\n" + + " \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",\n" + + " \"gravatar_id\": \"\",\n" + + " \"url\": \"https://github.sonarsource.com/api/v3/users/octocat\",\n" + + " \"html_url\": \"https://github.com/octocat\",\n" + + " \"followers_url\": \"https://github.sonarsource.com/api/v3/users/octocat/followers\",\n" + + " \"following_url\": \"https://github.sonarsource.com/api/v3/users/octocat/following{/other_user}\",\n" + + " \"gists_url\": \"https://github.sonarsource.com/api/v3/users/octocat/gists{/gist_id}\",\n" + + " \"starred_url\": \"https://github.sonarsource.com/api/v3/users/octocat/starred{/owner}{/repo}\",\n" + + " \"subscriptions_url\": \"https://github.sonarsource.com/api/v3/users/octocat/subscriptions\",\n" + + " \"organizations_url\": \"https://github.sonarsource.com/api/v3/users/octocat/orgs\",\n" + + " \"repos_url\": \"https://github.sonarsource.com/api/v3/users/octocat/repos\",\n" + + " \"events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/events{/privacy}\",\n" + + " \"received_events_url\": \"https://github.sonarsource.com/api/v3/users/octocat/received_events\",\n" + + " \"type\": \"Organization\",\n" + + " \"site_admin\": false\n" + + " }" + + "}"; when(httpClient.get(appUrl, accessToken, "/repos/octocat/Hello-World")) .thenReturn(new GetResponse() { @@ -976,7 +980,7 @@ public class GithubApplicationClientImplTest { } }); - Optional<GithubApplicationClient.Repository> repository = underTest.getRepository(appUrl, accessToken, "octocat", "octocat/Hello-World"); + Optional<GithubApplicationClient.Repository> repository = underTest.getRepository(appUrl, accessToken, "octocat/Hello-World"); assertThat(repository) .isPresent() @@ -986,12 +990,74 @@ public class GithubApplicationClientImplTest { .containsOnly(1296269L, "Hello-World", "octocat/Hello-World", "https://github.com/octocat/Hello-World", false, "master"); } + @Test + public void createAppInstallationToken_throws_IAE_if_application_token_cant_be_created() { + mockNoApplicationJwtToken(); + + assertThatThrownBy(() -> underTest.createAppInstallationToken(githubAppConfiguration, INSTALLATION_ID)) + .isInstanceOf(IllegalArgumentException.class); + } + + private void mockNoApplicationJwtToken() { + when(appSecurity.createAppToken(githubAppConfiguration.getId(), githubAppConfiguration.getPrivateKey())).thenThrow(IllegalArgumentException.class); + } + + @Test + public void createAppInstallationToken_returns_empty_if_post_throws_IOE() throws IOException { + mockAppToken(); + when(httpClient.post(anyString(), any(AccessToken.class), anyString())).thenThrow(IOException.class); + Optional<AppInstallationToken> accessToken = underTest.createAppInstallationToken(githubAppConfiguration, INSTALLATION_ID); + + assertThat(accessToken).isEmpty(); + assertThat(logTester.getLogs(Level.WARN)).extracting(LogAndArguments::getRawMsg).anyMatch(s -> s.startsWith("Failed to request")); + } + + @Test + public void createAppInstallationToken_returns_empty_if_access_token_cant_be_created() throws IOException { + AppToken appToken = mockAppToken(); + mockAccessTokenCallingGithubFailure(); + + Optional<AppInstallationToken> accessToken = underTest.createAppInstallationToken(githubAppConfiguration, INSTALLATION_ID); + + assertThat(accessToken).isEmpty(); + verify(httpClient).post(appUrl, appToken, "/app/installations/" + INSTALLATION_ID + "/access_tokens"); + } + + @Test + public void createAppInstallationToken_from_installation_id_returns_access_token() throws IOException { + AppToken appToken = mockAppToken(); + AppInstallationToken installToken = mockCreateAccessTokenCallingGithub(); + + Optional<AppInstallationToken> accessToken = underTest.createAppInstallationToken(githubAppConfiguration, INSTALLATION_ID); + + assertThat(accessToken).hasValue(installToken); + verify(httpClient).post(appUrl, appToken, "/app/installations/" + INSTALLATION_ID + "/access_tokens"); + } + + private void mockAccessTokenCallingGithubFailure() throws IOException { + Response response = mock(Response.class); + when(response.getContent()).thenReturn(Optional.empty()); + when(response.getCode()).thenReturn(HTTP_UNAUTHORIZED); + when(httpClient.post(eq(appUrl), any(AppToken.class), eq("/app/installations/" + INSTALLATION_ID + "/access_tokens"))).thenReturn(response); + } + private AppToken mockAppToken() { String jwt = randomAlphanumeric(5); when(appSecurity.createAppToken(githubAppConfiguration.getId(), githubAppConfiguration.getPrivateKey())).thenReturn(new AppToken(jwt)); return new AppToken(jwt); } + private AppInstallationToken mockCreateAccessTokenCallingGithub() throws IOException { + String token = randomAlphanumeric(5); + Response response = mock(Response.class); + when(response.getContent()).thenReturn(Optional.of("{" + + " \"token\": \"" + token + "\"" + + "}")); + when(response.getCode()).thenReturn(HTTP_CREATED); + when(httpClient.post(eq(appUrl), any(AppToken.class), eq("/app/installations/" + INSTALLATION_ID + "/access_tokens"))).thenReturn(response); + return new AppInstallationToken(token); + } + private static class OkGetResponse extends Response { private OkGetResponse(String content) { super(200, content); |