Skip to content

Commit

Permalink
Add support for Github Enterprise URL with optional /v3
Browse files Browse the repository at this point in the history
Add methods to generate a valid Github URL for both V3 and graphql endpoints on both Github and Github Enterprise installations
  • Loading branch information
kennyko committed Mar 26, 2020
1 parent 8f9c273 commit 7601a40
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void load(CoreExtension.Context context) {
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_URL)
.category(PULL_REQUEST_CATEGORY_LABEL).subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL)
.onQualifiers(Qualifiers.APP).name("The API URL for a GitHub instance").description(
"The API url for a GitHub instance. https://api.github.com/ for github.com, https://github.saobby.my.eu.orgpany.com/api/ when using GitHub Enterprise")
"The API url for a GitHub instance. https://api.github.com/ for github.com, https://github.saobby.my.eu.orgpany.com/api/v3 when using GitHub Enterprise")
.type(PropertyType.STRING).defaultValue("https://api.github.com").build(),

PropertyDefinition.builder(PullRequestBuildStatusDecorator.PULL_REQUEST_COMMENT_SUMMARY_ENABLED).category(PULL_REQUEST_CATEGORY_LABEL).subCategory(GENERAL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public RepositoryAuthenticationToken getInstallationToken(String apiUrl, String

ObjectMapper objectMapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

URLConnection appConnection = urlProvider.createUrlConnection(apiUrl + (apiUrl.endsWith("api") ? "/v3" : (apiUrl.endsWith("api/") ? "v3" : "")) + "/app/installations");
URLConnection appConnection = urlProvider.createUrlConnection(getV3Url(apiUrl) + "/app/installations");
appConnection.setRequestProperty(ACCEPT_HEADER, APP_PREVIEW_ACCEPT_HEADER);
appConnection.setRequestProperty(AUTHORIZATION_HEADER, BEARER_AUTHORIZATION_HEADER_PREFIX + jwtToken);

Expand Down Expand Up @@ -131,6 +131,15 @@ public RepositoryAuthenticationToken getInstallationToken(String apiUrl, String
"No token could be found with access to the requested repository with the given application ID and key");
}

private static String getV3Url(String apiUrl) {
if (apiUrl.endsWith("/")) {
apiUrl = apiUrl.substring(0, apiUrl.length() - 1);
}
if (apiUrl.endsWith("/api")) {
apiUrl = apiUrl + "/v3";
}
return apiUrl;
}

private static PrivateKey createPrivateKey(String apiPrivateKey) throws IOException {
try (PEMParser pemParser = new PEMParser(new StringReader(apiPrivateKey))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public void createCheckRun(AnalysisDetails analysisDetails, UnifyConfiguration u


GraphQLRequestEntity graphQLRequestEntity =
graphqlProvider.createRequestBuilder().url(apiUrl + (apiUrl.endsWith("/") ? "graphql" : "/graphql")).headers(headers)
graphqlProvider.createRequestBuilder().url(getGraphqlUrl(apiUrl)).headers(headers)
.request(CreateCheckRun.class)
.arguments(new Arguments("createCheckRun", new Argument<>("input", repositoryInputObject)))
.requestMethod(GraphQLTemplate.GraphQLMethod.MUTATE).build();
Expand All @@ -174,6 +174,18 @@ public void createCheckRun(AnalysisDetails analysisDetails, UnifyConfiguration u
}
}

private static String getGraphqlUrl(String apiUrl) {
if (apiUrl.endsWith("/")) {
apiUrl = apiUrl.substring(0, apiUrl.length() - 1);
}
if (apiUrl.endsWith("/v3")) {
apiUrl = apiUrl.substring(0, apiUrl.length() - 3);
}
apiUrl = apiUrl + "/graphql";

return apiUrl;
}

private static CheckAnnotationLevel mapToGithubAnnotationLevel(String sonarqubeSeverity) {
switch (sonarqubeSeverity) {
case Severity.INFO:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ public void testTokenRetrievedHappyPathApiPathTrailingSlash() throws IOException
testTokenForUrl("apiUrl/api/", "apiUrl/api/v3/app/installations");
}

@Test
public void testTokenRetrievedHappyPathV3Path() throws IOException {
testTokenForUrl("apiUrl/api/v3", "apiUrl/api/v3/app/installations");
}

@Test
public void testTokenRetrievedHappyPathV3PathTrailingSlash() throws IOException {
testTokenForUrl("apiUrl/api/v3/", "apiUrl/api/v3/app/installations");
}

private void testTokenForUrl(String apiUrl, String fullUrl) throws IOException {
UrlConnectionProvider urlProvider = mock(UrlConnectionProvider.class);
Clock clock = Clock.fixed(Instant.ofEpochMilli(123456789L), ZoneId.of("UTC"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,36 @@ public void createCheckRunHappyPathOkStatus() throws IOException, GeneralSecurit
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain", "http://api.target.domain/graphql");
}

@Test
public void createCheckRunHappyPathOkStatusTrailingSlash() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain/", "http://api.target.domain/graphql");
}

@Test
public void createCheckRunHappyPathOkStatusApiPath() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain/api", "http://api.target.domain/api/graphql");
}

@Test
public void createCheckRunHappyPathOkStatusApiPathTrailingSlash() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain/api/", "http://api.target.domain/api/graphql");
}

@Test
public void createCheckRunHappyPathOkStatusV3Path() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain/api/v3", "http://api.target.domain/api/graphql");
}

@Test
public void createCheckRunHappyPathOkStatusV3PathTrailingSlash() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.OK, "http://api.target.domain/api/v3/", "http://api.target.domain/api/graphql");
}

@Test
public void createCheckRunHappyPathErrorStatus() throws IOException, GeneralSecurityException {
createCheckRunHappyPath(QualityGate.Status.ERROR, "http://abc.de/", "http://abc.de/graphql");
}


private void createCheckRunHappyPath(QualityGate.Status status, String basePath, String fullPath) throws IOException, GeneralSecurityException {
when(server.getPublicRootUrl()).thenReturn("http://sonar.server/root");

Expand Down

0 comments on commit 7601a40

Please sign in to comment.