diff --git a/pom.xml b/pom.xml
index 1d4464d4..19d15d77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
org.springframework.cloud
spring-cloud-build
- 4.0.3
+ 4.0.6
@@ -47,6 +47,8 @@
1.1.0
1.12
4.11.0
+ 2.17.0
+ 4.0.6
@@ -145,6 +147,16 @@
awaitility
${awaitility.version}
+
+ org.jfrog.artifactory.client
+ artifactory-java-client-services
+ ${artifactory-client.version}
+
+
+ org.apache.groovy
+ groovy
+ ${groovy.version}
+
diff --git a/projects/spring-cloud/src/main/resources/application.yml b/projects/spring-cloud/src/main/resources/application.yml
index c840cfdd..95a2acfa 100644
--- a/projects/spring-cloud/src/main/resources/application.yml
+++ b/projects/spring-cloud/src/main/resources/application.yml
@@ -113,3 +113,57 @@ releaser:
projects-to-skip:
- spring-boot
- spring-cloud-stream
+ bundles:
+ repos:
+ spring-cloud-build:
+ - "org/springframework/cloud/spring-cloud-build*"
+ - "org/springframework/cloud/spring-cloud-starter-build*"
+ - "org/springframework/cloud/spring-cloud-dependencies-parent*"
+ spring-cloud-config:
+ - "org/springframework/cloud/spring-cloud-config*"
+ - "org/springframework/cloud/spring-cloud-starter-config*"
+ spring-cloud-function:
+ - "org/springframework/cloud/spring-cloud-function*"
+ - "org/springframework/cloud/spring-cloud-starter-function*"
+ spring-cloud-stream:
+ - "org/springframework/cloud/spring-cloud-stream*"
+ - "org/springframework/cloud/spring-cloud-starter-stream*"
+ spring-cloud-task:
+ - "org/springframework/cloud/spring-cloud-task*"
+ - "org/springframework/cloud/spring-cloud-starter-task*"
+ spring-cloud-bus:
+ - "org/springframework/cloud/spring-cloud-bus*"
+ - "org/springframework/cloud/spring-cloud-starter-bus*"
+ spring-cloud-commons:
+ - "org/springframework/cloud/spring-cloud-commons*"
+ - "org/springframework/cloud/spring-cloud-starter-commons*"
+ spring-cloud-netflix:
+ - "org/springframework/cloud/spring-cloud-netflix*"
+ - "org/springframework/cloud/spring-cloud-starter-netflix*"
+ spring-cloud-openfeign:
+ - "org/springframework/cloud/spring-cloud-openfeign*"
+ - "org/springframework/cloud/spring-cloud-starter-openfeign*"
+ spring-cloud-consul:
+ - "org/springframework/cloud/spring-cloud-consul*"
+ - "org/springframework/cloud/spring-cloud-starter-consul*"
+ spring-cloud-circuitbreaker:
+ - "org/springframework/cloud/spring-cloud-circuitbreaker*"
+ - "org/springframework/cloud/spring-cloud-starter-circuitbreaker*"
+ spring-cloud-gateway:
+ - "org/springframework/cloud/spring-cloud-gateway*"
+ - "org/springframework/cloud/spring-cloud-starter-gateway*"
+ spring-cloud-zookeeper:
+ - "org/springframework/cloud/spring-cloud-zookeeper*"
+ - "org/springframework/cloud/spring-cloud-starter-zookeeper*"
+ spring-cloud-contract:
+ - "org/springframework/cloud/spring-cloud-contract*"
+ - "org/springframework/cloud/spring-cloud-starter-contract*"
+ spring-cloud-kubernetes:
+ - "org/springframework/cloud/spring-cloud-kubernetes*"
+ - "org/springframework/cloud/spring-cloud-starter-kubernetes*"
+ spring-cloud-vault:
+ - "org/springframework/cloud/spring-cloud-vault*"
+ - "org/springframework/cloud/spring-cloud-starter-vault*"
+ spring-cloud-release:
+ - "org/springframework/cloud/spring-cloud-starter*"
+ - "org/springframework/cloud/spring-cloud-dependencies*"
diff --git a/releaser-core/pom.xml b/releaser-core/pom.xml
index 968d34e6..b0ee9beb 100644
--- a/releaser-core/pom.xml
+++ b/releaser-core/pom.xml
@@ -91,6 +91,14 @@
io.spring.initializr
initializr-metadata
+
+ org.jfrog.artifactory.client
+ artifactory-java-client-services
+
+
+ org.apache.groovy
+ groovy
+
org.springframework.boot
spring-boot-starter-test
diff --git a/releaser-core/src/main/java/releaser/internal/Releaser.java b/releaser-core/src/main/java/releaser/internal/Releaser.java
index bc5dc372..5794678a 100644
--- a/releaser-core/src/main/java/releaser/internal/Releaser.java
+++ b/releaser-core/src/main/java/releaser/internal/Releaser.java
@@ -18,11 +18,13 @@ package releaser.internal;
import java.io.File;
import java.util.List;
+import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import releaser.internal.buildsystem.GradleUpdater;
import releaser.internal.buildsystem.ProjectPomUpdater;
+import releaser.internal.commercial.ReleaseBundleCreator;
import releaser.internal.docs.DocumentationUpdater;
import releaser.internal.git.ProjectGitHandler;
import releaser.internal.github.ProjectGitHubHandler;
@@ -69,11 +71,13 @@ public class Releaser {
private ReleaserProperties releaserProperties;
+ private ReleaseBundleCreator releaseBundleCreator;
+
public Releaser(ReleaserProperties releaserProperties, ProjectPomUpdater projectPomUpdater,
ProjectCommandExecutor projectCommandExecutor, ProjectGitHandler projectGitHandler,
ProjectGitHubHandler projectGitHubHandler, TemplateGenerator templateGenerator, GradleUpdater gradleUpdater,
- SaganUpdater saganUpdater, DocumentationUpdater documentationUpdater,
- PostReleaseActions postReleaseActions) {
+ SaganUpdater saganUpdater, DocumentationUpdater documentationUpdater, PostReleaseActions postReleaseActions,
+ ReleaseBundleCreator releaseBundleCreator) {
this.releaserProperties = releaserProperties;
this.projectPomUpdater = projectPomUpdater;
this.projectCommandExecutor = projectCommandExecutor;
@@ -84,6 +88,7 @@ public class Releaser {
this.saganUpdater = saganUpdater;
this.documentationUpdater = documentationUpdater;
this.postReleaseActions = postReleaseActions;
+ this.releaseBundleCreator = releaseBundleCreator;
}
public File clonedProjectFromOrg(String projectName) {
@@ -377,7 +382,8 @@ public class Releaser {
return ExecutionResult.skipped();
}
- public ExecutionResult createReleaseBundle(boolean commercial, ProjectVersion versionFromBom, Boolean dryRun) {
+ public ExecutionResult createReleaseBundle(boolean commercial, ProjectVersion versionFromBom, Boolean dryRun,
+ Map> commercialRepos, String projectName) {
if (dryRun) {
log.info("\nWon't create a release bundle for a dry run");
return ExecutionResult.skipped();
@@ -391,7 +397,25 @@ public class Releaser {
return ExecutionResult.skipped();
}
log.info("\nCreating a release bundle");
- return ExecutionResult.success();
+ if (!commercialRepos.containsKey(projectName)) {
+ log.warn("No commercial repos configured for project [{}], double check releaser.bundles.repos",
+ projectName);
+ }
+ List repos = commercialRepos.get(projectName);
+ log.info("Creating release bundles for project [{}] in repos [{}]", projectName, repos);
+ try {
+ boolean result = this.releaseBundleCreator.createReleaseBundle(repos, versionFromBom.version);
+ if (!result) {
+ log.warn("Failed to create release bundle");
+ return ExecutionResult.unstable(new BuildUnstableException("Failed to create a release bundle"));
+ }
+ log.info("\nSuccessfully created a release bundle");
+ return ExecutionResult.success();
+ }
+ catch (Exception ex) {
+ log.error("Failed to create a release bundle", ex);
+ return ExecutionResult.unstable(new BuildUnstableException("Failed to create a release bundle", ex));
+ }
}
}
diff --git a/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java b/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
index 5176229f..64a125f5 100644
--- a/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
+++ b/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
@@ -80,6 +80,8 @@ public class ReleaserProperties implements Serializable {
private boolean commercial = false;
+ private Bundles bundles = new Bundles();
+
/**
* Project name to its version - overrides all versions retrieved from a release train
* repository like Spring Cloud Release.
@@ -208,6 +210,14 @@ public class ReleaserProperties implements Serializable {
this.commercial = commercial;
}
+ public Bundles getBundles() {
+ return bundles;
+ }
+
+ public void setBundles(Bundles bundles) {
+ this.bundles = bundles;
+ }
+
@Override
public String toString() {
return "ReleaserProperties{" + "workingDir='" + this.workingDir + '\'' + ", git=" + this.git + ", pom="
@@ -1563,4 +1573,68 @@ public class ReleaserProperties implements Serializable {
}
+ public static class Bundles implements Serializable {
+
+ private boolean createProjectReleaseBundle = false;
+
+ private boolean createReleaseTrainReleaseBundle = false;
+
+ private String repoUrl = "https://usw1.packages.broadcom.com";
+
+ private String repoUsername;
+
+ private String repoPassword;
+
+ private Map> repos;
+
+ public boolean isCreateProjectReleaseBundle() {
+ return createProjectReleaseBundle;
+ }
+
+ public void setCreateProjectReleaseBundle(boolean createProjectReleaseBundle) {
+ this.createProjectReleaseBundle = createProjectReleaseBundle;
+ }
+
+ public boolean isCreateReleaseTrainReleaseBundle() {
+ return createReleaseTrainReleaseBundle;
+ }
+
+ public void setCreateReleaseTrainReleaseBundle(boolean createReleaseTrainReleaseBundle) {
+ this.createReleaseTrainReleaseBundle = createReleaseTrainReleaseBundle;
+ }
+
+ public Map> getRepos() {
+ return repos;
+ }
+
+ public void setRepos(Map> repos) {
+ this.repos = repos;
+ }
+
+ public String getRepoUrl() {
+ return repoUrl;
+ }
+
+ public void setRepoUrl(String repoUrl) {
+ this.repoUrl = repoUrl;
+ }
+
+ public String getRepoUsername() {
+ return repoUsername;
+ }
+
+ public void setRepoUsername(String repoUsername) {
+ this.repoUsername = repoUsername;
+ }
+
+ public String getRepoPassword() {
+ return repoPassword;
+ }
+
+ public void setRepoPassword(String repoPassword) {
+ this.repoPassword = repoPassword;
+ }
+
+ }
+
}
diff --git a/releaser-core/src/main/java/releaser/internal/commercial/ReleaseBundleCreator.java b/releaser-core/src/main/java/releaser/internal/commercial/ReleaseBundleCreator.java
new file mode 100644
index 00000000..e952f24d
--- /dev/null
+++ b/releaser-core/src/main/java/releaser/internal/commercial/ReleaseBundleCreator.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013-2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package releaser.internal.commercial;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.jfrog.artifactory.client.Artifactory;
+import org.jfrog.artifactory.client.ArtifactoryClientBuilder;
+import org.jfrog.artifactory.client.ArtifactoryRequest;
+import org.jfrog.artifactory.client.ArtifactoryResponse;
+import org.jfrog.artifactory.client.aql.AqlItem;
+import org.jfrog.artifactory.client.aql.AqlQueryBuilder;
+import org.jfrog.artifactory.client.impl.ArtifactoryRequestImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import releaser.internal.ReleaserProperties;
+
+/**
+ * @author Ryan Baxter
+ */
+public class ReleaseBundleCreator {
+
+ private static final Logger log = LoggerFactory.getLogger(ReleaseBundleCreator.class);
+
+ private ReleaserProperties properties;
+
+ private Artifactory artifactory;
+
+ public ReleaseBundleCreator(ReleaserProperties properties) {
+ this.properties = properties;
+ this.artifactory = ArtifactoryClientBuilder.create().setUrl(properties.getBundles().getRepoUrl())
+ .setUsername(properties.getBundles().getRepoUsername())
+ .setPassword(properties.getBundles().getRepoPassword()).build();
+ }
+
+ public boolean createReleaseBundle(List repos, String version) throws IOException {
+ AqlQueryBuilder builder = new AqlQueryBuilder()
+ .item(AqlItem.aqlItem("repo", AqlItem.aqlItem("$eq", "spring-enterprise-maven-prod-local")));
+
+ AqlItem[] items = new AqlItem[repos.size()];
+ for (String repo : repos) {
+ items[repos.indexOf(repo)] = AqlItem.match("path", repo + "/" + version);
+ }
+ String aql = builder.or(items).asc("path", "name").build();
+ return createReleaseBundle(aql);
+ }
+
+ public boolean createReleaseBundle(String aql) throws IOException {
+ log.info("Creating release bundle with AQL [{}]", aql);
+
+ ArtifactoryRequest aqlRequest = new ArtifactoryRequestImpl().method(ArtifactoryRequest.Method.POST)
+ .apiUrl("lifecycle/api/v2/release_bundle").addQueryParam("project", "spring")
+ .addHeader("X-JFrog-Signing-Key-Name", "packagesKey").requestType(ArtifactoryRequest.ContentType.JSON)
+ .responseType(ArtifactoryRequest.ContentType.JSON).requestBody(aql);
+ ArtifactoryResponse response = artifactory.restCall(aqlRequest);
+ if (!response.isSuccessResponse()) {
+ log.warn("Failed to create release bundle {}", response.getRawBody());
+ return false;
+ }
+ log.info("Created release bundle {}", response.getRawBody());
+ return true;
+
+ }
+
+}
diff --git a/releaser-core/src/test/java/releaser/internal/ReleaserTests.java b/releaser-core/src/test/java/releaser/internal/ReleaserTests.java
index 513bc71b..00d0e20f 100644
--- a/releaser-core/src/test/java/releaser/internal/ReleaserTests.java
+++ b/releaser-core/src/test/java/releaser/internal/ReleaserTests.java
@@ -17,6 +17,7 @@
package releaser.internal;
import java.io.File;
+import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.function.Supplier;
@@ -31,6 +32,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import releaser.SpringCloudReleaserProperties;
import releaser.internal.buildsystem.GradleUpdater;
import releaser.internal.buildsystem.ProjectPomUpdater;
+import releaser.internal.commercial.ReleaseBundleCreator;
import releaser.internal.docs.DocumentationUpdater;
import releaser.internal.git.ProjectGitHandler;
import releaser.internal.github.ProjectGitHubHandler;
@@ -92,7 +94,13 @@ public class ReleaserTests {
Releaser releaser(Supplier originalVersionSupplier) {
return new Releaser(SpringCloudReleaserProperties.get(), this.projectPomUpdater, this.projectCommandExecutor,
this.projectGitHandler, this.projectGitHubHandler, this.templateGenerator, this.gradleUpdater,
- this.saganUpdater, this.documentationUpdater, this.postReleaseActions) {
+ this.saganUpdater, this.documentationUpdater, this.postReleaseActions,
+ new ReleaseBundleCreator(SpringCloudReleaserProperties.get()) {
+ @Override
+ public boolean createReleaseBundle(String aql) throws IOException {
+ return true;
+ }
+ }) {
@Override
ProjectVersion originalVersion(File project) {
return originalVersionSupplier.get();
@@ -103,7 +111,13 @@ public class ReleaserTests {
Releaser releaser() {
return new Releaser(new ReleaserProperties(), this.projectPomUpdater, this.projectCommandExecutor,
this.projectGitHandler, this.projectGitHubHandler, this.templateGenerator, this.gradleUpdater,
- this.saganUpdater, this.documentationUpdater, this.postReleaseActions);
+ this.saganUpdater, this.documentationUpdater, this.postReleaseActions,
+ new ReleaseBundleCreator(SpringCloudReleaserProperties.get()) {
+ @Override
+ public boolean createReleaseBundle(String aql) throws IOException {
+ return true;
+ }
+ });
}
@Test
diff --git a/releaser-spring/src/main/java/releaser/internal/spring/ReleaserConfiguration.java b/releaser-spring/src/main/java/releaser/internal/spring/ReleaserConfiguration.java
index dd1b20a9..9768a34b 100644
--- a/releaser-spring/src/main/java/releaser/internal/spring/ReleaserConfiguration.java
+++ b/releaser-spring/src/main/java/releaser/internal/spring/ReleaserConfiguration.java
@@ -24,6 +24,7 @@ import releaser.internal.ReleaserProperties;
import releaser.internal.ReleaserPropertiesUpdater;
import releaser.internal.buildsystem.GradleUpdater;
import releaser.internal.buildsystem.ProjectPomUpdater;
+import releaser.internal.commercial.ReleaseBundleCreator;
import releaser.internal.docs.CustomProjectDocumentationUpdater;
import releaser.internal.docs.DocumentationUpdater;
import releaser.internal.git.ProjectGitHandler;
@@ -154,10 +155,10 @@ class ReleaserConfiguration {
ProjectGitHandler projectGitHandler, ProjectGitHubHandler projectGitHubHandler,
TemplateGenerator templateGenerator, GradleUpdater gradleUpdater, SaganUpdater saganUpdater,
DocumentationUpdater documentationUpdater, PostReleaseActions postReleaseActions,
- ReleaserProperties releaserProperties) {
+ ReleaserProperties releaserProperties, ReleaseBundleCreator releaseBundleCreator) {
return new Releaser(releaserProperties, projectPomUpdater, projectCommandExecutor, projectGitHandler,
projectGitHubHandler, templateGenerator, gradleUpdater, saganUpdater, documentationUpdater,
- postReleaseActions);
+ postReleaseActions, releaseBundleCreator);
}
@Bean
@@ -173,4 +174,10 @@ class ReleaserConfiguration {
return new OptionsParser(allTasks, singleProjectReleaserTasks, context);
}
+ @Bean
+ @ConditionalOnMissingBean
+ ReleaseBundleCreator releaseBundleCreator(ReleaserProperties properties) {
+ return new ReleaseBundleCreator(properties);
+ }
+
}
diff --git a/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateProjectReleaseBundlePostReleaseTask.java b/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateProjectReleaseBundlePostReleaseTask.java
index 566e23c9..53a7ccfc 100644
--- a/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateProjectReleaseBundlePostReleaseTask.java
+++ b/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateProjectReleaseBundlePostReleaseTask.java
@@ -17,6 +17,7 @@
package releaser.internal.tasks.postrelease;
import releaser.internal.Releaser;
+import releaser.internal.project.ProjectVersion;
import releaser.internal.spring.Arguments;
import releaser.internal.tasks.ProjectPostReleaseReleaserTask;
import releaser.internal.tech.BuildUnstableException;
@@ -61,7 +62,8 @@ public class CreateProjectReleaseBundlePostReleaseTask implements ProjectPostRel
@Override
public ExecutionResult runTask(Arguments args) throws BuildUnstableException, RuntimeException {
return this.releaser.createReleaseBundle(args.properties.isCommercial(), args.versionFromBom,
- args.options.dryRun);
+ args.options.dryRun, args.properties.getBundles().getRepos(),
+ new ProjectVersion(args.project).projectName);
}
@Override
diff --git a/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateReleaseTrainReleaseBundlePostReleaseTask.java b/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateReleaseTrainReleaseBundlePostReleaseTask.java
index 7463b505..779c9c49 100644
--- a/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateReleaseTrainReleaseBundlePostReleaseTask.java
+++ b/releaser-spring/src/main/java/releaser/internal/tasks/postrelease/CreateReleaseTrainReleaseBundlePostReleaseTask.java
@@ -17,6 +17,7 @@
package releaser.internal.tasks.postrelease;
import releaser.internal.Releaser;
+import releaser.internal.project.ProjectVersion;
import releaser.internal.spring.Arguments;
import releaser.internal.tasks.TrainPostReleaseReleaserTask;
import releaser.internal.tech.BuildUnstableException;
@@ -60,7 +61,8 @@ public class CreateReleaseTrainReleaseBundlePostReleaseTask implements TrainPost
@Override
public ExecutionResult runTask(Arguments args) throws BuildUnstableException, RuntimeException {
- return releaser.createReleaseBundle(args.properties.isCommercial(), args.versionFromBom, args.options.dryRun);
+ return releaser.createReleaseBundle(args.properties.isCommercial(), args.versionFromBom, args.options.dryRun,
+ args.properties.getBundles().getRepos(), new ProjectVersion(args.project).projectName);
}
@Override