Skip to content

Commit 1a08235

Browse files
committed
Add sagan(Create|Delete)Release
Closes gh-9577
1 parent eb47aa7 commit 1a08235

File tree

8 files changed

+508
-0
lines changed

8 files changed

+508
-0
lines changed

build.gradle

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ apply plugin: 'locks'
1616
apply plugin: 'io.spring.convention.root'
1717
apply plugin: 'org.jetbrains.kotlin.jvm'
1818
apply plugin: 'org.springframework.security.update-dependencies'
19+
apply plugin: 'org.springframework.security.sagan'
1920

2021
group = 'org.springframework.security'
2122
description = 'Spring Security'
@@ -28,6 +29,11 @@ repositories {
2829
mavenCentral()
2930
}
3031

32+
tasks.named("saganCreateRelease") {
33+
referenceDocUrl = "https://docs.spring.io/spring-security/site/docs/{version}/reference/html5/"
34+
apiDocUrl = "https://docs.spring.io/spring-security/site/docs/{version}/api/"
35+
}
36+
3137
updateDependenciesSettings {
3238
gitHub {
3339
organization = "spring-projects"

buildSrc/build.gradle

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ gradlePlugin {
4444
id = "org.springframework.security.update-dependencies"
4545
implementationClass = "org.springframework.security.convention.versions.UpdateDependenciesPlugin"
4646
}
47+
sagan {
48+
id = "org.springframework.security.sagan"
49+
implementationClass = "org.springframework.gradle.sagan.SaganPlugin"
50+
}
4751
}
4852
}
4953

@@ -54,6 +58,7 @@ configurations {
5458
}
5559

5660
dependencies {
61+
implementation 'com.google.code.gson:gson:2.8.6'
5762
implementation 'com.thaiopensource:trang:20091111'
5863
implementation 'net.sourceforge.saxon:saxon:9.1.0.8'
5964
implementation localGroovy()
@@ -78,6 +83,7 @@ dependencies {
7883
testImplementation 'org.assertj:assertj-core:3.13.2'
7984
testImplementation 'org.mockito:mockito-core:3.0.0'
8085
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
86+
testImplementation "com.squareup.okhttp3:mockwebserver:3.14.9"
8187
}
8288

8389

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2019-2020 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+
17+
package org.springframework.gradle.sagan;
18+
19+
import java.util.regex.Pattern;
20+
21+
/**
22+
* Domain object for creating a new release version.
23+
*/
24+
public class Release {
25+
private String version;
26+
27+
private ReleaseStatus status;
28+
29+
private boolean current;
30+
31+
private String referenceDocUrl;
32+
33+
private String apiDocUrl;
34+
35+
public String getVersion() {
36+
return version;
37+
}
38+
39+
public void setVersion(String version) {
40+
this.version = version;
41+
}
42+
43+
public ReleaseStatus getStatus() {
44+
return status;
45+
}
46+
47+
public void setStatus(ReleaseStatus status) {
48+
this.status = status;
49+
}
50+
51+
public boolean isCurrent() {
52+
return current;
53+
}
54+
55+
public void setCurrent(boolean current) {
56+
this.current = current;
57+
}
58+
59+
public String getReferenceDocUrl() {
60+
return referenceDocUrl;
61+
}
62+
63+
public void setReferenceDocUrl(String referenceDocUrl) {
64+
this.referenceDocUrl = referenceDocUrl;
65+
}
66+
67+
public String getApiDocUrl() {
68+
return apiDocUrl;
69+
}
70+
71+
public void setApiDocUrl(String apiDocUrl) {
72+
this.apiDocUrl = apiDocUrl;
73+
}
74+
75+
@Override
76+
public String toString() {
77+
return "Release{" +
78+
"version='" + version + '\'' +
79+
", status=" + status +
80+
", current=" + current +
81+
", referenceDocUrl='" + referenceDocUrl + '\'' +
82+
", apiDocUrl='" + apiDocUrl + '\'' +
83+
'}';
84+
}
85+
86+
public enum ReleaseStatus {
87+
/**
88+
* Unstable version with limited support
89+
*/
90+
SNAPSHOT,
91+
/**
92+
* Pre-Release version meant to be tested by the community
93+
*/
94+
PRERELEASE,
95+
/**
96+
* Release Generally Available on public artifact repositories and enjoying full support from maintainers
97+
*/
98+
GENERAL_AVAILABILITY;
99+
100+
private static final Pattern PRERELEASE_PATTERN = Pattern.compile("[A-Za-z0-9\\.\\-]+?(M|RC)\\d+");
101+
102+
private static final String SNAPSHOT_SUFFIX = "SNAPSHOT";
103+
104+
/**
105+
* Parse the ReleaseStatus from a String
106+
* @param version a project version
107+
* @return the release status for this version
108+
*/
109+
public static ReleaseStatus parse(String version) {
110+
if (version == null) {
111+
throw new IllegalArgumentException("version cannot be null");
112+
}
113+
if (version.endsWith(SNAPSHOT_SUFFIX)) {
114+
return SNAPSHOT;
115+
}
116+
if (PRERELEASE_PATTERN.matcher(version).matches()) {
117+
return PRERELEASE;
118+
}
119+
return GENERAL_AVAILABILITY;
120+
}
121+
}
122+
123+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2019-2020 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+
17+
package org.springframework.gradle.sagan;
18+
19+
import com.google.gson.Gson;
20+
import okhttp3.*;
21+
22+
import java.io.IOException;
23+
import java.util.Base64;
24+
25+
/**
26+
* Implements necessary calls to the Sagan API See https://github.com/spring-io/sagan/blob/master/sagan-site/src/docs/asciidoc/index.adoc
27+
*/
28+
public class SaganApi {
29+
private String baseUrl = "https://spring.io/api";
30+
31+
private OkHttpClient client;
32+
private Gson gson = new Gson();
33+
34+
public SaganApi(String gitHubToken) {
35+
this.client = new OkHttpClient.Builder()
36+
.addInterceptor(new BasicInterceptor("not-used", gitHubToken))
37+
.build();
38+
}
39+
40+
public void setBaseUrl(String baseUrl) {
41+
this.baseUrl = baseUrl;
42+
}
43+
44+
public void createReleaseForProject(Release release, String projectName) {
45+
String url = this.baseUrl + "/projects/" + projectName + "/releases";
46+
String releaseJsonString = gson.toJson(release);
47+
RequestBody body = RequestBody.create(MediaType.parse("application/json"), releaseJsonString);
48+
Request request = new Request.Builder()
49+
.url(url)
50+
.post(body)
51+
.build();
52+
try {
53+
Response response = this.client.newCall(request).execute();
54+
if (!response.isSuccessful()) {
55+
throw new RuntimeException("Could not create release " + release + ". Got response " + response);
56+
}
57+
} catch (IOException fail) {
58+
throw new RuntimeException("Could not create release " + release, fail);
59+
}
60+
}
61+
62+
public void deleteReleaseForProject(String release, String projectName) {
63+
String url = this.baseUrl + "/projects/" + projectName + "/releases/" + release;
64+
Request request = new Request.Builder()
65+
.url(url)
66+
.delete()
67+
.build();
68+
try {
69+
Response response = this.client.newCall(request).execute();
70+
if (!response.isSuccessful()) {
71+
throw new RuntimeException("Could not delete release " + release + ". Got response " + response);
72+
}
73+
} catch (IOException fail) {
74+
throw new RuntimeException("Could not delete release " + release, fail);
75+
}
76+
}
77+
78+
private static class BasicInterceptor implements Interceptor {
79+
80+
private final String token;
81+
82+
public BasicInterceptor(String username, String token) {
83+
this.token = Base64.getEncoder().encodeToString((username + ":" + token).getBytes());
84+
}
85+
86+
@Override
87+
public okhttp3.Response intercept(Chain chain) throws IOException {
88+
Request request = chain.request().newBuilder()
89+
.addHeader("Authorization", "Basic " + this.token).build();
90+
return chain.proceed(request);
91+
}
92+
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2019-2020 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+
17+
package org.springframework.gradle.sagan;
18+
19+
import org.gradle.api.DefaultTask;
20+
import org.gradle.api.tasks.Input;
21+
import org.gradle.api.tasks.TaskAction;
22+
23+
public class SaganCreateReleaseTask extends DefaultTask {
24+
25+
@Input
26+
private String gitHubAccessToken;
27+
@Input
28+
private String version;
29+
@Input
30+
private String apiDocUrl;
31+
@Input
32+
private String referenceDocUrl;
33+
@Input
34+
private String projectName;
35+
36+
@TaskAction
37+
public void saganCreateRelease() {
38+
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
39+
Release release = new Release();
40+
release.setVersion(this.version);
41+
release.setApiDocUrl(this.apiDocUrl);
42+
release.setReferenceDocUrl(this.referenceDocUrl);
43+
sagan.createReleaseForProject(release, this.projectName);
44+
}
45+
46+
public String getGitHubAccessToken() {
47+
return gitHubAccessToken;
48+
}
49+
50+
public void setGitHubAccessToken(String gitHubAccessToken) {
51+
this.gitHubAccessToken = gitHubAccessToken;
52+
}
53+
54+
public String getVersion() {
55+
return version;
56+
}
57+
58+
public void setVersion(String version) {
59+
this.version = version;
60+
}
61+
62+
public String getApiDocUrl() {
63+
return apiDocUrl;
64+
}
65+
66+
public void setApiDocUrl(String apiDocUrl) {
67+
this.apiDocUrl = apiDocUrl;
68+
}
69+
70+
public String getReferenceDocUrl() {
71+
return referenceDocUrl;
72+
}
73+
74+
public void setReferenceDocUrl(String referenceDocUrl) {
75+
this.referenceDocUrl = referenceDocUrl;
76+
}
77+
78+
public String getProjectName() {
79+
return projectName;
80+
}
81+
82+
public void setProjectName(String projectName) {
83+
this.projectName = projectName;
84+
}
85+
86+
}

0 commit comments

Comments
 (0)