Skip to content

Commit e137e3d

Browse files
committed
Merge branch '2.1.x' into 2.2.x
2 parents 9c5e593 + f68671e commit e137e3d

File tree

7 files changed

+167
-25
lines changed

7 files changed

+167
-25
lines changed

ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,13 @@ public boolean isDistributionComplete(ReleaseInfo releaseInfo, Set<String> requi
101101
try {
102102
waitAtMost(timeout).with().pollDelay(Duration.ZERO).pollInterval(pollInterval).until(() -> {
103103
logger.debug("Checking bintray");
104-
PackageFile[] published = this.restTemplate.exchange(request, PackageFile[].class).getBody();
105-
return hasPublishedAll(published, requiredDigests);
104+
try {
105+
PackageFile[] published = this.restTemplate.exchange(request, PackageFile[].class).getBody();
106+
return hasPublishedAll(published, requiredDigests);
107+
}
108+
catch (HttpClientErrorException.NotFound ex) {
109+
return false;
110+
}
106111
});
107112
}
108113
catch (ConditionTimeoutException ex) {

ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.nio.file.Files;
2121
import java.util.List;
2222
import java.util.Set;
23+
import java.util.regex.Pattern;
24+
import java.util.stream.Collectors;
2325

2426
import com.fasterxml.jackson.databind.ObjectMapper;
2527
import io.spring.concourse.releasescripts.ReleaseInfo;
@@ -40,6 +42,7 @@
4042
* Command used to deploy builds from Artifactory to Bintray.
4143
*
4244
* @author Madhura Bhave
45+
* @author Phillip Webb
4346
*/
4447
@Component
4548
public class DistributeCommand implements Command {
@@ -50,9 +53,14 @@ public class DistributeCommand implements Command {
5053

5154
private final ObjectMapper objectMapper;
5255

53-
public DistributeCommand(ArtifactoryService artifactoryService, ObjectMapper objectMapper) {
56+
private final List<Pattern> optionalDeployments;
57+
58+
public DistributeCommand(ArtifactoryService artifactoryService, ObjectMapper objectMapper,
59+
DistributeProperties distributeProperties) {
5460
this.artifactoryService = artifactoryService;
5561
this.objectMapper = objectMapper;
62+
this.optionalDeployments = distributeProperties.getOptionalDeployments().stream().map(Pattern::compile)
63+
.collect(Collectors.toList());
5664
}
5765

5866
@Override
@@ -80,8 +88,18 @@ public void run(ApplicationArguments args) throws Exception {
8088
}
8189
}
8290
ReleaseInfo releaseInfo = ReleaseInfo.from(buildInfo);
83-
Set<String> artifactDigests = buildInfo.getArtifactDigests((artifact) -> !artifact.getName().endsWith(".zip"));
91+
Set<String> artifactDigests = buildInfo.getArtifactDigests(this::isIncluded);
8492
this.artifactoryService.distribute(type.getRepo(), releaseInfo, artifactDigests);
8593
}
8694

95+
private boolean isIncluded(Artifact artifact) {
96+
String path = artifact.getName();
97+
for (Pattern optionalDeployment : this.optionalDeployments) {
98+
if (optionalDeployment.matcher(path).matches()) {
99+
return false;
100+
}
101+
}
102+
return true;
103+
}
104+
87105
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 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.ArrayList;
20+
import java.util.List;
21+
22+
import org.springframework.boot.context.properties.ConfigurationProperties;
23+
24+
/**
25+
* Distribution properties.
26+
*
27+
* @author Phillip Webb
28+
*/
29+
@ConfigurationProperties(prefix = "distribute")
30+
public class DistributeProperties {
31+
32+
private List<String> optionalDeployments = new ArrayList<>();
33+
34+
public List<String> getOptionalDeployments() {
35+
return this.optionalDeployments;
36+
}
37+
38+
public void setOptionalDeployments(List<String> optionalDeployments) {
39+
this.optionalDeployments = optionalDeployments;
40+
}
41+
42+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
spring.main.banner-mode=off
2-
# logging.level.io.spring.concourse=DEBUG
2+
distribute.optional-deployments[0]=.*\\.zip
3+
distribute.optional-deployments[1]=spring-boot-project-\\d+\\.\\d+\\.\\d+(?:\\.RELEASE)?\\.pom
4+
logging.level.io.spring.concourse=DEBUG

ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,7 @@ void tearDown() {
8484

8585
@Test
8686
void promoteWhenSuccessful() {
87-
this.server
88-
.expect(requestTo(
89-
"https://repo.spring.io/api/build/promote/" + "example-build" + "/" + "example-build-1"))
87+
this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1"))
9088
.andExpect(method(HttpMethod.POST))
9189
.andExpect(content().json(
9290
"{\"status\": \"staged\", \"sourceRepo\": \"libs-staging-local\", \"targetRepo\": \"libs-milestone-local\"}"))
@@ -99,23 +97,19 @@ void promoteWhenSuccessful() {
9997

10098
@Test
10199
void promoteWhenArtifactsAlreadyPromoted() {
102-
this.server
103-
.expect(requestTo(
104-
"https://repo.spring.io/api/build/promote/" + "example-build" + "/" + "example-build-1"))
100+
this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1"))
105101
.andRespond(withStatus(HttpStatus.CONFLICT));
106-
this.server.expect(requestTo("https://repo.spring.io/api/build/" + "example-build" + "/" + "example-build-1"))
102+
this.server.expect(requestTo("https://repo.spring.io/api/build/example-build/example-build-1"))
107103
.andRespond(withJsonFrom("build-info-response.json"));
108104
this.service.promote("libs-release-local", getReleaseInfo());
109105
this.server.verify();
110106
}
111107

112108
@Test
113109
void promoteWhenCheckForArtifactsAlreadyPromotedFails() {
114-
this.server
115-
.expect(requestTo(
116-
"https://repo.spring.io/api/build/promote/" + "example-build" + "/" + "example-build-1"))
110+
this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1"))
117111
.andRespond(withStatus(HttpStatus.CONFLICT));
118-
this.server.expect(requestTo("https://repo.spring.io/api/build/" + "example-build" + "/" + "example-build-1"))
112+
this.server.expect(requestTo("https://repo.spring.io/api/build/example-build/example-build-1"))
119113
.andRespond(withStatus(HttpStatus.FORBIDDEN));
120114
assertThatExceptionOfType(HttpClientErrorException.class)
121115
.isThrownBy(() -> this.service.promote("libs-release-local", getReleaseInfo()));
@@ -124,11 +118,9 @@ void promoteWhenCheckForArtifactsAlreadyPromotedFails() {
124118

125119
@Test
126120
void promoteWhenPromotionFails() {
127-
this.server
128-
.expect(requestTo(
129-
"https://repo.spring.io/api/build/promote/" + "example-build" + "/" + "example-build-1"))
121+
this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1"))
130122
.andRespond(withStatus(HttpStatus.CONFLICT));
131-
this.server.expect(requestTo("https://repo.spring.io/api/build/" + "example-build" + "/" + "example-build-1"))
123+
this.server.expect(requestTo("https://repo.spring.io/api/build/example-build/example-build-1"))
132124
.andRespond(withJsonFrom("staged-build-info-response.json"));
133125
assertThatExceptionOfType(HttpClientErrorException.class)
134126
.isThrownBy(() -> this.service.promote("libs-release-local", getReleaseInfo()));
@@ -158,9 +150,7 @@ void distributeWhenSuccessful() throws Exception {
158150
@Test
159151
void distributeWhenFailure() throws Exception {
160152
ReleaseInfo releaseInfo = getReleaseInfo();
161-
this.server
162-
.expect(requestTo(
163-
"https://repo.spring.io/api/build/distribute/" + "example-build" + "/" + "example-build-1"))
153+
this.server.expect(requestTo("https://repo.spring.io/api/build/distribute/example-build/example-build-1"))
164154
.andExpect(method(HttpMethod.POST))
165155
.andExpect(content().json(
166156
"{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}"))

ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.spring.concourse.releasescripts.command;
1818

19+
import java.util.Arrays;
1920
import java.util.Set;
2021

2122
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -42,6 +43,7 @@
4243
* Tests for {@link DistributeCommand}.
4344
*
4445
* @author Madhura Bhave
46+
* @author Phillip Webb
4547
*/
4648
class DistributeCommandTests {
4749

@@ -55,8 +57,10 @@ class DistributeCommandTests {
5557
@BeforeEach
5658
void setup() {
5759
MockitoAnnotations.initMocks(this);
60+
DistributeProperties distributeProperties = new DistributeProperties();
61+
distributeProperties.setOptionalDeployments(Arrays.asList(".*\\.zip", "demo-\\d\\.\\d\\.\\d\\.doc"));
5862
this.objectMapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
59-
this.command = new DistributeCommand(this.service, this.objectMapper);
63+
this.command = new DistributeCommand(this.service, this.objectMapper, distributeProperties);
6064
}
6165

6266
@Test
@@ -94,8 +98,30 @@ void distributeWhenReleaseTypeReleaseShouldCallService() throws Exception {
9498
assertThat(artifactDigests).containsExactly("aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy");
9599
}
96100

101+
@Test
102+
@SuppressWarnings("unchecked")
103+
void distributeWhenReleaseTypeReleaseAndFilteredShouldCallService() throws Exception {
104+
ArgumentCaptor<ReleaseInfo> releaseInfoCaptor = ArgumentCaptor.forClass(ReleaseInfo.class);
105+
ArgumentCaptor<Set<String>> artifactDigestCaptor = ArgumentCaptor.forClass(Set.class);
106+
this.command.run(new DefaultApplicationArguments("distribute", "RELEASE",
107+
getBuildInfoLocation("filtered-build-info-response.json")));
108+
verify(this.service).distribute(eq(ReleaseType.RELEASE.getRepo()), releaseInfoCaptor.capture(),
109+
artifactDigestCaptor.capture());
110+
ReleaseInfo releaseInfo = releaseInfoCaptor.getValue();
111+
assertThat(releaseInfo.getBuildName()).isEqualTo("example");
112+
assertThat(releaseInfo.getBuildNumber()).isEqualTo("example-build-1");
113+
assertThat(releaseInfo.getGroupId()).isEqualTo("org.example.demo");
114+
assertThat(releaseInfo.getVersion()).isEqualTo("2.2.0");
115+
Set<String> artifactDigests = artifactDigestCaptor.getValue();
116+
assertThat(artifactDigests).containsExactly("aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy");
117+
}
118+
97119
private String getBuildInfoLocation() throws Exception {
98-
return new ClassPathResource("build-info-response.json", ArtifactoryService.class).getFile().getAbsolutePath();
120+
return getBuildInfoLocation("build-info-response.json");
121+
}
122+
123+
private String getBuildInfoLocation(String file) throws Exception {
124+
return new ClassPathResource(file, ArtifactoryService.class).getFile().getAbsolutePath();
99125
}
100126

101127
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"buildInfo": {
3+
"version": "1.0.1",
4+
"name": "example",
5+
"number": "example-build-1",
6+
"started": "2019-09-10T12:18:05.430+0000",
7+
"durationMillis": 0,
8+
"artifactoryPrincipal": "user",
9+
"url": "https://my-ci.com",
10+
"modules": [
11+
{
12+
"id": "org.example.demo:demo:2.2.0",
13+
"artifacts": [
14+
{
15+
"type": "jar",
16+
"sha1": "ayyyya9151a22cb3145538e523dbbaaaaaaaa",
17+
"sha256": "aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy",
18+
"md5": "aaaaaacddea1724b0b69d8yyyyyyy",
19+
"name": "demo-2.2.0.jar"
20+
}
21+
]
22+
},
23+
{
24+
"id": "org.example.demo:demo:2.2.0:zip",
25+
"artifacts": [
26+
{
27+
"type": "zip",
28+
"sha1": "ayyyya9151a22cb3145538e523dbbaaaaaaab",
29+
"sha256": "aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyz",
30+
"md5": "aaaaaacddea1724b0b69d8yyyyyyz",
31+
"name": "demo-2.2.0.zip"
32+
}
33+
]
34+
},
35+
{
36+
"id": "org.example.demo:demo:2.2.0:doc",
37+
"artifacts": [
38+
{
39+
"type": "jar",
40+
"sha1": "ayyyya9151a22cb3145538e523dbbaaaaaaba",
41+
"sha256": "aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyzy",
42+
"md5": "aaaaaacddea1724b0b69d8yyyyyzy",
43+
"name": "demo-2.2.0.doc"
44+
}
45+
]
46+
}
47+
],
48+
"statuses": [
49+
{
50+
"status": "staged",
51+
"repository": "libs-release-local",
52+
"timestamp": "2019-09-10T12:42:24.716+0000",
53+
"user": "user",
54+
"timestampDate": 1568119344716
55+
}
56+
]
57+
},
58+
"uri": "https://my-artifactory-repo.com/api/build/example/example-build-1"
59+
}

0 commit comments

Comments
 (0)