Do not publish to Sonatype when already published

Closes gh-27080
This commit is contained in:
Andy Wilkinson 2021-06-24 17:01:06 +01:00
parent 0b2c86d122
commit 7617f0df60
3 changed files with 36 additions and 39 deletions

View File

@ -72,8 +72,9 @@ public class PublishToCentralCommand implements Command {
byte[] content = Files.readAllBytes(new File(buildInfoLocation).toPath());
BuildInfoResponse buildInfoResponse = this.objectMapper.readValue(content, BuildInfoResponse.class);
BuildInfo buildInfo = buildInfoResponse.getBuildInfo();
ReleaseInfo releaseInfo = ReleaseInfo.from(buildInfo);
String artifactsLocation = nonOptionArgs.get(3);
this.sonatype.publish(ReleaseInfo.from(buildInfo), new File(artifactsLocation).toPath());
this.sonatype.publish(releaseInfo, new File(artifactsLocation).toPath());
}
}

View File

@ -89,11 +89,30 @@ public class SonatypeService {
}
/**
* Checks if artifacts are already published to Maven Central.
* @return true if artifacts are published
* Publishes the release by creating a staging repository and deploying to it the
* artifacts at the given {@code artifactsRoot}. The repository is then closed and,
* upon successfully closure, it is released.
* @param releaseInfo the release information
* @param artifactsRoot the root directory of the artifacts to stage
*/
public boolean artifactsPublished(ReleaseInfo releaseInfo) {
public void publish(ReleaseInfo releaseInfo, Path artifactsRoot) {
if (artifactsPublished(releaseInfo)) {
return;
}
logger.info("Creating staging repository");
String buildId = releaseInfo.getBuildNumber();
String repositoryId = createStagingRepository(buildId);
Collection<DeployableArtifact> artifacts = this.artifactCollector.collectArtifacts(artifactsRoot);
logger.info("Staging repository {} created. Deploying {} artifacts", repositoryId, artifacts.size());
deploy(artifacts, repositoryId);
logger.info("Deploy complete. Closing staging repository");
close(repositoryId);
logger.info("Staging repository closed");
release(repositoryId, buildId);
logger.info("Staging repository released");
}
private boolean artifactsPublished(ReleaseInfo releaseInfo) {
try {
ResponseEntity<?> entity = this.restTemplate
.getForEntity(String.format(NEXUS_REPOSITORY_PATH + "%s/spring-boot-%s.jar.sha1",
@ -109,27 +128,6 @@ public class SonatypeService {
return false;
}
/**
* Publishes the release by creating a staging repository and deploying to it the
* artifacts at the given {@code artifactsRoot}. The repository is then closed and,
* upon successfully closure, it is released.
* @param releaseInfo the release information
* @param artifactsRoot the root directory of the artifacts to stage
*/
public void publish(ReleaseInfo releaseInfo, Path artifactsRoot) {
logger.info("Creating staging repository");
String buildId = releaseInfo.getBuildNumber();
String repositoryId = createStagingRepository(buildId);
Collection<DeployableArtifact> artifacts = this.artifactCollector.collectArtifacts(artifactsRoot);
logger.info("Staging repository {} created. Deploying {} artifacts", repositoryId, artifacts.size());
deploy(artifacts, repositoryId);
logger.info("Deploy complete. Closing staging repository");
close(repositoryId);
logger.info("Staging repository closed");
release(repositoryId, buildId);
logger.info("Staging repository released");
}
private String createStagingRepository(String buildId) {
Map<String, Object> body = new HashMap<>();
body.put("data", Collections.singletonMap("description", buildId));

View File

@ -74,29 +74,23 @@ class SonatypeServiceTests {
}
@Test
void artifactsPublishedWhenPublishedShouldReturnTrue() {
void publishWhenAlreadyPublishedShouldNotPublish() {
this.server.expect(requestTo(String.format(
"/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().body("ce8d8b6838ecceb68962b9150b18682f4237ccf71".getBytes()));
boolean published = this.service.artifactsPublished(getReleaseInfo());
assertThat(published).isTrue();
this.server.verify();
}
@Test
void artifactsPublishedWhenNotPublishedShouldReturnFalse() {
this.server.expect(requestTo(String.format(
"/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(withStatus(HttpStatus.NOT_FOUND));
boolean published = this.service.artifactsPublished(getReleaseInfo());
assertThat(published).isFalse();
Path artifactsRoot = new File("src/test/resources/io/spring/concourse/releasescripts/sonatype/artifactory-repo")
.toPath();
this.service.publish(getReleaseInfo(), artifactsRoot);
this.server.verify();
}
@Test
void publishWithSuccessfulClose() throws IOException {
this.server.expect(requestTo(String.format(
"/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(withStatus(HttpStatus.NOT_FOUND));
this.server.expect(requestTo("/service/local/staging/profiles/1a2b3c4d/start"))
.andExpect(method(HttpMethod.POST)).andExpect(header("Content-Type", "application/json"))
.andExpect(header("Accept", "application/json, application/*+json"))
@ -145,6 +139,10 @@ class SonatypeServiceTests {
@Test
void publishWithCloseFailureDueToRuleViolations() throws IOException {
this.server.expect(requestTo(String.format(
"/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(withStatus(HttpStatus.NOT_FOUND));
this.server.expect(requestTo("/service/local/staging/profiles/1a2b3c4d/start"))
.andExpect(method(HttpMethod.POST)).andExpect(header("Content-Type", "application/json"))
.andExpect(header("Accept", "application/json, application/*+json"))