Skip to content

Commit 6c6e339

Browse files
committed
Merge branch '2.3.x'
Closes gh-24316
2 parents 3dc03ac + f569d76 commit 6c6e339

File tree

9 files changed

+463
-0
lines changed

9 files changed

+463
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2012-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 io.spring.concourse.releasescripts.command;
18+
19+
import java.util.List;
20+
21+
import io.spring.concourse.releasescripts.ReleaseType;
22+
import io.spring.concourse.releasescripts.sdkman.SdkmanService;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
26+
import org.springframework.boot.ApplicationArguments;
27+
import org.springframework.stereotype.Component;
28+
import org.springframework.util.Assert;
29+
30+
/**
31+
* Command used to publish to SDKMAN.
32+
*
33+
* @author Madhura Bhave
34+
*/
35+
@Component
36+
public class PublishToSdkmanCommand implements Command {
37+
38+
private static final Logger logger = LoggerFactory.getLogger(PublishToSdkmanCommand.class);
39+
40+
private final SdkmanService service;
41+
42+
public PublishToSdkmanCommand(SdkmanService service) {
43+
this.service = service;
44+
}
45+
46+
@Override
47+
public void run(ApplicationArguments args) throws Exception {
48+
logger.debug("Running 'push to SDKMAN' command");
49+
List<String> nonOptionArgs = args.getNonOptionArgs();
50+
Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified");
51+
Assert.state(nonOptionArgs.size() >= 3, "Release type or version not specified");
52+
String releaseType = nonOptionArgs.get(1);
53+
ReleaseType type = ReleaseType.from(releaseType);
54+
if (!ReleaseType.RELEASE.equals(type)) {
55+
return;
56+
}
57+
String version = nonOptionArgs.get(2);
58+
boolean makeDefault = false;
59+
if (nonOptionArgs.size() == 4) {
60+
String releaseBranch = nonOptionArgs.get(3);
61+
makeDefault = ("master".equals(releaseBranch));
62+
}
63+
this.service.publish(version, makeDefault);
64+
}
65+
66+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2012-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 io.spring.concourse.releasescripts.sdkman;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
21+
/**
22+
* {@link ConfigurationProperties @ConfigurationProperties} for SDKMAN.
23+
*
24+
* @author Madhura Bhave
25+
*/
26+
@ConfigurationProperties(prefix = "sdkman")
27+
public class SdkmanProperties {
28+
29+
private String consumerKey;
30+
31+
private String consumerToken;
32+
33+
public String getConsumerKey() {
34+
return this.consumerKey;
35+
}
36+
37+
public void setConsumerKey(String consumerKey) {
38+
this.consumerKey = consumerKey;
39+
}
40+
41+
public String getConsumerToken() {
42+
return this.consumerToken;
43+
}
44+
45+
public void setConsumerToken(String consumerToken) {
46+
this.consumerToken = consumerToken;
47+
}
48+
49+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright 2012-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 io.spring.concourse.releasescripts.sdkman;
18+
19+
import java.net.URI;
20+
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import org.springframework.boot.web.client.RestTemplateBuilder;
25+
import org.springframework.http.MediaType;
26+
import org.springframework.http.RequestEntity;
27+
import org.springframework.stereotype.Component;
28+
import org.springframework.util.StringUtils;
29+
import org.springframework.web.client.RestTemplate;
30+
31+
/**
32+
* Central class for interacting with SDKMAN's API.
33+
*
34+
* @author Madhura Bhave
35+
*/
36+
@Component
37+
public class SdkmanService {
38+
39+
private static final Logger logger = LoggerFactory.getLogger(SdkmanService.class);
40+
41+
private static final String SDKMAN_URL = "https://vendors.sdkman.io/";
42+
43+
private static final String DOWNLOAD_URL = "https://repo.spring.io/simple/libs-release-local/org/springframework/boot/spring-boot-cli/"
44+
+ "%s/spring-boot-cli-%s-bin.zip";
45+
46+
private static final String SPRING_BOOT = "springboot";
47+
48+
private final RestTemplate restTemplate;
49+
50+
public SdkmanService(RestTemplateBuilder builder, SdkmanProperties properties) {
51+
String consumerKey = properties.getConsumerKey();
52+
String consumerToken = properties.getConsumerToken();
53+
if (StringUtils.hasLength(consumerKey)) {
54+
builder = builder.basicAuthentication(consumerKey, consumerToken);
55+
}
56+
this.restTemplate = builder.build();
57+
}
58+
59+
public void publish(String version, boolean makeDefault) {
60+
release(version);
61+
if (makeDefault) {
62+
makeDefault(version);
63+
}
64+
broadcast(version);
65+
}
66+
67+
private void broadcast(String version) {
68+
BroadcastRequest broadcastRequest = new BroadcastRequest(version);
69+
RequestEntity<BroadcastRequest> broadcastEntity = RequestEntity.post(URI.create(SDKMAN_URL + "announce/struct"))
70+
.contentType(MediaType.APPLICATION_JSON).body(broadcastRequest);
71+
this.restTemplate.exchange(broadcastEntity, String.class);
72+
logger.debug("Broadcast complete");
73+
}
74+
75+
private void makeDefault(String version) {
76+
logger.debug("Making this version the default");
77+
Request request = new Request(version);
78+
RequestEntity<Request> requestEntity = RequestEntity.post(URI.create(SDKMAN_URL + "default"))
79+
.contentType(MediaType.APPLICATION_JSON).body(request);
80+
this.restTemplate.exchange(requestEntity, String.class);
81+
logger.debug("Make default complete");
82+
}
83+
84+
private void release(String version) {
85+
ReleaseRequest releaseRequest = new ReleaseRequest(version, String.format(DOWNLOAD_URL, version, version));
86+
RequestEntity<ReleaseRequest> releaseEntity = RequestEntity.post(URI.create(SDKMAN_URL + "release"))
87+
.contentType(MediaType.APPLICATION_JSON).body(releaseRequest);
88+
this.restTemplate.exchange(releaseEntity, String.class);
89+
logger.debug("Release complete");
90+
}
91+
92+
static class Request {
93+
94+
private final String candidate = SPRING_BOOT;
95+
96+
private final String version;
97+
98+
Request(String version) {
99+
this.version = version;
100+
}
101+
102+
public String getCandidate() {
103+
return this.candidate;
104+
}
105+
106+
public String getVersion() {
107+
return this.version;
108+
}
109+
110+
}
111+
112+
static class ReleaseRequest extends Request {
113+
114+
private final String url;
115+
116+
ReleaseRequest(String version, String url) {
117+
super(version);
118+
this.url = url;
119+
}
120+
121+
public String getUrl() {
122+
return this.url;
123+
}
124+
125+
}
126+
127+
static class BroadcastRequest extends Request {
128+
129+
private final String hashtag = SPRING_BOOT;
130+
131+
BroadcastRequest(String version) {
132+
super(version);
133+
}
134+
135+
public String getHashtag() {
136+
return this.hashtag;
137+
}
138+
139+
}
140+
141+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2012-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 io.spring.concourse.releasescripts.command;
18+
19+
import io.spring.concourse.releasescripts.sdkman.SdkmanService;
20+
import org.assertj.core.api.Assertions;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
import org.mockito.ArgumentCaptor;
24+
import org.mockito.Mock;
25+
import org.mockito.MockitoAnnotations;
26+
27+
import org.springframework.boot.DefaultApplicationArguments;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.mockito.Mockito.verify;
31+
import static org.mockito.Mockito.verifyNoInteractions;
32+
33+
/**
34+
* Tests for {@link PublishToSdkmanCommand}.
35+
*
36+
* @author Madhura Bhave
37+
*/
38+
class PublishToSdkmanCommandTests {
39+
40+
@Mock
41+
private SdkmanService service;
42+
43+
private PublishToSdkmanCommand command;
44+
45+
@BeforeEach
46+
void setup() {
47+
MockitoAnnotations.initMocks(this);
48+
this.command = new PublishToSdkmanCommand(this.service);
49+
}
50+
51+
@Test
52+
void runWhenReleaseTypeNotSpecifiedShouldThrowException() throws Exception {
53+
Assertions.assertThatIllegalStateException()
54+
.isThrownBy(() -> this.command.run(new DefaultApplicationArguments("publishGradlePlugin")));
55+
}
56+
57+
@Test
58+
void runWhenVersionNotSpecifiedShouldThrowException() throws Exception {
59+
Assertions.assertThatIllegalStateException()
60+
.isThrownBy(() -> this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "RELEASE")));
61+
}
62+
63+
@Test
64+
void runWhenReleaseTypeMilestoneShouldDoNothing() throws Exception {
65+
this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "M", "1.2.3"));
66+
verifyNoInteractions(this.service);
67+
}
68+
69+
@Test
70+
void runWhenReleaseTypeRCShouldDoNothing() throws Exception {
71+
this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "RC", "1.2.3"));
72+
verifyNoInteractions(this.service);
73+
}
74+
75+
@Test
76+
void runWhenBranchNotSpecifiedShouldCallServiceWithMakeDefaultFalse() throws Exception {
77+
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3");
78+
testRun(args, false);
79+
}
80+
81+
@Test
82+
void runWhenBranchNotMasterShouldCallServiceWithMakeDefaultFalse() throws Exception {
83+
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3", "other");
84+
testRun(args, false);
85+
}
86+
87+
@Test
88+
void runWhenReleaseTypeReleaseShouldCallService() throws Exception {
89+
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3", "master");
90+
testRun(args, true);
91+
}
92+
93+
private void testRun(DefaultApplicationArguments args, boolean makeDefault) throws Exception {
94+
ArgumentCaptor<String> versionCaptor = ArgumentCaptor.forClass(String.class);
95+
ArgumentCaptor<Boolean> makeDefaultCaptor = ArgumentCaptor.forClass(Boolean.class);
96+
this.command.run(args);
97+
verify(this.service).publish(versionCaptor.capture(), makeDefaultCaptor.capture());
98+
String version = versionCaptor.getValue();
99+
Boolean makeDefaultValue = makeDefaultCaptor.getValue();
100+
assertThat(version).isEqualTo("1.2.3");
101+
assertThat(makeDefaultValue).isEqualTo(makeDefault);
102+
}
103+
104+
}

0 commit comments

Comments
 (0)