diff --git a/.github/codecov.yml b/.github/codecov.yml deleted file mode 100644 index b05dc0869f..0000000000 --- a/.github/codecov.yml +++ /dev/null @@ -1,3 +0,0 @@ -codecov: - ignore: - - "org/kohsuke/github/extras/okhtp3/ObsoleteUrlFactory.java" diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..b54ee1fa97 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,7 @@ +ignore: + - "**/extras/okhttp3/ObsoleteUrlFactory**" + - "**/extras/OkHttpConnector" + - "**/extras/OkHttp3Connector" + - "**/example/**" + - "**/github/EnforcementLevel" + diff --git a/pom.xml b/pom.xml index f5f9f061f3..27a0b6cd38 100644 --- a/pom.xml +++ b/pom.xml @@ -110,17 +110,6 @@ jacoco.surefire.argLine - - - org/kohsuke/github/extras/okhtp3/ObsoleteUrlFactory.* - org/kohsuke/github/extras/okhtp3/ObsoleteUrlFactory$*.* - - org/kohsuke/github/example/** - - org/kohsuke/github/extras/OkHttp3Connector.* - org/kohsuke/github/EnforcementLevel.* - org/kohsuke/github/GHPerson$1.* - @@ -171,6 +160,7 @@ + org.kohsuke.github.extras.OkHttpConnector org.kohsuke.github.extras.OkHttp3Connector org.kohsuke.github.EnforcementLevel org.kohsuke.github.GHPerson.1 diff --git a/src/main/java/org/kohsuke/github/GitHubClient.java b/src/main/java/org/kohsuke/github/GitHubClient.java index 9ba5b91026..4e66de560e 100644 --- a/src/main/java/org/kohsuke/github/GitHubClient.java +++ b/src/main/java/org/kohsuke/github/GitHubClient.java @@ -141,10 +141,9 @@ public boolean isCredentialValid() { getRateLimit(); return true; } catch (IOException e) { - if (LOGGER.isLoggable(FINE)) - LOGGER.log(FINE, - "Exception validating credentials on " + getApiUrl() + " with login '" + login + "' " + e, - e); + LOGGER.log(FINE, + "Exception validating credentials on " + getApiUrl() + " with login '" + login + "' " + e, + e); return false; } } @@ -384,11 +383,7 @@ public GitHubResponse sendRequest(GitHubRequest request, @CheckForNull Gi GitHubResponse.ResponseInfo responseInfo = null; try { try { - if (LOGGER.isLoggable(FINE)) { - LOGGER.log(FINE, - "GitHub API request [" + (login == null ? "anonymous" : login) + "]: " - + request.method() + " " + request.url().toString()); - } + logRequest(request); rateLimitChecker.checkRateLimit(this, request); responseInfo = getResponseInfo(request); @@ -424,6 +419,12 @@ public GitHubResponse sendRequest(GitHubRequest request, @CheckForNull Gi throw new GHIOException("Ran out of retries for URL: " + request.url().toString()); } + private void logRequest(@Nonnull final GitHubRequest request) { + LOGGER.log(FINE, + () -> "GitHub API request [" + (login == null ? "anonymous" : login) + "]: " + request.method() + " " + + request.url().toString()); + } + @Nonnull protected abstract GitHubResponse.ResponseInfo getResponseInfo(GitHubRequest request) throws IOException; @@ -442,14 +443,9 @@ private static GitHubResponse createResponse(@Nonnull GitHubResponse.Resp // statistics - See https://developer.github.com/v3/repos/statistics/#a-word-about-caching // fork creation - See https://developer.github.com/v3/repos/forks/#create-a-fork - if (responseInfo.url().toString().endsWith("/forks")) { - LOGGER.log(INFO, "The fork is being created. Please try again in 5 seconds."); - } else if (responseInfo.url().toString().endsWith("/statistics")) { - LOGGER.log(INFO, "The statistics are being generated. Please try again in 5 seconds."); - } else { - LOGGER.log(INFO, - "Received 202 from " + responseInfo.url().toString() + " . Please try again in 5 seconds."); - } + LOGGER.log(INFO, + "Received HTTP_ACCEPTED(202) from " + responseInfo.url().toString() + + " . Please try again in 5 seconds."); // Maybe throw an exception instead? } else if (handler != null) { body = handler.apply(responseInfo); @@ -562,9 +558,7 @@ private void noteRateLimit(@Nonnull GitHubResponse.ResponseInfo responseInfo) { GHRateLimit.Record observed = new GHRateLimit.Record(limit, remaining, reset, responseInfo); updateRateLimit(GHRateLimit.fromRecord(observed, responseInfo.request().rateLimitTarget())); } catch (NumberFormatException | NullPointerException e) { - if (LOGGER.isLoggable(FINEST)) { - LOGGER.log(FINEST, "Missing or malformed X-RateLimit header: ", e); - } + LOGGER.log(FINEST, "Missing or malformed X-RateLimit header: ", e); } } diff --git a/src/test/java/org/kohsuke/github/GitHubConnectionTest.java b/src/test/java/org/kohsuke/github/GitHubConnectionTest.java index 98be781faf..f28f6bac98 100644 --- a/src/test/java/org/kohsuke/github/GitHubConnectionTest.java +++ b/src/test/java/org/kohsuke/github/GitHubConnectionTest.java @@ -10,11 +10,7 @@ import java.util.HashMap; import java.util.Map; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.*; /** * Unit test for {@link GitHub}. @@ -164,10 +160,24 @@ public void testGitHubIsApiUrlValid() throws IOException { // GitHub hub = GitHub.connectAnonymously(); GitHub hub = GitHub.connectToEnterpriseAnonymously(mockGitHub.apiServer().baseUrl()); + hub.checkApiUrlValidity(); try { hub.checkApiUrlValidity(); + fail(); } catch (IOException ioe) { - assertTrue(ioe.getMessage().contains("private mode enabled")); + assertThat(ioe.getMessage(), containsString("doesn't look like GitHub API URL")); + } + try { + hub.checkApiUrlValidity(); + fail(); + } catch (IOException ioe) { + assertThat(ioe.getMessage(), containsString("private mode enabled")); + } + try { + hub.getClient().requireCredential(); + fail(); + } catch (Exception e) { + assertThat(e.getMessage(), containsString("This operation requires a credential")); } } diff --git a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/__files/-2.json b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/__files/-2.json new file mode 100644 index 0000000000..08bb7e9f09 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/__files/-2.json @@ -0,0 +1,33 @@ +{ + "current_user_url": "https://api.github.com/user", + "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}", + "authorizations_url": "https://api.github.com/authorizations", + "code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}", + "commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}", + "emails_url": "https://api.github.com/user/emails", + "emojis_url": "https://api.github.com/emojis", + "events_url": "https://api.github.com/events", + "feeds_url": "https://api.github.com/feeds", + "followers_url": "https://api.github.com/user/followers", + "following_url": "https://api.github.com/user/following{/target}", + "gists_url": "https://api.github.com/gists{/gist_id}", + "hub_url": "https://api.github.com/hub", + "issue_search_url": "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}", + "issues_url": "https://api.github.com/issues", + "keys_url": "https://api.github.com/user/keys", + "label_search_url": "https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}", + "notifications_url": "https://api.github.com/notifications", + "organization_url": "https://api.github.com/orgs/{org}", + "organization_repositories_url": "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}", + "organization_teams_url": "https://api.github.com/orgs/{org}/teams", + "public_gists_url": "https://api.github.com/gists/public", + "repository_url": "https://api.github.com/repos/{owner}/{repo}", + "repository_search_url": "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}", + "current_user_repositories_url": "https://api.github.com/user/repos{?type,page,per_page,sort}", + "starred_url": "https://api.github.com/user/starred{/owner}{/repo}", + "starred_gists_url": "https://api.github.com/gists/starred", + "user_url": "https://api.github.com/users/{user}", + "user_organizations_url": "https://api.github.com/user/orgs", + "user_repositories_url": "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}", + "user_search_url": "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}" +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-1.json b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-1.json index d78254c96b..dd0e0322ea 100644 --- a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-1.json +++ b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-1.json @@ -26,7 +26,6 @@ "Accept", "Accept-Encoding, Accept, X-Requested-With" ], - "ETag": "W/\"323592c0d9feaab7a8e4a4e2a555feec\"", "X-GitHub-Media-Type": "unknown, github.v3", "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", "Access-Control-Allow-Origin": "*", @@ -41,5 +40,8 @@ }, "uuid": "2ce6df61-378a-43bd-9d37-d0851f8699bf", "persistent": true, + "scenarioName": "scenario-1", + "requiredScenarioState": "Started", + "newScenarioState": "scenario-1-step-2", "insertionIndex": 1 } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.1.json b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.1.json new file mode 100644 index 0000000000..47fc996b2f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.1.json @@ -0,0 +1,47 @@ +{ + "id": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "name": "", + "request": { + "url": "/", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "-2.json", + "headers": { + "Date": "Wed, 26 Feb 2020 03:55:33 GMT", + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "200 OK", + "X-RateLimit-Limit": "60", + "X-RateLimit-Remaining": "58", + "X-RateLimit-Reset": "1582692906", + "Cache-Control": "public, max-age=60, s-maxage=60", + "Vary": [ + "Accept", + "Accept-Encoding, Accept, X-Requested-With" + ], + "X-GitHub-Media-Type": "unknown, github.v3", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "1; mode=block", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "EE6F:3AF2:5C10D:6DDAD:5E55EC35" + } + }, + "uuid": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "persistent": true, + "scenarioName": "scenario-1", + "requiredScenarioState": "scenario-1-step-2.1", + "newScenarioState": "scenario-1-step-3", + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.json b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.json new file mode 100644 index 0000000000..2a1044febe --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-2.json @@ -0,0 +1,47 @@ +{ + "id": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "name": "", + "request": { + "url": "/", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "-2.json", + "headers": { + "Date": "Wed, 26 Feb 2020 03:55:33 GMT", + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "200 OK", + "X-RateLimit-Limit": "60", + "X-RateLimit-Remaining": "58", + "X-RateLimit-Reset": "1582692906", + "Cache-Control": "public, max-age=60, s-maxage=60", + "Vary": [ + "Accept", + "Accept-Encoding, Accept, X-Requested-With" + ], + "X-GitHub-Media-Type": "unknown, github.v3", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "1; mode=block", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "EE6F:3AF2:5C10D:6DDAD:5E55EC35" + } + }, + "uuid": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "persistent": true, + "scenarioName": "scenario-1", + "requiredScenarioState": "scenario-1-step-2", + "newScenarioState": "scenario-1-step-2.1", + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-3.json b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-3.json new file mode 100644 index 0000000000..d3e7c598df --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GitHubConnectionTest/wiremock/testGitHubIsApiUrlValid/mappings/-3.json @@ -0,0 +1,47 @@ +{ + "id": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "name": "", + "request": { + "url": "/", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" + } + } + }, + "response": { + "status": 401, + "body": "{}", + "headers": { + "Date": "Wed, 26 Feb 2020 03:55:33 GMT", + "Content-Type": "application/json; charset=utf-8", + "Server": "GitHub.com", + "Status": "401 NOT_AUTHORIZED", + "X-RateLimit-Limit": "60", + "X-RateLimit-Remaining": "58", + "X-RateLimit-Reset": "1582692906", + "Cache-Control": "public, max-age=60, s-maxage=60", + "Vary": [ + "Accept", + "Accept-Encoding, Accept, X-Requested-With" + ], + "X-GitHub-Media-Type": "unknown, github.v3", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "1; mode=block", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "EE6F:3AF2:5C10D:6DDAD:5E55EC35" + } + }, + "uuid": "2ce6df61-378a-43bd-9d37-d0851f8699bf", + "persistent": true, + "scenarioName": "scenario-1", + "requiredScenarioState": "scenario-1-step-3", + "newScenarioState": "scenario-1-step-3", + "insertionIndex": 1 +} \ No newline at end of file