Skip to content

Commit 5257e36

Browse files
author
Steve Riesenberg
committed
Update SaganApi to work with Contentful backend
Also fixed an issue with incorrect referenceDocUrl for Antora with SNAPSHOT versions. Closes gh-12575
1 parent 0421e25 commit 5257e36

File tree

7 files changed

+270
-9
lines changed

7 files changed

+270
-9
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2020-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.gradle.github.user;
17+
18+
import java.io.IOException;
19+
20+
import com.google.gson.Gson;
21+
import okhttp3.Interceptor;
22+
import okhttp3.OkHttpClient;
23+
import okhttp3.Request;
24+
import okhttp3.Response;
25+
26+
/**
27+
* @author Steve Riesenberg
28+
*/
29+
public class GitHubUserApi {
30+
private String baseUrl = "https://api.github.com";
31+
32+
private final OkHttpClient httpClient;
33+
private Gson gson = new Gson();
34+
35+
public GitHubUserApi(String gitHubAccessToken) {
36+
this.httpClient = new OkHttpClient.Builder()
37+
.addInterceptor(new AuthorizationInterceptor(gitHubAccessToken))
38+
.build();
39+
}
40+
41+
public void setBaseUrl(String baseUrl) {
42+
this.baseUrl = baseUrl;
43+
}
44+
45+
/**
46+
* Retrieve a GitHub user by the personal access token.
47+
*
48+
* @return The GitHub user
49+
*/
50+
public User getUser() {
51+
String url = this.baseUrl + "/user";
52+
Request request = new Request.Builder().url(url).get().build();
53+
try (Response response = this.httpClient.newCall(request).execute()) {
54+
if (!response.isSuccessful()) {
55+
throw new RuntimeException(
56+
String.format("Unable to retrieve GitHub user." +
57+
" Please check the personal access token and try again." +
58+
" Got response %s", response));
59+
}
60+
return this.gson.fromJson(response.body().charStream(), User.class);
61+
} catch (IOException ex) {
62+
throw new RuntimeException("Unable to retrieve GitHub user.", ex);
63+
}
64+
}
65+
66+
private static class AuthorizationInterceptor implements Interceptor {
67+
private final String token;
68+
69+
public AuthorizationInterceptor(String token) {
70+
this.token = token;
71+
}
72+
73+
@Override
74+
public Response intercept(Chain chain) throws IOException {
75+
Request request = chain.request().newBuilder()
76+
.addHeader("Authorization", "Bearer " + this.token)
77+
.build();
78+
79+
return chain.proceed(request);
80+
}
81+
}
82+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.springframework.gradle.github.user;
2+
3+
/**
4+
* @author Steve Riesenberg
5+
*/
6+
public class User {
7+
private Long id;
8+
private String login;
9+
private String name;
10+
private String url;
11+
12+
public Long getId() {
13+
return this.id;
14+
}
15+
16+
public void setId(Long id) {
17+
this.id = id;
18+
}
19+
20+
public String getLogin() {
21+
return this.login;
22+
}
23+
24+
public void setLogin(String login) {
25+
this.login = login;
26+
}
27+
28+
public String getName() {
29+
return this.name;
30+
}
31+
32+
public void setName(String name) {
33+
this.name = name;
34+
}
35+
36+
public String getUrl() {
37+
return this.url;
38+
}
39+
40+
public void setUrl(String url) {
41+
this.url = url;
42+
}
43+
44+
@Override
45+
public String toString() {
46+
return "User{" +
47+
"id=" + id +
48+
", login='" + login + '\'' +
49+
", name='" + name + '\'' +
50+
", url='" + url + '\'' +
51+
'}';
52+
}
53+
}

buildSrc/src/main/java/org/springframework/gradle/sagan/SaganApi.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
* Implements necessary calls to the Sagan API See https://spring.io/restdocs/index.html
2727
*/
2828
public class SaganApi {
29-
private String baseUrl = "https://spring.io/api";
29+
private String baseUrl = "https://api.spring.io";
3030

3131
private OkHttpClient client;
3232
private Gson gson = new Gson();
3333

34-
public SaganApi(String gitHubToken) {
34+
public SaganApi(String username, String gitHubToken) {
3535
this.client = new OkHttpClient.Builder()
36-
.addInterceptor(new BasicInterceptor("not-used", gitHubToken))
36+
.addInterceptor(new BasicInterceptor(username, gitHubToken))
3737
.build();
3838
}
3939

buildSrc/src/main/java/org/springframework/gradle/sagan/SaganCreateReleaseTask.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import org.gradle.api.tasks.Input;
2121
import org.gradle.api.tasks.TaskAction;
2222

23+
import org.springframework.gradle.github.user.GitHubUserApi;
24+
import org.springframework.gradle.github.user.User;
25+
2326
public class SaganCreateReleaseTask extends DefaultTask {
2427

2528
@Input
@@ -35,11 +38,22 @@ public class SaganCreateReleaseTask extends DefaultTask {
3538

3639
@TaskAction
3740
public void saganCreateRelease() {
38-
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
41+
GitHubUserApi github = new GitHubUserApi(this.gitHubAccessToken);
42+
User user = github.getUser();
43+
44+
// Antora reference docs URLs for snapshots do not contain -SNAPSHOT
45+
String referenceDocUrl = this.referenceDocUrl;
46+
if (this.version.endsWith("-SNAPSHOT")) {
47+
referenceDocUrl = this.referenceDocUrl
48+
.replace("{version}", this.version)
49+
.replace("-SNAPSHOT", "");
50+
}
51+
52+
SaganApi sagan = new SaganApi(user.getLogin(), this.gitHubAccessToken);
3953
Release release = new Release();
4054
release.setVersion(this.version);
4155
release.setApiDocUrl(this.apiDocUrl);
42-
release.setReferenceDocUrl(this.referenceDocUrl);
56+
release.setReferenceDocUrl(referenceDocUrl);
4357
sagan.createReleaseForProject(release, this.projectName);
4458
}
4559

buildSrc/src/main/java/org/springframework/gradle/sagan/SaganDeleteReleaseTask.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import org.gradle.api.tasks.Input;
2121
import org.gradle.api.tasks.TaskAction;
2222

23+
import org.springframework.gradle.github.user.GitHubUserApi;
24+
import org.springframework.gradle.github.user.User;
25+
2326
public class SaganDeleteReleaseTask extends DefaultTask {
2427

2528
@Input
@@ -31,7 +34,10 @@ public class SaganDeleteReleaseTask extends DefaultTask {
3134

3235
@TaskAction
3336
public void saganCreateRelease() {
34-
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
37+
GitHubUserApi github = new GitHubUserApi(this.gitHubAccessToken);
38+
User user = github.getUser();
39+
40+
SaganApi sagan = new SaganApi(user.getLogin(), this.gitHubAccessToken);
3541
sagan.deleteReleaseForProject(this.version, this.projectName);
3642
}
3743

buildSrc/src/test/java/io/spring/gradle/convention/sagan/SaganApiTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class SaganApiTests {
4242
public void setup() throws Exception {
4343
this.server = new MockWebServer();
4444
this.server.start();
45-
this.sagan = new SaganApi("mock-oauth-token");
45+
this.sagan = new SaganApi("user", "mock-oauth-token");
4646
this.baseUrl = this.server.url("/api").toString();
4747
this.sagan.setBaseUrl(this.baseUrl);
4848
}
@@ -63,7 +63,7 @@ public void createWhenValidThenNoException() throws Exception {
6363
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
6464
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases");
6565
assertThat(request.getMethod()).isEqualToIgnoringCase("post");
66-
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
66+
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic dXNlcjptb2NrLW9hdXRoLXRva2Vu");
6767
assertThat(request.getBody().readString(Charset.defaultCharset())).isEqualToIgnoringWhitespace("{\n" +
6868
" \"version\":\"5.6.0-SNAPSHOT\",\n" +
6969
" \"current\":false,\n" +
@@ -79,7 +79,7 @@ public void deleteWhenValidThenNoException() throws Exception {
7979
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
8080
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases/5.6.0-SNAPSHOT");
8181
assertThat(request.getMethod()).isEqualToIgnoringCase("delete");
82-
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
82+
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic dXNlcjptb2NrLW9hdXRoLXRva2Vu");
8383
assertThat(request.getBody().readString(Charset.defaultCharset())).isEmpty();
8484
}
8585
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2020-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.gradle.github.user;
17+
18+
import okhttp3.mockwebserver.MockResponse;
19+
import okhttp3.mockwebserver.MockWebServer;
20+
import org.junit.jupiter.api.AfterEach;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
26+
27+
/**
28+
* @author Steve Riesenberg
29+
*/
30+
public class GitHubUserApiTests {
31+
private GitHubUserApi gitHubUserApi;
32+
33+
private MockWebServer server;
34+
35+
private String baseUrl;
36+
37+
@BeforeEach
38+
public void setup() throws Exception {
39+
this.server = new MockWebServer();
40+
this.server.start();
41+
this.baseUrl = this.server.url("/api").toString();
42+
this.gitHubUserApi = new GitHubUserApi("mock-oauth-token");
43+
this.gitHubUserApi.setBaseUrl(this.baseUrl);
44+
}
45+
46+
@AfterEach
47+
public void cleanup() throws Exception {
48+
this.server.shutdown();
49+
}
50+
51+
@Test
52+
public void getUserWhenValidParametersThenSuccess() {
53+
// @formatter:off
54+
String responseJson = "{\n" +
55+
" \"avatar_url\": \"https://avatars.githubusercontent.com/u/583231?v=4\",\n" +
56+
" \"bio\": null,\n" +
57+
" \"blog\": \"https://github.blog\",\n" +
58+
" \"company\": \"@github\",\n" +
59+
" \"created_at\": \"2011-01-25T18:44:36Z\",\n" +
60+
" \"email\": null,\n" +
61+
" \"events_url\": \"https://api.github.com/users/octocat/events{/privacy}\",\n" +
62+
" \"followers\": 8481,\n" +
63+
" \"followers_url\": \"https://api.github.com/users/octocat/followers\",\n" +
64+
" \"following\": 9,\n" +
65+
" \"following_url\": \"https://api.github.com/users/octocat/following{/other_user}\",\n" +
66+
" \"gists_url\": \"https://api.github.com/users/octocat/gists{/gist_id}\",\n" +
67+
" \"gravatar_id\": \"\",\n" +
68+
" \"hireable\": null,\n" +
69+
" \"html_url\": \"https://github.com/octocat\",\n" +
70+
" \"id\": 583231,\n" +
71+
" \"location\": \"San Francisco\",\n" +
72+
" \"login\": \"octocat\",\n" +
73+
" \"name\": \"The Octocat\",\n" +
74+
" \"node_id\": \"MDQ6VXNlcjU4MzIzMQ==\",\n" +
75+
" \"organizations_url\": \"https://api.github.com/users/octocat/orgs\",\n" +
76+
" \"public_gists\": 8,\n" +
77+
" \"public_repos\": 8,\n" +
78+
" \"received_events_url\": \"https://api.github.com/users/octocat/received_events\",\n" +
79+
" \"repos_url\": \"https://api.github.com/users/octocat/repos\",\n" +
80+
" \"site_admin\": false,\n" +
81+
" \"starred_url\": \"https://api.github.com/users/octocat/starred{/owner}{/repo}\",\n" +
82+
" \"subscriptions_url\": \"https://api.github.com/users/octocat/subscriptions\",\n" +
83+
" \"twitter_username\": null,\n" +
84+
" \"type\": \"User\",\n" +
85+
" \"updated_at\": \"2023-02-25T12:14:58Z\",\n" +
86+
" \"url\": \"https://api.github.com/users/octocat\"\n" +
87+
"}";
88+
// @formatter:on
89+
this.server.enqueue(new MockResponse().setBody(responseJson));
90+
91+
User user = this.gitHubUserApi.getUser();
92+
assertThat(user.getId()).isEqualTo(583231);
93+
assertThat(user.getLogin()).isEqualTo("octocat");
94+
assertThat(user.getName()).isEqualTo("The Octocat");
95+
assertThat(user.getUrl()).isEqualTo("https://api.github.com/users/octocat");
96+
}
97+
98+
@Test
99+
public void getUserWhenErrorResponseThenException() {
100+
this.server.enqueue(new MockResponse().setResponseCode(400));
101+
// @formatter:off
102+
assertThatExceptionOfType(RuntimeException.class)
103+
.isThrownBy(() -> this.gitHubUserApi.getUser());
104+
// @formatter:on
105+
}
106+
}

0 commit comments

Comments
 (0)