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