Skip to content

Commit 7fb89a1

Browse files
committed
Merge remote-tracking branch 'origin/master' into bump-ghapi
2 parents 03d36c3 + 01cb1ac commit 7fb89a1

File tree

8 files changed

+105
-16
lines changed

8 files changed

+105
-16
lines changed

.github/workflows/cd.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ jobs:
4343
if: needs.validate.outputs.should_release == 'true'
4444
steps:
4545
- name: Check out
46-
uses: actions/checkout@v2.3.4
46+
uses: actions/checkout@v3.0.2
4747
with:
4848
fetch-depth: 0
4949
- name: Set up JDK 8
50-
uses: actions/setup-java@v2
50+
uses: actions/setup-java@v3
5151
with:
5252
distribution: 'adopt'
5353
java-version: 8

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildPlugin(configurations: [
22
[ platform: "linux", jdk: "8"],
33
[ platform: "windows", jdk: "8"],
4-
[ platform: "linux", jdk: "11", javaLevel: "8" ]
4+
[ platform: "linux", jdk: "11" ]
55
])

docs/github-app.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ credentials:
109109

110110
== Configuring the github organization folder
111111

112-
See the link:https://docs.cloudbees.com/docs/admin-resources/latest/plugins/github-branch-source[main documentation]
112+
See the link:https://docs.cloudbees.com/docs/cloudbees-ci/latest/cloud-admin-guide/github-branch-source-plugin[main documentation]
113113
for how to create a GitHub folder.
114114

115115
- Load the folders configuration page

pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
<dependency>
7272
<groupId>com.github.tomakehurst</groupId>
7373
<artifactId>wiremock-jre8-standalone</artifactId>
74-
<version>2.32.0</version>
74+
<version>2.33.2</version>
7575
<scope>test</scope>
7676
</dependency>
7777
<dependency>
@@ -114,6 +114,10 @@
114114
<artifactId>workflow-cps-global-lib</artifactId>
115115
<scope>test</scope>
116116
</dependency>
117+
<dependency>
118+
<groupId>io.jenkins.plugins</groupId>
119+
<artifactId>okhttp-api</artifactId>
120+
</dependency>
117121
</dependencies>
118122
<dependencyManagement>
119123
<dependencies>
@@ -136,7 +140,7 @@
136140
<plugin>
137141
<groupId>com.diffplug.spotless</groupId>
138142
<artifactId>spotless-maven-plugin</artifactId>
139-
<version>2.21.0</version>
143+
<version>2.22.4</version>
140144
<executions>
141145
<execution>
142146
<id>spotless-check</id>

src/main/java/org/jenkinsci/plugins/github_branch_source/ApiRateLimitChecker.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
import hudson.model.TaskListener;
77
import hudson.util.LogTaskListener;
88
import java.io.IOException;
9+
import java.util.List;
910
import java.util.Objects;
1011
import java.util.Random;
1112
import java.util.concurrent.TimeUnit;
1213
import java.util.logging.Level;
1314
import java.util.logging.Logger;
15+
import org.apache.commons.lang.StringUtils;
1416
import org.jenkinsci.plugins.github.config.GitHubServerConfig;
1517
import org.kohsuke.github.GHRateLimit;
1618
import org.kohsuke.github.GitHub;
@@ -231,13 +233,22 @@ protected boolean checkRateLimit(GHRateLimit.Record rateLimitRecord, long count)
231233
throws InterruptedException {
232234
LocalChecker checker = getLocalChecker();
233235
if (checker == null) {
234-
// If a checker was not configured for this thread, try our best and continue.
235-
configureThreadLocalChecker(
236-
new LogTaskListener(LOGGER, Level.INFO), GitHubServerConfig.GITHUB_URL);
236+
// If a checker was not configured for this thread, try our best by attempting to get the
237+
// URL from the first configured GitHub endpoint, else default to the public endpoint.
238+
// NOTE: Defaulting to the public GitHub endpoint is insufficient for those using GitHub
239+
// enterprise as it forces rate limit checking in those cases.
240+
String apiUrl = GitHubServerConfig.GITHUB_URL;
241+
List<Endpoint> endpoints = GitHubConfiguration.get().getEndpoints();
242+
if (endpoints.size() > 0 && !StringUtils.isBlank(endpoints.get(0).getApiUri())) {
243+
apiUrl = endpoints.get(0).getApiUri();
244+
}
245+
configureThreadLocalChecker(new LogTaskListener(LOGGER, Level.INFO), apiUrl);
237246
checker = getLocalChecker();
238247
checker.writeLog(
239248
"LocalChecker for rate limit was not set for this thread. "
240-
+ "Configured using system settings.");
249+
+ "Configured using system settings with API URL '"
250+
+ apiUrl
251+
+ "'.");
241252
}
242253
return checker.checkRateLimit(rateLimitRecord, count);
243254
}

src/main/java/org/jenkinsci/plugins/github_branch_source/Connector.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import hudson.security.ACL;
5151
import hudson.util.FormValidation;
5252
import hudson.util.ListBoxModel;
53+
import io.jenkins.plugins.okhttp.api.JenkinsOkHttpClient;
5354
import java.io.File;
5455
import java.io.IOException;
5556
import java.net.HttpURLConnection;
@@ -100,7 +101,8 @@ public class Connector {
100101

101102
private static final Random ENTROPY = new Random();
102103
private static final String SALT = Long.toHexString(ENTROPY.nextLong());
103-
private static final OkHttpClient baseClient = new OkHttpClient();
104+
private static final OkHttpClient baseClient =
105+
JenkinsOkHttpClient.newClientBuilder(new OkHttpClient()).build();
104106

105107
private Connector() {
106108
throw new IllegalAccessError("Utility class");
@@ -544,7 +546,8 @@ public void onError(IOException e, HttpURLConnection uc) throws IOException {
544546

545547
/**
546548
* Alternative to {@link GitHub#isCredentialValid()} that relies on the cached user object in the
547-
* {@link GitHub} instance and hence reduced rate limit consumption.
549+
* {@link GitHub} instance and hence reduced rate limit consumption. It also uses a separate
550+
* endpoint if rate limit checking is disabled.
548551
*
549552
* @param gitHub the instance to check.
550553
* @return {@code true} if the credentials are valid.
@@ -554,7 +557,15 @@ static boolean isCredentialValid(GitHub gitHub) {
554557
return true;
555558
} else {
556559
try {
557-
gitHub.getRateLimit();
560+
// If rate limit checking is disabled, use the meta endpoint instead
561+
// of the rate limiting endpoint
562+
GitHubConfiguration gitHubConfiguration = GitHubConfiguration.get();
563+
if (gitHubConfiguration != null
564+
&& gitHubConfiguration.getApiRateLimitChecker() == ApiRateLimitChecker.NoThrottle) {
565+
gitHub.getMeta();
566+
} else {
567+
gitHub.getRateLimit();
568+
}
558569
return true;
559570
} catch (IOException e) {
560571
if (LOGGER.isLoggable(FINE)) {

src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMNavigator.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import hudson.util.ListBoxModel;
4747
import java.io.FileNotFoundException;
4848
import java.io.IOException;
49+
import java.net.MalformedURLException;
4950
import java.util.ArrayList;
5051
import java.util.Collections;
5152
import java.util.EnumSet;
@@ -1574,15 +1575,21 @@ public List<Action> retrieveActions(
15741575
// trusted source
15751576
listener.getLogger().printf("Looking up details of %s...%n", getRepoOwner());
15761577
List<Action> result = new ArrayList<>();
1578+
String apiUri = Util.fixEmptyAndTrim(getApiUri());
15771579
StandardCredentials credentials =
1578-
Connector.lookupScanCredentials((Item) owner, getApiUri(), credentialsId);
1579-
GitHub hub = Connector.connect(getApiUri(), credentials);
1580+
Connector.lookupScanCredentials((Item) owner, apiUri, credentialsId);
1581+
GitHub hub = Connector.connect(apiUri, credentials);
1582+
boolean privateMode = determinePrivateMode(apiUri);
15801583
try {
15811584
Connector.configureLocalRateLimitChecker(listener, hub);
15821585
GHUser u = hub.getUser(getRepoOwner());
15831586
String objectUrl = u.getHtmlUrl() == null ? null : u.getHtmlUrl().toExternalForm();
15841587
result.add(new ObjectMetadataAction(Util.fixEmpty(u.getName()), null, objectUrl));
1585-
result.add(new GitHubOrgMetadataAction(u));
1588+
if (privateMode) {
1589+
result.add(new GitHubOrgMetadataAction((String) null));
1590+
} else {
1591+
result.add(new GitHubOrgMetadataAction(u));
1592+
}
15861593
result.add(new GitHubLink("icon-github-logo", u.getHtmlUrl()));
15871594
if (objectUrl == null) {
15881595
listener.getLogger().println("Organization URL: unspecified");
@@ -1600,6 +1607,23 @@ public List<Action> retrieveActions(
16001607
}
16011608
}
16021609

1610+
private static boolean determinePrivateMode(String apiUri) {
1611+
if (apiUri == null || apiUri.equals(GitHubServerConfig.GITHUB_URL)) {
1612+
return false;
1613+
}
1614+
try {
1615+
GitHub.connectToEnterpriseAnonymously(apiUri).checkApiUrlValidity();
1616+
} catch (MalformedURLException e) {
1617+
// URL is bogus so there is never going to be an avatar - or anything else come to think of it
1618+
return true;
1619+
} catch (IOException e) {
1620+
if (e.getMessage().contains("private mode enabled")) {
1621+
return true;
1622+
}
1623+
}
1624+
return false;
1625+
}
1626+
16031627
/** {@inheritDoc} */
16041628
@Override
16051629
public void afterSave(@NonNull SCMNavigatorOwner owner) {

src/test/java/org/jenkinsci/plugins/github_branch_source/ApiRateLimitCheckerTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.logging.Logger;
2222
import java.util.stream.Stream;
2323
import org.jenkinsci.plugins.github.config.GitHubServerConfig;
24+
import org.junit.After;
2425
import org.junit.Before;
2526
import org.junit.Test;
2627
import org.kohsuke.github.GHRateLimit;
@@ -92,6 +93,11 @@ public void setUp() throws Exception {
9293
ApiRateLimitChecker.resetLocalChecker();
9394
}
9495

96+
@After
97+
public void tearDown() throws Exception {
98+
GitHubConfiguration.get().setEndpoints(new ArrayList<>());
99+
}
100+
95101
private void setupStubs(List<RateLimit> scenarios) throws Exception {
96102

97103
githubApi.stubFor(
@@ -187,6 +193,7 @@ public void NoCheckerConfigured() throws Exception {
187193
assertEquals(
188194
3,
189195
countOfOutputLinesContaining("LocalChecker for rate limit was not set for this thread."));
196+
assertEquals(3, countOfOutputLinesContaining("with API URL 'https://api.github.com'"));
190197
assertEquals(3, countOfOutputLines(m -> m.matches(".*[sS]leeping.*")));
191198
// github rate_limit endpoint should be contacted for ThrottleOnOver
192199
// rateLimit()
@@ -199,6 +206,38 @@ public void NoCheckerConfigured() throws Exception {
199206
assertEquals(initialRequestCount + 9, getRequestCount(githubApi));
200207
}
201208

209+
@Test
210+
public void NoCheckerConfiguredWithEndpoint() throws Exception {
211+
// set up scenarios
212+
List<RateLimit> scenarios = new ArrayList<>();
213+
long now = System.currentTimeMillis();
214+
int limit = 5000;
215+
scenarios.add(new RateLimit(limit, 30, new Date(now - 10000)));
216+
scenarios.add(new RateLimit(limit, limit, new Date(now - 8000)));
217+
scenarios.add(new RateLimit(limit, 20, new Date(now - 6000)));
218+
scenarios.add(new RateLimit(limit, limit, new Date(now - 4000)));
219+
scenarios.add(new RateLimit(limit, 10, new Date(now - 2000)));
220+
scenarios.add(new RateLimit(limit, limit, new Date(now)));
221+
setupStubs(scenarios);
222+
223+
List<Endpoint> endpoints = new ArrayList<>();
224+
endpoints.add(new Endpoint("https://git.company.com/api/v3", "Company GitHub"));
225+
endpoints.add(new Endpoint("https://git2.company.com/api/v3", "Company GitHub 2"));
226+
GitHubConfiguration.get().setEndpoints(endpoints);
227+
228+
GitHubConfiguration.get().setApiRateLimitChecker(ApiRateLimitChecker.NoThrottle);
229+
github.getMeta();
230+
231+
assertEquals(
232+
1,
233+
countOfOutputLinesContaining("LocalChecker for rate limit was not set for this thread."));
234+
assertEquals(1, countOfOutputLinesContaining("with API URL 'https://git.company.com/api/v3'"));
235+
// ThrottleOnOver should not be used for NoThrottle since it is not the public GitHub endpoint
236+
assertEquals(0, countOfOutputLinesContaining("ThrottleOnOver will be used instead"));
237+
238+
assertEquals(initialRequestCount + 2, getRequestCount(githubApi));
239+
}
240+
202241
/**
203242
* Verify that the throttle does not happen in OnOver throttle when none of the quota has been
204243
* used

0 commit comments

Comments
 (0)