Wait for distribution to reach Bintray before checking its completeness
Previously, as soon as the distribution of a release from Artifactory to Bintray had been initiated we would start checking if it was complete. This created a race condition between the distribution being created and us checking if it was complete. If the check won the race and happened before the creation, Bintray would respond with a 404. This commit updates BintrayService to wait for up to 5 minutes for the distribution to be created on Bintray. Once it has been created we then wait for up to 40 minutes for it to be complete as we did before. The use of Awaitility has been introduced in this commit to simplify the logic required to wait for the distribution's creation and completion. Closes gh-18902
This commit is contained in:
parent
8b1ff0a1a9
commit
891c7120ef
|
|
@ -44,6 +44,10 @@
|
|||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-parameter-names</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,19 +17,25 @@
|
|||
package io.spring.concourse.releasescripts.bintray;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.spring.concourse.releasescripts.ReleaseInfo;
|
||||
import io.spring.concourse.releasescripts.sonatype.SonatypeProperties;
|
||||
import io.spring.concourse.releasescripts.sonatype.SonatypeService;
|
||||
import io.spring.concourse.releasescripts.system.ConsoleLogger;
|
||||
import org.awaitility.core.ConditionTimeoutException;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.awaitility.Awaitility.waitAtMost;
|
||||
|
||||
/**
|
||||
* Central class for interacting with Bintray's REST API.
|
||||
*
|
||||
|
|
@ -64,25 +70,29 @@ public class BintrayService {
|
|||
}
|
||||
|
||||
public boolean isDistributionComplete(ReleaseInfo releaseInfo) {
|
||||
RequestEntity<Void> publishedFilesRequest = getRequest(releaseInfo, 0);
|
||||
RequestEntity<Void> allFilesRequest = getRequest(releaseInfo, 1);
|
||||
Object[] allFiles = this.restTemplate.exchange(allFilesRequest, Object[].class).getBody();
|
||||
int count = 0;
|
||||
while (count < 120) {
|
||||
Object[] publishedFiles = this.restTemplate.exchange(publishedFilesRequest, Object[].class).getBody();
|
||||
int unpublished = allFiles.length - publishedFiles.length;
|
||||
if (unpublished == 0) {
|
||||
return true;
|
||||
}
|
||||
count++;
|
||||
Object[] allFiles = waitAtMost(5, TimeUnit.MINUTES).with().pollDelay(20, TimeUnit.SECONDS).until(() -> {
|
||||
try {
|
||||
Thread.sleep(20000);
|
||||
return this.restTemplate.exchange(allFilesRequest, Object[].class).getBody();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
|
||||
catch (HttpClientErrorException ex) {
|
||||
if (ex.getStatusCode() != HttpStatus.NOT_FOUND) {
|
||||
throw ex;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, Objects::nonNull);
|
||||
RequestEntity<Void> publishedFilesRequest = getRequest(releaseInfo, 0);
|
||||
try {
|
||||
waitAtMost(40, TimeUnit.MINUTES).with().pollDelay(20, TimeUnit.SECONDS).until(() -> {
|
||||
Object[] publishedFiles = this.restTemplate.exchange(publishedFilesRequest, Object[].class).getBody();
|
||||
return allFiles.length == publishedFiles.length;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
catch (ConditionTimeoutException ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private RequestEntity<Void> getRequest(ReleaseInfo releaseInfo, int includeUnpublished) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
|
|||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.ExpectedCount;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
|
|
@ -40,6 +41,7 @@ import static org.springframework.test.web.client.match.MockRestRequestMatchers.
|
|||
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.withStatus;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
|
|
@ -73,6 +75,11 @@ class BintrayServiceTests {
|
|||
|
||||
@Test
|
||||
void isDistributionComplete() throws Exception {
|
||||
this.server
|
||||
.expect(requestTo(String.format(
|
||||
"https://api.bintray.com/packages/%s/%s/%s/versions/%s/files?include_unpublished=%s",
|
||||
this.properties.getSubject(), this.properties.getRepo(), "example", "1.1.0.RELEASE", 1)))
|
||||
.andRespond(withStatus(HttpStatus.NOT_FOUND));
|
||||
setupGetPackageFiles(1, "all-package-files.json");
|
||||
setupGetPackageFiles(0, "published-files.json");
|
||||
setupGetPackageFiles(0, "all-package-files.json");
|
||||
|
|
|
|||
Loading…
Reference in New Issue