commit
6c6e339dbb
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.spring.concourse.releasescripts.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.spring.concourse.releasescripts.ReleaseType;
|
||||||
|
import io.spring.concourse.releasescripts.sdkman.SdkmanService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command used to publish to SDKMAN.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class PublishToSdkmanCommand implements Command {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PublishToSdkmanCommand.class);
|
||||||
|
|
||||||
|
private final SdkmanService service;
|
||||||
|
|
||||||
|
public PublishToSdkmanCommand(SdkmanService service) {
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
logger.debug("Running 'push to SDKMAN' command");
|
||||||
|
List<String> nonOptionArgs = args.getNonOptionArgs();
|
||||||
|
Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified");
|
||||||
|
Assert.state(nonOptionArgs.size() >= 3, "Release type or version not specified");
|
||||||
|
String releaseType = nonOptionArgs.get(1);
|
||||||
|
ReleaseType type = ReleaseType.from(releaseType);
|
||||||
|
if (!ReleaseType.RELEASE.equals(type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String version = nonOptionArgs.get(2);
|
||||||
|
boolean makeDefault = false;
|
||||||
|
if (nonOptionArgs.size() == 4) {
|
||||||
|
String releaseBranch = nonOptionArgs.get(3);
|
||||||
|
makeDefault = ("master".equals(releaseBranch));
|
||||||
|
}
|
||||||
|
this.service.publish(version, makeDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.spring.concourse.releasescripts.sdkman;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ConfigurationProperties @ConfigurationProperties} for SDKMAN.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "sdkman")
|
||||||
|
public class SdkmanProperties {
|
||||||
|
|
||||||
|
private String consumerKey;
|
||||||
|
|
||||||
|
private String consumerToken;
|
||||||
|
|
||||||
|
public String getConsumerKey() {
|
||||||
|
return this.consumerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConsumerKey(String consumerKey) {
|
||||||
|
this.consumerKey = consumerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConsumerToken() {
|
||||||
|
return this.consumerToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConsumerToken(String consumerToken) {
|
||||||
|
this.consumerToken = consumerToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.spring.concourse.releasescripts.sdkman;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.RequestEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Central class for interacting with SDKMAN's API.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SdkmanService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SdkmanService.class);
|
||||||
|
|
||||||
|
private static final String SDKMAN_URL = "https://vendors.sdkman.io/";
|
||||||
|
|
||||||
|
private static final String DOWNLOAD_URL = "https://repo.spring.io/simple/libs-release-local/org/springframework/boot/spring-boot-cli/"
|
||||||
|
+ "%s/spring-boot-cli-%s-bin.zip";
|
||||||
|
|
||||||
|
private static final String SPRING_BOOT = "springboot";
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public SdkmanService(RestTemplateBuilder builder, SdkmanProperties properties) {
|
||||||
|
String consumerKey = properties.getConsumerKey();
|
||||||
|
String consumerToken = properties.getConsumerToken();
|
||||||
|
if (StringUtils.hasLength(consumerKey)) {
|
||||||
|
builder = builder.basicAuthentication(consumerKey, consumerToken);
|
||||||
|
}
|
||||||
|
this.restTemplate = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publish(String version, boolean makeDefault) {
|
||||||
|
release(version);
|
||||||
|
if (makeDefault) {
|
||||||
|
makeDefault(version);
|
||||||
|
}
|
||||||
|
broadcast(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void broadcast(String version) {
|
||||||
|
BroadcastRequest broadcastRequest = new BroadcastRequest(version);
|
||||||
|
RequestEntity<BroadcastRequest> broadcastEntity = RequestEntity.post(URI.create(SDKMAN_URL + "announce/struct"))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON).body(broadcastRequest);
|
||||||
|
this.restTemplate.exchange(broadcastEntity, String.class);
|
||||||
|
logger.debug("Broadcast complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeDefault(String version) {
|
||||||
|
logger.debug("Making this version the default");
|
||||||
|
Request request = new Request(version);
|
||||||
|
RequestEntity<Request> requestEntity = RequestEntity.post(URI.create(SDKMAN_URL + "default"))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON).body(request);
|
||||||
|
this.restTemplate.exchange(requestEntity, String.class);
|
||||||
|
logger.debug("Make default complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void release(String version) {
|
||||||
|
ReleaseRequest releaseRequest = new ReleaseRequest(version, String.format(DOWNLOAD_URL, version, version));
|
||||||
|
RequestEntity<ReleaseRequest> releaseEntity = RequestEntity.post(URI.create(SDKMAN_URL + "release"))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON).body(releaseRequest);
|
||||||
|
this.restTemplate.exchange(releaseEntity, String.class);
|
||||||
|
logger.debug("Release complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Request {
|
||||||
|
|
||||||
|
private final String candidate = SPRING_BOOT;
|
||||||
|
|
||||||
|
private final String version;
|
||||||
|
|
||||||
|
Request(String version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCandidate() {
|
||||||
|
return this.candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ReleaseRequest extends Request {
|
||||||
|
|
||||||
|
private final String url;
|
||||||
|
|
||||||
|
ReleaseRequest(String version, String url) {
|
||||||
|
super(version);
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return this.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BroadcastRequest extends Request {
|
||||||
|
|
||||||
|
private final String hashtag = SPRING_BOOT;
|
||||||
|
|
||||||
|
BroadcastRequest(String version) {
|
||||||
|
super(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashtag() {
|
||||||
|
return this.hashtag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.spring.concourse.releasescripts.command;
|
||||||
|
|
||||||
|
import io.spring.concourse.releasescripts.sdkman.SdkmanService;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import org.springframework.boot.DefaultApplicationArguments;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link PublishToSdkmanCommand}.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
class PublishToSdkmanCommandTests {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SdkmanService service;
|
||||||
|
|
||||||
|
private PublishToSdkmanCommand command;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
this.command = new PublishToSdkmanCommand(this.service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenReleaseTypeNotSpecifiedShouldThrowException() throws Exception {
|
||||||
|
Assertions.assertThatIllegalStateException()
|
||||||
|
.isThrownBy(() -> this.command.run(new DefaultApplicationArguments("publishGradlePlugin")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenVersionNotSpecifiedShouldThrowException() throws Exception {
|
||||||
|
Assertions.assertThatIllegalStateException()
|
||||||
|
.isThrownBy(() -> this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "RELEASE")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenReleaseTypeMilestoneShouldDoNothing() throws Exception {
|
||||||
|
this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "M", "1.2.3"));
|
||||||
|
verifyNoInteractions(this.service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenReleaseTypeRCShouldDoNothing() throws Exception {
|
||||||
|
this.command.run(new DefaultApplicationArguments("publishGradlePlugin", "RC", "1.2.3"));
|
||||||
|
verifyNoInteractions(this.service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenBranchNotSpecifiedShouldCallServiceWithMakeDefaultFalse() throws Exception {
|
||||||
|
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3");
|
||||||
|
testRun(args, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenBranchNotMasterShouldCallServiceWithMakeDefaultFalse() throws Exception {
|
||||||
|
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3", "other");
|
||||||
|
testRun(args, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenReleaseTypeReleaseShouldCallService() throws Exception {
|
||||||
|
DefaultApplicationArguments args = new DefaultApplicationArguments("promote", "RELEASE", "1.2.3", "master");
|
||||||
|
testRun(args, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testRun(DefaultApplicationArguments args, boolean makeDefault) throws Exception {
|
||||||
|
ArgumentCaptor<String> versionCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<Boolean> makeDefaultCaptor = ArgumentCaptor.forClass(Boolean.class);
|
||||||
|
this.command.run(args);
|
||||||
|
verify(this.service).publish(versionCaptor.capture(), makeDefaultCaptor.capture());
|
||||||
|
String version = versionCaptor.getValue();
|
||||||
|
Boolean makeDefaultValue = makeDefaultCaptor.getValue();
|
||||||
|
assertThat(version).isEqualTo("1.2.3");
|
||||||
|
assertThat(makeDefaultValue).isEqualTo(makeDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.spring.concourse.releasescripts.sdkman;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.web.client.MockRestServiceServer;
|
||||||
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||||
|
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link SdkmanService}.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
@EnableConfigurationProperties(SdkmanProperties.class)
|
||||||
|
@RestClientTest(SdkmanService.class)
|
||||||
|
class SdkmanServiceTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SdkmanService service;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SdkmanProperties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockRestServiceServer server;
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
this.server.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void publishWhenMakeDefaultTrue() throws Exception {
|
||||||
|
setupExpectation("https://vendors.sdkman.io/release",
|
||||||
|
"{\"candidate\": \"springboot\", \"version\": \"1.2.3\", \"url\": \"https://repo.spring.io/simple/libs-release-local/org/springframework/boot/spring-boot-cli/1.2.3/spring-boot-cli-1.2.3-bin.zip\"}");
|
||||||
|
setupExpectation("https://vendors.sdkman.io/default",
|
||||||
|
"{\"candidate\": \"springboot\", \"version\": \"1.2.3\"}");
|
||||||
|
setupExpectation("https://vendors.sdkman.io/announce/struct",
|
||||||
|
"{\"candidate\": \"springboot\", \"version\": \"1.2.3\", \"hashtag\": \"springboot\"}");
|
||||||
|
this.service.publish("1.2.3", true);
|
||||||
|
this.server.verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void publishWhenMakeDefaultFalse() throws Exception {
|
||||||
|
setupExpectation("https://vendors.sdkman.io/release",
|
||||||
|
"{\"candidate\": \"springboot\", \"version\": \"1.2.3\", \"url\": \"https://repo.spring.io/simple/libs-release-local/org/springframework/boot/spring-boot-cli/1.2.3/spring-boot-cli-1.2.3-bin.zip\"}");
|
||||||
|
setupExpectation("https://vendors.sdkman.io/announce/struct",
|
||||||
|
"{\"candidate\": \"springboot\", \"version\": \"1.2.3\", \"hashtag\": \"springboot\"}");
|
||||||
|
this.service.publish("1.2.3", false);
|
||||||
|
this.server.verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupExpectation(String url, String body) {
|
||||||
|
this.server.expect(requestTo(url)).andExpect(method(HttpMethod.POST)).andExpect(content().json(body))
|
||||||
|
.andExpect(header("Authorization",
|
||||||
|
"Basic " + Base64Utils.encodeToString(String
|
||||||
|
.format("%s:%s", this.properties.getConsumerKey(), this.properties.getConsumerToken())
|
||||||
|
.getBytes())))
|
||||||
|
.andExpect(header("Content-Type", MediaType.APPLICATION_JSON.toString())).andRespond(withSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue