From 7b14d5bb087b49565676625b12acac620765b8cd Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 24 Jun 2021 18:48:22 -0700 Subject: [PATCH] Protect against NPE in isAlreadyPromoted Fixes gh-27094 --- .../artifactory/ArtifactoryService.java | 8 +++++- .../artifactory/ArtifactoryServiceTests.java | 11 ++++++++ .../no-status-build-info-response.json | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/artifactory/no-status-build-info-response.json diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryService.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryService.java index d01ba77b95..2bb2cd7603 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryService.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryService.java @@ -20,6 +20,7 @@ import java.net.URI; import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; +import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.Status; import io.spring.concourse.releasescripts.artifactory.payload.PromotionRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,7 +97,12 @@ public class ArtifactoryService { logger.debug("Checking if already promoted"); ResponseEntity entity = this.restTemplate .getForEntity(BUILD_INFO_URL + buildName + "/" + buildNumber, BuildInfoResponse.class); - BuildInfoResponse.Status status = entity.getBody().getBuildInfo().getStatuses()[0]; + Status[] statuses = entity.getBody().getBuildInfo().getStatuses(); + BuildInfoResponse.Status status = (statuses != null) ? statuses[0] : null; + if (status == null) { + logger.debug("Returned no status object"); + return false; + } logger.debug("Returned repository " + status.getRepository() + " expecting " + targetRepo); return status.getRepository().equals(targetRepo); } diff --git a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java index 0d017916fc..19ab95e125 100644 --- a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java +++ b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java @@ -97,6 +97,17 @@ class ArtifactoryServiceTests { this.server.verify(); } + @Test + void promoteWhenCheckForArtifactsAlreadyPromotedReturnsNoStatus() { + this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1")) + .andRespond(withStatus(HttpStatus.CONFLICT)); + this.server.expect(requestTo("https://repo.spring.io/api/build/example-build/example-build-1")) + .andRespond(withJsonFrom("no-status-build-info-response.json")); + assertThatExceptionOfType(HttpClientErrorException.class) + .isThrownBy(() -> this.service.promote("libs-milestone-local", getReleaseInfo())); + this.server.verify(); + } + @Test void promoteWhenPromotionFails() { this.server.expect(requestTo("https://repo.spring.io/api/build/promote/example-build/example-build-1")) diff --git a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/artifactory/no-status-build-info-response.json b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/artifactory/no-status-build-info-response.json new file mode 100644 index 0000000000..6183ca8001 --- /dev/null +++ b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/artifactory/no-status-build-info-response.json @@ -0,0 +1,26 @@ +{ + "buildInfo": { + "version": "1.0.1", + "name": "example", + "number": "example-build-1", + "started": "2019-09-10T12:18:05.430+0000", + "durationMillis": 0, + "artifactoryPrincipal": "user", + "url": "https://my-ci.com", + "modules": [ + { + "id": "org.example.demo:demo:2.2.0", + "artifacts": [ + { + "type": "jar", + "sha1": "ayyyya9151a22cb3145538e523dbbaaaaaaaa", + "sha256": "aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy", + "md5": "aaaaaacddea1724b0b69d8yyyyyyy", + "name": "demo-2.2.0.jar" + } + ] + } + ] + }, + "uri": "https://my-artifactory-repo.com/api/build/example/example-build-1" +} \ No newline at end of file