From 6d93d732b4f5407b5f30238533e38c6bb8e73833 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 11 Jun 2020 18:48:35 -0700 Subject: [PATCH] Cherry-pick release script updates Cherry-pick release script updates from 2.3.x See gh-21474 --- .../artifactory/ArtifactoryService.java | 33 ++++++--- .../payload/BuildInfoResponse.java | 50 ++++++++++++- .../bintray/BintrayService.java | 73 ++++++++++++------- .../PackageFile.java} | 24 +++--- .../command/CommandProcessor.java | 12 ++- .../command/DistributeCommand.java | 30 ++++++-- .../command/PromoteCommand.java | 5 ++ .../command/PublishGradlePlugin.java | 5 ++ .../command/SyncToCentralCommand.java | 5 ++ .../sonatype/SonatypeService.java | 13 ++-- .../src/main/resources/application.properties | 3 +- .../artifactory/ArtifactoryServiceTests.java | 52 +++++++++---- .../bintray/BintrayServiceTests.java | 22 +++--- .../command/DistributeCommandTests.java | 15 +++- .../sonatype/SonatypeServiceTests.java | 6 +- .../bintray/all-package-files.json | 6 +- .../bintray/no-package-files.json | 1 + ...hed-files.json => some-package-files.json} | 2 +- ci/scripts/promote.sh | 6 +- ci/scripts/sync-to-maven-central.sh | 2 +- 20 files changed, 265 insertions(+), 100 deletions(-) rename ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/{system/ConsoleLogger.java => bintray/PackageFile.java} (59%) create mode 100644 ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/no-package-files.json rename ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/{published-files.json => some-package-files.json} (84%) 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 370f345f79..423f6899b3 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 @@ -17,13 +17,16 @@ package io.spring.concourse.releasescripts.artifactory; import java.net.URI; +import java.time.Duration; +import java.util.Set; import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; import io.spring.concourse.releasescripts.artifactory.payload.DistributionRequest; import io.spring.concourse.releasescripts.artifactory.payload.PromotionRequest; import io.spring.concourse.releasescripts.bintray.BintrayService; -import io.spring.concourse.releasescripts.system.ConsoleLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.MediaType; @@ -42,6 +45,8 @@ import org.springframework.web.client.RestTemplate; @Component public class ArtifactoryService { + private static final Logger logger = LoggerFactory.getLogger(ArtifactoryService.class); + private static final String ARTIFACTORY_URL = "https://repo.spring.io"; private static final String PROMOTION_URL = ARTIFACTORY_URL + "/api/build/promote/"; @@ -56,8 +61,6 @@ public class ArtifactoryService { private final BintrayService bintrayService; - private static final ConsoleLogger console = new ConsoleLogger(); - public ArtifactoryService(RestTemplateBuilder builder, ArtifactoryProperties artifactoryProperties, BintrayService bintrayService) { this.bintrayService = bintrayService; @@ -78,20 +81,21 @@ public class ArtifactoryService { PromotionRequest request = getPromotionRequest(targetRepo); String buildName = releaseInfo.getBuildName(); String buildNumber = releaseInfo.getBuildNumber(); - console.log("Promoting " + buildName + "/" + buildNumber + " to " + request.getTargetRepo()); + logger.info("Promoting " + buildName + "/" + buildNumber + " to " + request.getTargetRepo()); RequestEntity requestEntity = RequestEntity .post(URI.create(PROMOTION_URL + buildName + "/" + buildNumber)).contentType(MediaType.APPLICATION_JSON) .body(request); try { this.restTemplate.exchange(requestEntity, String.class); + logger.debug("Promotion complete"); } catch (HttpClientErrorException ex) { boolean isAlreadyPromoted = isAlreadyPromoted(buildName, buildNumber, request.getTargetRepo()); if (isAlreadyPromoted) { - console.log("Already promoted."); + logger.info("Already promoted."); } else { - console.log("Promotion failed."); + logger.info("Promotion failed."); throw ex; } } @@ -99,12 +103,15 @@ public class ArtifactoryService { private boolean isAlreadyPromoted(String buildName, String buildNumber, String targetRepo) { try { + logger.debug("Checking if alreay promoted"); ResponseEntity entity = this.restTemplate .getForEntity(BUILD_INFO_URL + buildName + "/" + buildNumber, BuildInfoResponse.class); BuildInfoResponse.Status status = entity.getBody().getBuildInfo().getStatuses()[0]; + logger.debug("Reutned repository " + status.getRepository() + " expecting " + targetRepo); return status.getRepository().equals(targetRepo); } catch (HttpClientErrorException ex) { + logger.debug("Client error, assuming not promoted"); return false; } } @@ -112,20 +119,28 @@ public class ArtifactoryService { /** * Deploy builds from Artifactory to Bintray. * @param sourceRepo the source repo in Artifactory. + * @param releaseInfo the resease info + * @param artifactDigests the artifact digests */ - public void distribute(String sourceRepo, ReleaseInfo releaseInfo) { + public void distribute(String sourceRepo, ReleaseInfo releaseInfo, Set artifactDigests) { + logger.debug("Attempting distribute via Artifactory"); + if (this.bintrayService.isDistributionComplete(releaseInfo, artifactDigests, Duration.ofMinutes(2))) { + logger.info("Distribution already complete"); + return; + } DistributionRequest request = new DistributionRequest(new String[] { sourceRepo }); RequestEntity requestEntity = RequestEntity .post(URI.create(DISTRIBUTION_URL + releaseInfo.getBuildName() + "/" + releaseInfo.getBuildNumber())) .contentType(MediaType.APPLICATION_JSON).body(request); try { this.restTemplate.exchange(requestEntity, Object.class); + logger.debug("Distribution call completed"); } catch (HttpClientErrorException ex) { - console.log("Failed to distribute."); + logger.info("Failed to distribute."); throw ex; } - if (!this.bintrayService.isDistributionComplete(releaseInfo)) { + if (!this.bintrayService.isDistributionComplete(releaseInfo, artifactDigests, Duration.ofMinutes(60))) { throw new DistributionTimeoutException("Distribution timed out."); } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/payload/BuildInfoResponse.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/payload/BuildInfoResponse.java index 1ec9ee57e9..0c340e8d04 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/payload/BuildInfoResponse.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/payload/BuildInfoResponse.java @@ -16,6 +16,12 @@ package io.spring.concourse.releasescripts.artifactory.payload; +import java.util.Arrays; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * Represents the response from Artifactory's buildInfo endpoint. * @@ -54,7 +60,7 @@ public class BuildInfoResponse { } public String getName() { - return name; + return this.name; } public void setName(String name) { @@ -83,6 +89,14 @@ public class BuildInfoResponse { public void setVersion(String version) { this.version = version; + + } + + public Set getArtifactDigests(Predicate predicate) { + return Arrays.stream(this.modules).flatMap((module) -> { + Artifact[] artifacts = module.getArtifacts(); + return (artifacts != null) ? Arrays.stream(artifacts) : Stream.empty(); + }).filter(predicate).map(Artifact::getSha256).collect(Collectors.toSet()); } } @@ -105,6 +119,8 @@ public class BuildInfoResponse { private String id; + private Artifact[] artifacts; + public String getId() { return this.id; } @@ -113,6 +129,38 @@ public class BuildInfoResponse { this.id = id; } + public Artifact[] getArtifacts() { + return this.artifacts; + } + + public void setArtifacts(Artifact[] artifacts) { + this.artifacts = artifacts; + } + + } + + public static class Artifact { + + private String name; + + private String sha256; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSha256() { + return this.sha256; + } + + public void setSha256(String sha256) { + this.sha256 = sha256; + } + } } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java index 2cc1fe779e..cc133121f0 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java @@ -17,17 +17,18 @@ package io.spring.concourse.releasescripts.bintray; import java.net.URI; -import java.util.Objects; -import java.util.concurrent.TimeUnit; +import java.time.Duration; +import java.util.HashSet; +import java.util.Set; 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.slf4j.Logger; +import org.slf4j.LoggerFactory; 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; @@ -45,6 +46,8 @@ import static org.awaitility.Awaitility.waitAtMost; @Component public class BintrayService { + private static final Logger logger = LoggerFactory.getLogger(BintrayService.class); + private static final String BINTRAY_URL = "https://api.bintray.com/"; private static final String GRADLE_PLUGIN_REQUEST = "[ { \"name\": \"gradle-plugin\", \"values\": [\"org.springframework.boot:org.springframework.boot:spring-boot-gradle-plugin\"] } ]"; @@ -57,8 +60,6 @@ public class BintrayService { private final SonatypeService sonatypeService; - private static final ConsoleLogger console = new ConsoleLogger(); - public BintrayService(RestTemplateBuilder builder, BintrayProperties bintrayProperties, SonatypeProperties sonatypeProperties, SonatypeService sonatypeService) { this.bintrayProperties = bintrayProperties; @@ -72,32 +73,48 @@ public class BintrayService { this.restTemplate = builder.build(); } - public boolean isDistributionComplete(ReleaseInfo releaseInfo) { - RequestEntity allFilesRequest = getRequest(releaseInfo, 1); - Object[] allFiles = waitAtMost(5, TimeUnit.MINUTES).with().pollDelay(20, TimeUnit.SECONDS).until(() -> { - try { - return this.restTemplate.exchange(allFilesRequest, Object[].class).getBody(); - } - catch (HttpClientErrorException ex) { - if (ex.getStatusCode() != HttpStatus.NOT_FOUND) { - throw ex; - } - return null; - } - }, Objects::nonNull); - RequestEntity publishedFilesRequest = getRequest(releaseInfo, 0); + public boolean isDistributionComplete(ReleaseInfo releaseInfo, Set requiredDigets, Duration timeout) { + return isDistributionComplete(releaseInfo, requiredDigets, timeout, Duration.ofSeconds(20)); + } + + public boolean isDistributionComplete(ReleaseInfo releaseInfo, Set requiredDigets, Duration timeout, + Duration pollInterval) { + logger.debug("Checking if distribution is complete"); + RequestEntity request = 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; + waitAtMost(timeout).with().pollDelay(Duration.ZERO).pollInterval(pollInterval).until(() -> { + logger.debug("Checking bintray"); + PackageFile[] published = this.restTemplate.exchange(request, PackageFile[].class).getBody(); + return hasPublishedAll(published, requiredDigets); }); } catch (ConditionTimeoutException ex) { + logger.debug("Timeout checking bintray"); return false; } return true; } + private boolean hasPublishedAll(PackageFile[] published, Set requiredDigets) { + if (published == null || published.length == 0) { + logger.debug("Bintray returned no published files"); + return false; + } + Set remaining = new HashSet<>(requiredDigets); + for (PackageFile publishedFile : published) { + logger.debug( + "Found published file " + publishedFile.getName() + " with digest " + publishedFile.getSha256()); + remaining.remove(publishedFile.getSha256()); + } + if (remaining.isEmpty()) { + logger.debug("Found all required digests"); + return true; + } + logger.debug("Some digests have not been published:"); + remaining.forEach(logger::debug); + return false; + } + private RequestEntity getRequest(ReleaseInfo releaseInfo, int includeUnpublished) { return RequestEntity.get(URI.create(BINTRAY_URL + "packages/" + this.bintrayProperties.getSubject() + "/" + this.bintrayProperties.getRepo() + "/" + releaseInfo.getGroupId() + "/versions/" @@ -109,6 +126,7 @@ public class BintrayService { * @param releaseInfo the release information */ public void publishGradlePlugin(ReleaseInfo releaseInfo) { + logger.debug("Publishing Gradle Pluging"); RequestEntity requestEntity = RequestEntity .post(URI.create(BINTRAY_URL + "packages/" + this.bintrayProperties.getSubject() + "/" + this.bintrayProperties.getRepo() + "/" + releaseInfo.getGroupId() + "/versions/" @@ -116,9 +134,10 @@ public class BintrayService { .contentType(MediaType.APPLICATION_JSON).body(GRADLE_PLUGIN_REQUEST); try { this.restTemplate.exchange(requestEntity, Object.class); + logger.debug("Publishing Gradle Pluging complete"); } catch (HttpClientErrorException ex) { - console.log("Failed to add attribute to gradle plugin."); + logger.info("Failed to add attribute to gradle plugin."); throw ex; } } @@ -128,8 +147,9 @@ public class BintrayService { * @param releaseInfo the release information */ public void syncToMavenCentral(ReleaseInfo releaseInfo) { - console.log("Calling Bintray to sync to Sonatype"); + logger.info("Calling Bintray to sync to Sonatype"); if (this.sonatypeService.artifactsPublished(releaseInfo)) { + logger.info("Artifacts already published"); return; } RequestEntity requestEntity = RequestEntity @@ -139,9 +159,10 @@ public class BintrayService { .contentType(MediaType.APPLICATION_JSON).body(this.sonatypeProperties); try { this.restTemplate.exchange(requestEntity, Object.class); + logger.debug("Sync complete"); } catch (HttpClientErrorException ex) { - console.log("Failed to sync."); + logger.info("Failed to sync."); throw ex; } } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/system/ConsoleLogger.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/PackageFile.java similarity index 59% rename from ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/system/ConsoleLogger.java rename to ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/PackageFile.java index 1b8e6d29fa..4a6f3ad8cb 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/system/ConsoleLogger.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/PackageFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 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. @@ -14,19 +14,25 @@ * limitations under the License. */ -package io.spring.concourse.releasescripts.system; - -import org.slf4j.helpers.MessageFormatter; +package io.spring.concourse.releasescripts.bintray; /** - * Simple console logger used to output progress messages. + * Details for a single packaged file. * - * @author Madhura Bhave + * @author Phillip Webb */ -public class ConsoleLogger { +public class PackageFile { + + private String name; + + private String sha256; + + public String getName() { + return this.name; + } - public void log(String message, Object... args) { - System.err.println(MessageFormatter.arrayFormat(message, args).getMessage()); + public String getSha256() { + return this.sha256; } } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/CommandProcessor.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/CommandProcessor.java index 6b7de70dff..eea33a5666 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/CommandProcessor.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/CommandProcessor.java @@ -19,6 +19,9 @@ package io.spring.concourse.releasescripts.command; import java.util.Collections; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -32,6 +35,8 @@ import org.springframework.util.Assert; @Component public class CommandProcessor implements ApplicationRunner { + private static final Logger logger = LoggerFactory.getLogger(CommandProcessor.class); + private final List commands; public CommandProcessor(List commands) { @@ -40,11 +45,14 @@ public class CommandProcessor implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { + logger.debug("Running command processor"); List nonOptionArgs = args.getNonOptionArgs(); Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified"); String request = nonOptionArgs.get(0); - this.commands.stream().filter((c) -> c.getName().equals(request)).findFirst() - .orElseThrow(() -> new IllegalStateException("Unknown command '" + request + "'")).run(args); + Command command = this.commands.stream().filter((candidate) -> candidate.getName().equals(request)).findFirst() + .orElseThrow(() -> new IllegalStateException("Unknown command '" + request + "'")); + logger.debug("Found command " + command.getClass().getName()); + command.run(args); } } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java index 3d9e97ee94..d22aa974d3 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java @@ -19,12 +19,18 @@ package io.spring.concourse.releasescripts.command; import java.io.File; import java.nio.file.Files; import java.util.List; +import java.util.Set; import com.fasterxml.jackson.databind.ObjectMapper; import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.ReleaseType; import io.spring.concourse.releasescripts.artifactory.ArtifactoryService; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; +import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.Artifact; +import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.BuildInfo; +import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.Module; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @@ -38,30 +44,44 @@ import org.springframework.util.Assert; @Component public class DistributeCommand implements Command { - private final ArtifactoryService service; + private static final Logger logger = LoggerFactory.getLogger(DistributeCommand.class); + + private final ArtifactoryService artifactoryService; private final ObjectMapper objectMapper; - public DistributeCommand(ArtifactoryService service, ObjectMapper objectMapper) { - this.service = service; + public DistributeCommand(ArtifactoryService artifactoryService, ObjectMapper objectMapper) { + this.artifactoryService = artifactoryService; this.objectMapper = objectMapper; } @Override public void run(ApplicationArguments args) throws Exception { + logger.debug("Running 'distribute' command"); List nonOptionArgs = args.getNonOptionArgs(); Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified"); Assert.state(nonOptionArgs.size() == 3, "Release type or build info not specified"); String releaseType = nonOptionArgs.get(1); ReleaseType type = ReleaseType.from(releaseType); if (!ReleaseType.RELEASE.equals(type)) { + logger.info("Skipping distribution of " + type + " type"); return; } String buildInfoLocation = nonOptionArgs.get(2); + logger.debug("Loading build-info from " + buildInfoLocation); byte[] content = Files.readAllBytes(new File(buildInfoLocation).toPath()); BuildInfoResponse buildInfoResponse = this.objectMapper.readValue(content, BuildInfoResponse.class); - ReleaseInfo releaseInfo = ReleaseInfo.from(buildInfoResponse.getBuildInfo()); - this.service.distribute(type.getRepo(), releaseInfo); + BuildInfo buildInfo = buildInfoResponse.getBuildInfo(); + logger.debug("Loading build info:"); + for (Module module : buildInfo.getModules()) { + logger.debug(module.getId()); + for (Artifact artifact : module.getArtifacts()) { + logger.debug(artifact.getSha256() + " " + artifact.getName()); + } + } + ReleaseInfo releaseInfo = ReleaseInfo.from(buildInfo); + Set artifactDigests = buildInfo.getArtifactDigests((artifact) -> !artifact.getName().endsWith(".zip")); + this.artifactoryService.distribute(type.getRepo(), releaseInfo, artifactDigests); } } diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PromoteCommand.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PromoteCommand.java index 230059d88f..ef5ecc2d87 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PromoteCommand.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PromoteCommand.java @@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.ReleaseType; import io.spring.concourse.releasescripts.artifactory.ArtifactoryService; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @@ -38,6 +40,8 @@ import org.springframework.util.Assert; @Component public class PromoteCommand implements Command { + private static final Logger logger = LoggerFactory.getLogger(PromoteCommand.class); + private final ArtifactoryService service; private final ObjectMapper objectMapper; @@ -49,6 +53,7 @@ public class PromoteCommand implements Command { @Override public void run(ApplicationArguments args) throws Exception { + logger.debug("Running 'promote' command"); List nonOptionArgs = args.getNonOptionArgs(); Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified"); Assert.state(nonOptionArgs.size() == 3, "Release type or build info location not specified"); diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PublishGradlePlugin.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PublishGradlePlugin.java index 68af1dce26..a00d6d340f 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PublishGradlePlugin.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PublishGradlePlugin.java @@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.ReleaseType; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; import io.spring.concourse.releasescripts.bintray.BintrayService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @@ -38,6 +40,8 @@ import org.springframework.util.Assert; @Component public class PublishGradlePlugin implements Command { + private static final Logger logger = LoggerFactory.getLogger(PublishGradlePlugin.class); + private static final String PUBLISH_GRADLE_PLUGIN_COMMAND = "publishGradlePlugin"; private final BintrayService service; @@ -56,6 +60,7 @@ public class PublishGradlePlugin implements Command { @Override public void run(ApplicationArguments args) throws Exception { + logger.debug("Running 'publish gradle' command"); List nonOptionArgs = args.getNonOptionArgs(); Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified"); Assert.state(nonOptionArgs.size() == 3, "Release type or build info not specified"); diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/SyncToCentralCommand.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/SyncToCentralCommand.java index 23c20482eb..0a7a02de76 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/SyncToCentralCommand.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/SyncToCentralCommand.java @@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.ReleaseType; import io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse; import io.spring.concourse.releasescripts.bintray.BintrayService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @@ -38,6 +40,8 @@ import org.springframework.util.Assert; @Component public class SyncToCentralCommand implements Command { + private static final Logger logger = LoggerFactory.getLogger(SyncToCentralCommand.class); + private static final String SYNC_TO_CENTRAL_COMMAND = "syncToCentral"; private final BintrayService service; @@ -56,6 +60,7 @@ public class SyncToCentralCommand implements Command { @Override public void run(ApplicationArguments args) throws Exception { + logger.debug("Running 'sync to central' command"); List nonOptionArgs = args.getNonOptionArgs(); Assert.state(!nonOptionArgs.isEmpty(), "No command argument specified"); Assert.state(nonOptionArgs.size() == 3, "Release type or build info not specified"); diff --git a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/sonatype/SonatypeService.java b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/sonatype/SonatypeService.java index ce2ff317d2..0ef88e5639 100644 --- a/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/sonatype/SonatypeService.java +++ b/ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/sonatype/SonatypeService.java @@ -17,7 +17,8 @@ package io.spring.concourse.releasescripts.sonatype; import io.spring.concourse.releasescripts.ReleaseInfo; -import io.spring.concourse.releasescripts.system.ConsoleLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpStatus; @@ -35,12 +36,12 @@ import org.springframework.web.client.RestTemplate; @Component public class SonatypeService { + private static final Logger logger = LoggerFactory.getLogger(SonatypeService.class); + private static final String SONATYPE_REPOSITORY_URI = "https://oss.sonatype.org/service/local/repositories/releases/content/org/springframework/boot/spring-boot/"; private final RestTemplate restTemplate; - private static final ConsoleLogger console = new ConsoleLogger(); - public SonatypeService(RestTemplateBuilder builder, SonatypeProperties sonatypeProperties) { String username = sonatypeProperties.getUserToken(); String password = sonatypeProperties.getPasswordToken(); @@ -57,11 +58,11 @@ public class SonatypeService { */ public boolean artifactsPublished(ReleaseInfo releaseInfo) { try { - ResponseEntity entity = this.restTemplate + ResponseEntity entity = this.restTemplate .getForEntity(String.format(SONATYPE_REPOSITORY_URI + "%s/spring-boot-%s.jar.sha1", - releaseInfo.getVersion(), releaseInfo.getVersion()), Object.class); + releaseInfo.getVersion(), releaseInfo.getVersion()), byte[].class); if (HttpStatus.OK.equals(entity.getStatusCode())) { - console.log("Already published to Sonatype."); + logger.info("Already published to Sonatype."); return true; } } diff --git a/ci/images/releasescripts/src/main/resources/application.properties b/ci/images/releasescripts/src/main/resources/application.properties index 8b13789179..5bc7bb6054 100644 --- a/ci/images/releasescripts/src/main/resources/application.properties +++ b/ci/images/releasescripts/src/main/resources/application.properties @@ -1 +1,2 @@ - +spring.main.banner-mode=off +# logging.level.io.spring.concourse=DEBUG \ No newline at end of file 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 d0b8a2b34d..f78f0a01a7 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 @@ -16,10 +16,15 @@ package io.spring.concourse.releasescripts.artifactory; +import java.time.Duration; +import java.util.Collections; +import java.util.Set; + import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.bintray.BintrayService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.mockito.InOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -35,10 +40,13 @@ import org.springframework.util.Base64Utils; import org.springframework.web.client.HttpClientErrorException; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; 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; @@ -55,6 +63,10 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat @EnableConfigurationProperties(ArtifactoryProperties.class) class ArtifactoryServiceTests { + private static final Duration SHORT_TIMEOUT = Duration.ofMinutes(2); + + private static final Duration LONG_TIMEOUT = Duration.ofMinutes(60); + @Autowired private ArtifactoryService service; @@ -126,21 +138,24 @@ class ArtifactoryServiceTests { } @Test + @SuppressWarnings("unchecked") void distributeWhenSuccessful() throws Exception { ReleaseInfo releaseInfo = getReleaseInfo(); - given(this.bintrayService.isDistributionComplete(releaseInfo)).willReturn(true); - this.server - .expect(requestTo( - "https://repo.spring.io/api/build/distribute/" + "example-build" + "/" + "example-build-1")) + given(this.bintrayService.isDistributionComplete(eq(releaseInfo), (Set) any(), any())).willReturn(false, + true); + this.server.expect(requestTo("https://repo.spring.io/api/build/distribute/example-build/example-build-1")) .andExpect(method(HttpMethod.POST)) .andExpect(content().json( "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}")) .andExpect(header("Authorization", "Basic " + Base64Utils.encodeToString(String .format("%s:%s", this.properties.getUsername(), this.properties.getPassword()).getBytes()))) .andExpect(header("Content-Type", MediaType.APPLICATION_JSON.toString())).andRespond(withSuccess()); - this.service.distribute("libs-release-local", releaseInfo); + Set artifactDigests = Collections.singleton("602e20176706d3cc7535f01ffdbe91b270ae5014"); + this.service.distribute("libs-release-local", releaseInfo, artifactDigests); this.server.verify(); - verify(this.bintrayService, times(1)).isDistributionComplete(releaseInfo); + InOrder ordered = inOrder(this.bintrayService); + ordered.verify(this.bintrayService).isDistributionComplete(releaseInfo, artifactDigests, SHORT_TIMEOUT); + ordered.verify(this.bintrayService).isDistributionComplete(releaseInfo, artifactDigests, LONG_TIMEOUT); } @Test @@ -156,29 +171,36 @@ class ArtifactoryServiceTests { .format("%s:%s", this.properties.getUsername(), this.properties.getPassword()).getBytes()))) .andExpect(header("Content-Type", MediaType.APPLICATION_JSON.toString())) .andRespond(withStatus(HttpStatus.FORBIDDEN)); + Set artifactDigests = Collections.singleton("602e20176706d3cc7535f01ffdbe91b270ae5014"); assertThatExceptionOfType(HttpClientErrorException.class) - .isThrownBy(() -> this.service.distribute("libs-release-local", releaseInfo)); + .isThrownBy(() -> this.service.distribute("libs-release-local", releaseInfo, artifactDigests)); this.server.verify(); - verifyNoInteractions(this.bintrayService); + verify(this.bintrayService, times(1)).isDistributionComplete(releaseInfo, artifactDigests, SHORT_TIMEOUT); + verifyNoMoreInteractions(this.bintrayService); } @Test + @SuppressWarnings("unchecked") void distributeWhenGettingPackagesTimesOut() throws Exception { ReleaseInfo releaseInfo = getReleaseInfo(); - given(this.bintrayService.isDistributionComplete(releaseInfo)).willReturn(false); - this.server - .expect(requestTo( - "https://repo.spring.io/api/build/distribute/" + "example-build" + "/" + "example-build-1")) + given(this.bintrayService.isDistributionComplete(eq(releaseInfo), (Set) any(), any())) + .willReturn(false); + given(this.bintrayService.isDistributionComplete(eq(releaseInfo), (Set) any(), any())) + .willReturn(false); + this.server.expect(requestTo("https://repo.spring.io/api/build/distribute/example-build/example-build-1")) .andExpect(method(HttpMethod.POST)) .andExpect(content().json( "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}")) .andExpect(header("Authorization", "Basic " + Base64Utils.encodeToString(String .format("%s:%s", this.properties.getUsername(), this.properties.getPassword()).getBytes()))) .andExpect(header("Content-Type", MediaType.APPLICATION_JSON.toString())).andRespond(withSuccess()); + Set artifactDigests = Collections.singleton("602e20176706d3cc7535f01ffdbe91b270ae5014"); assertThatExceptionOfType(DistributionTimeoutException.class) - .isThrownBy(() -> this.service.distribute("libs-release-local", releaseInfo)); + .isThrownBy(() -> this.service.distribute("libs-release-local", releaseInfo, artifactDigests)); this.server.verify(); - verify(this.bintrayService, times(1)).isDistributionComplete(releaseInfo); + InOrder ordered = inOrder(this.bintrayService); + ordered.verify(this.bintrayService).isDistributionComplete(releaseInfo, artifactDigests, SHORT_TIMEOUT); + ordered.verify(this.bintrayService).isDistributionComplete(releaseInfo, artifactDigests, LONG_TIMEOUT); } private ReleaseInfo getReleaseInfo() { diff --git a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/bintray/BintrayServiceTests.java b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/bintray/BintrayServiceTests.java index e622ed3adb..67c4369c8e 100644 --- a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/bintray/BintrayServiceTests.java +++ b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/bintray/BintrayServiceTests.java @@ -16,6 +16,10 @@ package io.spring.concourse.releasescripts.bintray; +import java.time.Duration; +import java.util.LinkedHashSet; +import java.util.Set; + import io.spring.concourse.releasescripts.ReleaseInfo; import io.spring.concourse.releasescripts.sonatype.SonatypeProperties; import io.spring.concourse.releasescripts.sonatype.SonatypeService; @@ -28,7 +32,6 @@ 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; @@ -41,7 +44,6 @@ 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; /** @@ -75,15 +77,15 @@ 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, "no-package-files.json"); + setupGetPackageFiles(0, "some-package-files.json"); setupGetPackageFiles(0, "all-package-files.json"); - assertThat(this.service.isDistributionComplete(getReleaseInfo())).isTrue(); + Set digests = new LinkedHashSet<>(); + digests.add("602e20176706d3cc7535f01ffdbe91b270ae5012"); + digests.add("602e20176706d3cc7535f01ffdbe91b270ae5013"); + digests.add("602e20176706d3cc7535f01ffdbe91b270ae5014"); + assertThat(this.service.isDistributionComplete(getReleaseInfo(), digests, Duration.ofMinutes(1), Duration.ZERO)) + .isTrue(); this.server.verify(); } diff --git a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java index c8949f2240..3fcaf5dc7e 100644 --- a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java +++ b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java @@ -16,6 +16,8 @@ package io.spring.concourse.releasescripts.command; +import java.util.Set; + import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import io.spring.concourse.releasescripts.ReleaseInfo; @@ -54,7 +56,7 @@ class DistributeCommandTests { void setup() { MockitoAnnotations.initMocks(this); this.objectMapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - this.command = new DistributeCommand(this.service, objectMapper); + this.command = new DistributeCommand(this.service, this.objectMapper); } @Test @@ -76,15 +78,20 @@ class DistributeCommandTests { } @Test + @SuppressWarnings("unchecked") void distributeWhenReleaseTypeReleaseShouldCallService() throws Exception { - ArgumentCaptor captor = ArgumentCaptor.forClass(ReleaseInfo.class); + ArgumentCaptor releaseInfoCaptor = ArgumentCaptor.forClass(ReleaseInfo.class); + ArgumentCaptor> artifactDigestCaptor = ArgumentCaptor.forClass(Set.class); this.command.run(new DefaultApplicationArguments("distribute", "RELEASE", getBuildInfoLocation())); - verify(this.service).distribute(eq(ReleaseType.RELEASE.getRepo()), captor.capture()); - ReleaseInfo releaseInfo = captor.getValue(); + verify(this.service).distribute(eq(ReleaseType.RELEASE.getRepo()), releaseInfoCaptor.capture(), + artifactDigestCaptor.capture()); + ReleaseInfo releaseInfo = releaseInfoCaptor.getValue(); assertThat(releaseInfo.getBuildName()).isEqualTo("example"); assertThat(releaseInfo.getBuildNumber()).isEqualTo("example-build-1"); assertThat(releaseInfo.getGroupId()).isEqualTo("org.example.demo"); assertThat(releaseInfo.getVersion()).isEqualTo("2.2.0"); + Set artifactDigests = artifactDigestCaptor.getValue(); + assertThat(artifactDigests).containsExactly("aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy"); } private String getBuildInfoLocation() throws Exception { diff --git a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/sonatype/SonatypeServiceTests.java b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/sonatype/SonatypeServiceTests.java index ee477feeaf..ae0a257ecd 100644 --- a/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/sonatype/SonatypeServiceTests.java +++ b/ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/sonatype/SonatypeServiceTests.java @@ -45,9 +45,6 @@ class SonatypeServiceTests { @Autowired private SonatypeService service; - @Autowired - private SonatypeProperties properties; - @Autowired private MockRestServiceServer server; @@ -60,7 +57,8 @@ class SonatypeServiceTests { void artifactsPublishedWhenPublishedShouldReturnTrue() { this.server.expect(requestTo(String.format( "https://oss.sonatype.org/service/local/repositories/releases/content/org/springframework/boot/spring-boot/%s/spring-boot-%s.jar.sha1", - "1.1.0.RELEASE", "1.1.0.RELEASE"))).andExpect(method(HttpMethod.GET)).andRespond(withSuccess()); + "1.1.0.RELEASE", "1.1.0.RELEASE"))).andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess().body("ce8d8b6838ecceb68962b975b18682f4237ccf71".getBytes())); boolean published = this.service.artifactsPublished(getReleaseInfo()); assertThat(published).isTrue(); this.server.verify(); diff --git a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/all-package-files.json b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/all-package-files.json index cb4839cd13..c5d5d15eab 100644 --- a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/all-package-files.json +++ b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/all-package-files.json @@ -8,7 +8,7 @@ "owner": "jfrog", "created": "ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)", "size": 1234, - "sha1": "602e20176706d3cc7535f01ffdbe91b270ae5012" + "sha256": "602e20176706d3cc7535f01ffdbe91b270ae5012" }, { "name": "nutcracker-1.1.pom", @@ -19,7 +19,7 @@ "owner": "jfrog", "created": "ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)", "size": 1234, - "sha1": "602e20176706d3cc7535f01ffdbe91b270ae5012" + "sha256": "602e20176706d3cc7535f01ffdbe91b270ae5013" }, { "name": "nutcracker-1.1.jar", @@ -30,6 +30,6 @@ "owner": "jfrog", "created": "ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)", "size": 1234, - "sha1": "602e20176706d3cc7535f01ffdbe91b270ae5012" + "sha256": "602e20176706d3cc7535f01ffdbe91b270ae5014" } ] \ No newline at end of file diff --git a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/no-package-files.json b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/no-package-files.json new file mode 100644 index 0000000000..0637a088a0 --- /dev/null +++ b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/no-package-files.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/published-files.json b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/some-package-files.json similarity index 84% rename from ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/published-files.json rename to ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/some-package-files.json index 05d2bfc0e8..23cbd5cfe8 100644 --- a/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/published-files.json +++ b/ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/some-package-files.json @@ -8,6 +8,6 @@ "owner": "jfrog", "created": "ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)", "size": 1234, - "sha1": "602e20176706d3cc7535f01ffdbe91b270ae5012" + "sha256": "602e20176706d3cc7535f01ffdbe91b270ae5012" } ] \ No newline at end of file diff --git a/ci/scripts/promote.sh b/ci/scripts/promote.sh index 818d9b6bcd..cff0f3e86b 100755 --- a/ci/scripts/promote.sh +++ b/ci/scripts/promote.sh @@ -5,11 +5,11 @@ source $(dirname $0)/common.sh version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json -java -jar /spring-boot-release-scripts.jar promote $RELEASE_TYPE $BUILD_INFO_LOCATION > /dev/null || { exit 1; } +java -jar /spring-boot-release-scripts.jar promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; } -java -jar /spring-boot-release-scripts.jar distribute $RELEASE_TYPE $BUILD_INFO_LOCATION > /dev/null || { exit 1; } +java -jar /spring-boot-release-scripts.jar distribute $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; } -java -jar /spring-boot-release-scripts.jar publishGradlePlugin $RELEASE_TYPE $BUILD_INFO_LOCATION > /dev/null || { exit 1; } +java -jar /spring-boot-release-scripts.jar publishGradlePlugin $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; } echo "Promotion complete" echo $version > version/version diff --git a/ci/scripts/sync-to-maven-central.sh b/ci/scripts/sync-to-maven-central.sh index d1a0069a22..32e882b5d4 100755 --- a/ci/scripts/sync-to-maven-central.sh +++ b/ci/scripts/sync-to-maven-central.sh @@ -2,7 +2,7 @@ export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) -java -jar /spring-boot-release-scripts.jar syncToCentral "RELEASE" $BUILD_INFO_LOCATION > /dev/null || { exit 1; } +java -jar /spring-boot-release-scripts.jar syncToCentral "RELEASE" $BUILD_INFO_LOCATION || { exit 1; } echo "Sync complete" echo $version > version/version