diff --git a/Jenkinsfile b/Jenkinsfile index 43e938d..5055b26 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,6 +54,7 @@ pipeline { GITHUB = credentials('3a20bcaa-d8ad-48e3-901d-9fbc941376ee') GITHUB_TOKEN = credentials('7b3ebbea-7001-479b-8578-b8c464dab973') REPO_SPRING_IO = credentials('repo_spring_io-jenkins-release-token') + COMMERCIAL = credentials('repo_spring_vmware_com-jenkins-token') ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c') STAGING_PROFILE_ID = credentials('spring-data-release-deployment-maven-central-staging-profile-id') MAVEN_SIGNING_KEY = credentials('spring-gpg-private-key') diff --git a/ci/settings.xml b/ci/settings.xml index d129e6d..dd29c17 100644 --- a/ci/settings.xml +++ b/ci/settings.xml @@ -18,5 +18,15 @@ ${env.ARTIFACTORY_USR} ${env.ARTIFACTORY_PSW} + + spring-commercial-snapshot + ${env.COMMERCIAL_USR} + ${env.COMMERCIAL_PSW} + + + spring-commercial-release + ${env.COMMERCIAL_USR} + ${env.COMMERCIAL_PSW} + diff --git a/src/main/java/org/springframework/data/release/build/BuildConfiguration.java b/src/main/java/org/springframework/data/release/build/BuildConfiguration.java index 17eb9b0..ba6ec6d 100644 --- a/src/main/java/org/springframework/data/release/build/BuildConfiguration.java +++ b/src/main/java/org/springframework/data/release/build/BuildConfiguration.java @@ -19,10 +19,8 @@ import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.release.model.Project; -import org.springframework.plugin.core.OrderAwarePluginRegistry; +import org.springframework.data.release.model.SupportedProject; import org.springframework.plugin.core.PluginRegistry; - import org.xmlbeam.XBProjector; import org.xmlbeam.XBProjector.Flags; import org.xmlbeam.config.DefaultXMLFactoriesConfig; @@ -37,8 +35,8 @@ import org.xmlbeam.config.DefaultXMLFactoriesConfig.NamespacePhilosophy; class BuildConfiguration { @Bean - public PluginRegistry buildSystems(List buildSystems) { - return OrderAwarePluginRegistry.create(buildSystems); + public PluginRegistry buildSystems(List buildSystems) { + return PluginRegistry.of(buildSystems); } @Bean diff --git a/src/main/java/org/springframework/data/release/build/BuildExecutor.java b/src/main/java/org/springframework/data/release/build/BuildExecutor.java index 3513f44..b82f43d 100644 --- a/src/main/java/org/springframework/data/release/build/BuildExecutor.java +++ b/src/main/java/org/springframework/data/release/build/BuildExecutor.java @@ -35,16 +35,15 @@ import java.util.function.BiFunction; import java.util.function.Supplier; import java.util.stream.Collector; import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.annotation.PreDestroy; import org.apache.commons.io.IOUtils; - import org.springframework.data.release.infra.InfrastructureOperations; import org.springframework.data.release.io.Workspace; import org.springframework.data.release.model.JavaVersion; import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.ProjectAware; import org.springframework.data.release.utils.ListWrapperCollector; import org.springframework.data.util.Streamable; @@ -61,8 +60,7 @@ import org.springframework.util.Assert; @RequiredArgsConstructor class BuildExecutor { - private final @NonNull PluginRegistry buildSystems; - private final MavenProperties mavenProperties; + private final @NonNull PluginRegistry buildSystems; private final ExecutorService executor; private final Workspace workspace; @@ -121,13 +119,14 @@ class BuildExecutor { if (futureResult == null) { - if (!iteration.stream().map(ProjectAware::getProject).anyMatch(project -> project.equals(dependency))) { - throw new IllegalStateException(moduleIteration.getProject().getName() + " requires " + if (!iteration.stream().map(ProjectAware::getSupportedProject) + .anyMatch(project -> project.equals(dependency))) { + throw new IllegalStateException(moduleIteration.getSupportedProject().getName() + " requires " + dependency.getName() + " which is not part of the Iteration. Please fix Projects/Iterations setup"); } throw new IllegalStateException("No future result for " + dependency.getName() + ", required by " - + moduleIteration.getProject().getName()); + + moduleIteration.getSupportedProject().getName()); } futureResult.join(); @@ -156,16 +155,18 @@ class BuildExecutor { .collect(toSummaryCollector()); } - private CompletableFuture run(M module, BiFunction function) { + private CompletableFuture run(M module, + BiFunction function) { Assert.notNull(module, "Module must not be null!"); CompletableFuture result = new CompletableFuture<>(); Supplier exception = () -> new IllegalStateException( - String.format("No build system plugin found for project %s!", module.getProject())); + String.format("No build system plugin found for project %s!", module.getSupportedProject())); - BuildSystem buildSystem = buildSystems.getPluginFor(module.getProject(), exception) - .withJavaVersion(detectJavaVersion(module.getProject())); + BuildSystem buildSystem = buildSystems // + .getPluginFor(module.getSupportedProject(), exception) // + .withJavaVersion(detectJavaVersion(module.getSupportedProject())); Runnable runnable = () -> { @@ -183,7 +184,7 @@ class BuildExecutor { } @SneakyThrows - public JavaVersion detectJavaVersion(Project project) { + public JavaVersion detectJavaVersion(SupportedProject project) { File ciProperties = workspace.getFile(InfrastructureOperations.CI_PROPERTIES, project); diff --git a/src/main/java/org/springframework/data/release/build/BuildOperations.java b/src/main/java/org/springframework/data/release/build/BuildOperations.java index 02d5ad7..0952ca9 100644 --- a/src/main/java/org/springframework/data/release/build/BuildOperations.java +++ b/src/main/java/org/springframework/data/release/build/BuildOperations.java @@ -29,12 +29,11 @@ import java.util.stream.Collectors; import org.assertj.core.util.VisibleForTesting; import org.springframework.data.release.deployment.DeploymentInformation; import org.springframework.data.release.deployment.StagingRepository; -import org.springframework.data.release.model.Iteration; -import org.springframework.data.release.model.Module; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.ProjectAware; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.Logger; @@ -52,7 +51,7 @@ import org.springframework.util.Assert; @RequiredArgsConstructor public class BuildOperations { - private final @NonNull PluginRegistry buildSystems; + private final @NonNull PluginRegistry buildSystems; private final @NonNull Logger logger; private final @NonNull MavenProperties properties; private final @NonNull BuildExecutor executor; @@ -117,7 +116,7 @@ public class BuildOperations { */ public void open(ModuleIteration iteration) { - doWithBuildSystem(iteration, (buildSystem, moduleIteration) -> buildSystem.open()); + doWithBuildSystem(iteration, (buildSystem, moduleIteration) -> buildSystem.open(iteration.getTrain())); } /** @@ -131,8 +130,10 @@ public class BuildOperations { Assert.notNull(stagingRepository, "StagingRepository must not be null"); Assert.isTrue(stagingRepository.isPresent(), "StagingRepository must be present"); + Train train = iteration.getTrain(); + doWithBuildSystem(iteration, (buildSystem, moduleIteration) -> { - buildSystem.close(stagingRepository); + buildSystem.close(train, stagingRepository); return null; }); } @@ -145,7 +146,7 @@ public class BuildOperations { */ public void build(TrainIteration iteration) { - executor.doWithBuildSystemOrdered(iteration, BuildSystem::triggerBuild); + executor.doWithBuildSystemOrdered(iteration, (it, l) -> it.triggerBuild(l)); logger.log(iteration, "Build finished"); } @@ -156,11 +157,11 @@ public class BuildOperations { * @param iteration * @return */ - public StagingRepository openStagingRepository(Iteration iteration) { + public StagingRepository openStagingRepository(TrainIteration iteration) { - BuildSystem orchestrator = buildSystems.getRequiredPluginFor(Projects.BUILD); + BuildSystem orchestrator = buildSystems.getRequiredPluginFor(iteration.getSupportedProject(Projects.BUILD)); - return iteration.isPublic() ? orchestrator.open() : StagingRepository.EMPTY; + return iteration.isPublic() ? orchestrator.open(iteration.getTrain()) : StagingRepository.EMPTY; } /** @@ -169,27 +170,28 @@ public class BuildOperations { * @param stagingRepository * @return */ - public void closeStagingRepository(StagingRepository stagingRepository) { + public void closeStagingRepository(Train train, StagingRepository stagingRepository) { - BuildSystem orchestrator = buildSystems.getRequiredPluginFor(Projects.BUILD); + BuildSystem orchestrator = buildSystems.getRequiredPluginFor(train.getSupportedProject(Projects.BUILD)); if (stagingRepository.isPresent()) { - orchestrator.close(stagingRepository); + orchestrator.close(train, stagingRepository); } } /** * Promote the staging repository. * - * @param stagingRepository + * @param train must not be {@literal null}. + * @param stagingRepository must not be {@literal null}. * @return */ - public void releaseStagingRepository(StagingRepository stagingRepository) { + public void releaseStagingRepository(Train train, StagingRepository stagingRepository) { - BuildSystem orchestrator = buildSystems.getRequiredPluginFor(Projects.BUILD); + BuildSystem orchestrator = buildSystems.getRequiredPluginFor(train.getSupportedProject(Projects.BUILD)); if (stagingRepository.isPresent()) { - orchestrator.release(stagingRepository); + orchestrator.release(train, stagingRepository); } } @@ -215,16 +217,19 @@ public class BuildOperations { */ public void release(ModuleIteration iteration, StagingRepository stagingRepository) { + Train train = iteration.getTrain(); + doWithBuildSystem(iteration, (buildSystem, moduleIteration) -> { - buildSystem.release(stagingRepository); + buildSystem.release(train, stagingRepository); return null; }); } public void buildDocumentation(TrainIteration iteration) { - executor.doWithBuildSystemOrdered(Streamable.of(iteration.getModulesExcept(BOM, COMMONS, BUILD)), - BuildSystem::triggerDocumentationBuild); + Streamable of = Streamable.of(iteration.getModulesExcept(BOM, COMMONS, BUILD)); + + executor.doWithBuildSystemOrdered(of, BuildSystem::triggerDocumentationBuild); logger.log(iteration, "Documentation build finished"); } @@ -244,14 +249,17 @@ public class BuildOperations { */ public List performRelease(TrainIteration iteration) { - Iteration it = iteration.getIteration(); - StagingRepository stagingRepository = it.isPublic() ? openStagingRepository(it) : StagingRepository.EMPTY; + StagingRepository stagingRepository = iteration.isPublic() // + ? openStagingRepository(iteration) // + : StagingRepository.EMPTY; BuildExecutor.Summary summary = executor.doWithBuildSystemOrdered(iteration, (buildSystem, moduleIteration) -> buildSystem.deploy(moduleIteration, stagingRepository)); + Train train = iteration.getTrain(); + if (stagingRepository.isPresent()) { - closeStagingRepository(stagingRepository); + closeStagingRepository(train, stagingRepository); } smokeTests(iteration, stagingRepository); @@ -259,10 +267,12 @@ public class BuildOperations { logger.log(iteration, "Release: %s", summary); if (stagingRepository.isPresent()) { - releaseStagingRepository(stagingRepository); + releaseStagingRepository(train, stagingRepository); } - return summary.getExecutions().stream().map(BuildExecutor.ExecutionResult::getResult).collect(Collectors.toList()); + return summary.getExecutions().stream() + .map(BuildExecutor.ExecutionResult::getResult) + .collect(Collectors.toList()); } /** @@ -296,8 +306,7 @@ public class BuildOperations { Assert.notNull(train, "Train must not be null!"); - BuildExecutor.Summary summary = executor.doWithBuildSystemAnyOrder(train, - BuildSystem::triggerDistributionBuild); + BuildExecutor.Summary summary = executor.doWithBuildSystemAnyOrder(train, BuildSystem::triggerDistributionBuild); logger.log(train, "Distribution build: %s", summary); } @@ -357,24 +366,30 @@ public class BuildOperations { /** * Verifies Java version presence and that the project can be build using Maven. + * + * @param train must not be {@literal null}. */ - public void verify() { + public void verify(Train train) { - Project project = Projects.BUILD; + SupportedProject project = train.getSupportedProject(Projects.BUILD); BuildSystem buildSystem = buildSystems.getRequiredPluginFor(project); - buildSystem.withJavaVersion(executor.detectJavaVersion(project)).verify(); + buildSystem.verify(train); + // buildSystem.withJavaVersion(executor.detectJavaVersion(project)).verify(train); } /** * Verifies Maven staging authentication. + * + * @param train must not be {@literal null}. */ - public void verifyStagingAuthentication() { + public void verifyStagingAuthentication(Train train) { - Project project = Projects.BUILD; + SupportedProject project = train.getSupportedProject(Projects.BUILD); BuildSystem buildSystem = buildSystems.getRequiredPluginFor(project); - buildSystem.withJavaVersion(executor.detectJavaVersion(project)).verifyStagingAuthentication(); + buildSystem.verifyStagingAuthentication(train); + // buildSystem.withJavaVersion(executor.detectJavaVersion(project)).verifyStagingAuthentication(train); } /** @@ -385,15 +400,17 @@ public class BuildOperations { * @param function must not be {@literal null}. * @return */ - private T doWithBuildSystem(ModuleIteration module, BiFunction function) { + private T doWithBuildSystem(S module, + BiFunction function) { Assert.notNull(module, "ModuleIteration must not be null!"); Supplier exception = () -> new IllegalStateException( - String.format("No build system plugin found for project %s!", module.getProject())); + String.format("No build system plugin found for project %s!", module.getSupportedProject())); - BuildSystem buildSystem = buildSystems.getPluginFor(module.getProject(), exception); + BuildSystem buildSystem = buildSystems.getPluginFor(module.getSupportedProject(), exception); - return function.apply(buildSystem.withJavaVersion(executor.detectJavaVersion(module.getProject())), module); + return function.apply(buildSystem.withJavaVersion(executor.detectJavaVersion(module.getSupportedProject())), + module); } } diff --git a/src/main/java/org/springframework/data/release/build/BuildSystem.java b/src/main/java/org/springframework/data/release/build/BuildSystem.java index 120fa9d..e1039a5 100644 --- a/src/main/java/org/springframework/data/release/build/BuildSystem.java +++ b/src/main/java/org/springframework/data/release/build/BuildSystem.java @@ -20,8 +20,9 @@ import org.springframework.data.release.deployment.StagingRepository; import org.springframework.data.release.model.JavaVersion; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.ProjectAware; +import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.plugin.core.Plugin; @@ -32,7 +33,7 @@ import org.springframework.plugin.core.Plugin; * @author Mark Paluch * @author Greg Turnquist */ -interface BuildSystem extends Plugin { +interface BuildSystem extends Plugin { /** * Updates the project descriptors for the given {@link ModuleIteration} using the given {@link UpdateInformation}. @@ -61,18 +62,24 @@ interface BuildSystem extends Plugin { /** * Open a remote repository for staging artifacts. + * + * @param train must not be {@literal null}. */ - StagingRepository open(); + StagingRepository open(Train train); /** * Close a remote repository for staging artifacts. + * + * @param train must not be {@literal null}. */ - void close(StagingRepository stagingRepository); + void close(Train train, StagingRepository stagingRepository); /** * Release a remote repository of staged artifacts. + * + * @param train must not be {@literal null}. */ - void release(StagingRepository stagingRepository); + void release(Train train, StagingRepository stagingRepository); M triggerBuild(M module); @@ -113,13 +120,17 @@ interface BuildSystem extends Plugin { /** * Verify general functionality and correctness of the build setup. + * + * @param train must not be {@literal null}. */ - void verify(); + void verify(Train train); /** * Verify general functionality and correctness of the build setup. + * + * @param train must not be {@literal null}. */ - void verifyStagingAuthentication(); + void verifyStagingAuthentication(Train train); /** * Prepare the build system with a Java version. diff --git a/src/main/java/org/springframework/data/release/build/MavenArtifact.java b/src/main/java/org/springframework/data/release/build/MavenArtifact.java index 85bf60f..851c4ef 100644 --- a/src/main/java/org/springframework/data/release/build/MavenArtifact.java +++ b/src/main/java/org/springframework/data/release/build/MavenArtifact.java @@ -47,7 +47,7 @@ public class MavenArtifact { Assert.notNull(module, "Module iteration must not be null!"); - this.project = module.getModule().getProject(); + this.project = module.getProject(); this.version = ArtifactVersion.of(module); } diff --git a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java index 9e1ad89..d0ebeff 100644 --- a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java +++ b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java @@ -48,18 +48,11 @@ import org.springframework.data.release.build.Pom.Artifact; import org.springframework.data.release.deployment.DefaultDeploymentInformation; import org.springframework.data.release.deployment.DeploymentInformation; import org.springframework.data.release.deployment.DeploymentProperties; +import org.springframework.data.release.deployment.DeploymentProperties.Authentication; import org.springframework.data.release.deployment.DeploymentProperties.MavenCentral; import org.springframework.data.release.deployment.StagingRepository; import org.springframework.data.release.io.Workspace; -import org.springframework.data.release.model.ArtifactVersion; -import org.springframework.data.release.model.Gpg; -import org.springframework.data.release.model.JavaVersion; -import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Phase; -import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.ProjectAware; -import org.springframework.data.release.model.TrainIteration; -import org.springframework.data.release.model.Version; +import org.springframework.data.release.model.*; import org.springframework.data.release.utils.Logger; import org.springframework.stereotype.Component; import org.springframework.util.Assert; @@ -107,17 +100,18 @@ class MavenBuildSystem implements BuildSystem { @Override public M updateProjectDescriptors(M module, UpdateInformation information) { - PomUpdater updater = new PomUpdater(logger, information, module.getProject()); + PomUpdater updater = new PomUpdater(logger, information, module.getSupportedProject()); + TrainIteration train = information.getTrain(); if (updater.isBuildProject()) { if (information.isBomInBuildProject()) { - updateBom(updater, information, "bom/pom.xml", BUILD); + updateBom(updater, information, "bom/pom.xml", train.getSupportedProject(BUILD)); } updateParentPom(updater, information); } else if (updater.isBomProject()) { - updateBom(updater, information, "bom/pom.xml", BOM); + updateBom(updater, information, "bom/pom.xml", train.getSupportedProject(BOM)); } else { doWithProjection(workspace.getFile(POM_XML, updater.getProject()), pom -> { @@ -138,12 +132,12 @@ class MavenBuildSystem implements BuildSystem { @Override public ModuleIteration prepareVersion(ModuleIteration module, Phase phase) { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); UpdateInformation information = UpdateInformation.of(module.getTrainIteration(), phase); CommandLine goals = CommandLine.of(goal("versions:set"), goal("versions:commit")); - if (BOM.equals(project)) { + if (BOM.equals(module.getProject())) { mvn.execute(project, goals.and(arg("newVersion").withValue(information.getReleaseTrainVersion())) // .and(arg("generateBackupPoms").withValue("false"))); @@ -154,11 +148,12 @@ class MavenBuildSystem implements BuildSystem { .and(Argument.of("-pl").withValue("bom"))); } else { - mvn.execute(project, goals.and(arg("newVersion").withValue(information.getProjectVersionToSet(project))) - .and(arg("generateBackupPoms").withValue("false"))); + mvn.execute(project, + goals.and(arg("newVersion").withValue(information.getProjectVersionToSet(project.getProject()))) + .and(arg("generateBackupPoms").withValue("false"))); } - if (BUILD.equals(project)) { + if (BUILD.equals(module.getProject())) { if (!module.getTrain().usesCalver()) { mvn.execute(project, goals.and(arg("newVersion").withValue(information.getReleaseTrainVersion())) // @@ -179,7 +174,7 @@ class MavenBuildSystem implements BuildSystem { */ public M triggerPreReleaseCheck(M module) { - mvn.execute(module.getProject(), CommandLine.of(Goal.CLEAN, Goal.VALIDATE, profile("pre-release"))); + mvn.execute(module.getSupportedProject(), CommandLine.of(Goal.CLEAN, Goal.VALIDATE, profile("pre-release"))); return module; } @@ -188,7 +183,7 @@ class MavenBuildSystem implements BuildSystem { * Perform a {@literal nexus-staging:rc-open} and extract the {@code stagingProfileId} from the results. */ @Override - public StagingRepository open() { + public StagingRepository open(Train train) { Assert.notNull(properties.getMavenCentral(), "Maven Central properties must not be null"); Assert.hasText(properties.getMavenCentral().getStagingProfileId(), "Staging Profile Identifier must not be empty"); @@ -199,7 +194,7 @@ class MavenBuildSystem implements BuildSystem { arg("openedRepositoryMessageFormat").withValue("'" + REPO_OPENING_TAG + "%s" + REPO_CLOSING_TAG + "'")) .andIf(!ObjectUtils.isEmpty(properties.getSettingsXml()), () -> settingsXml(properties.getSettingsXml())); - MavenRuntime.MavenInvocationResult invocationResult = mvn.execute(BUILD, arguments); + MavenRuntime.MavenInvocationResult invocationResult = mvn.execute(train.getSupportedProject(BUILD), arguments); List rcOpenLogContents = invocationResult.getLog(); @@ -220,7 +215,7 @@ class MavenBuildSystem implements BuildSystem { * Perform a {@literal nexus-staging:rc-close}. */ @Override - public void close(StagingRepository stagingRepository) { + public void close(Train train, StagingRepository stagingRepository) { Assert.notNull(stagingRepository, "StagingRepository must not be null"); Assert.isTrue(stagingRepository.isPresent(), "StagingRepository must be present"); @@ -230,7 +225,7 @@ class MavenBuildSystem implements BuildSystem { arg("stagingRepositoryId").withValue(stagingRepository.getId())) .andIf(!ObjectUtils.isEmpty(properties.getSettingsXml()), () -> settingsXml(properties.getSettingsXml())); - mvn.execute(BUILD, arguments); + mvn.execute(train.getSupportedProject(BUILD), arguments); } /* @@ -241,10 +236,10 @@ class MavenBuildSystem implements BuildSystem { public M triggerBuild(M module) { CommandLine arguments = CommandLine.of(Goal.CLEAN, Goal.INSTALL)// - .and(profile("ci,release")).andIf(module.getProject().skipTests(), SKIP_TESTS) + .and(profile("ci,release")).andIf(module.getSupportedProject().getProject().skipTests(), SKIP_TESTS) .andIf(!ObjectUtils.isEmpty(properties.getSettingsXml()), settingsXml(properties.getSettingsXml())); - mvn.execute(module.getProject(), arguments); + mvn.execute(module.getSupportedProject(), arguments); return module; } @@ -299,24 +294,31 @@ class MavenBuildSystem implements BuildSystem { Assert.notNull(module, "Module iteration must not be null!"); Assert.notNull(information, "Deployment information must not be null!"); - if (!module.getIteration().isPreview()) { - logger.log(module, "Not a preview version (milestone or release candidate). Skipping Artifactory deployment."); + boolean isCommercialRelease = module.isCommercial(); + + if (!module.getIteration().isPreview() && !isCommercialRelease) { + logger.log(module, + "Not a preview version (milestone or release candidate) or commercial release. Skipping Artifactory deployment."); return; } - logger.log(module, "Deploying artifacts to Spring Artifactory…"); + logger.log(module, + String.format("Deploying artifacts to Spring %sArtifactory…", isCommercialRelease ? "Commercial " : "")); + + Authentication authentication = properties.getAuthentication(module); CommandLine arguments = CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // profile("ci,release,artifactory"), // SKIP_TESTS, // - arg("artifactory.server").withValue(properties.getServer().getUri()), - arg("artifactory.staging-repository").withValue(properties.getStagingRepository()), - arg("artifactory.username").withValue(properties.getUsername()), - arg("artifactory.password").withValue(properties.getPassword()), + arg("artifactory.server").withValue(authentication.getServer().getUri()), + arg("artifactory.staging-repository").withValue(authentication.getStagingRepository()), + arg("artifactory.username").withValue(authentication.getUsername()), + arg("artifactory.password").withValue(authentication.getPassword()), arg("artifactory.build-name").withQuotedValue(information.getBuildName()), - arg("artifactory.build-number").withValue(information.getBuildNumber())); + arg("artifactory.build-number").withValue(information.getBuildNumber()), + arg("artifactory.project").withValue(information.getProject())); - mvn.execute(module.getProject(), arguments); + mvn.execute(module.getSupportedProject(), arguments); } /** @@ -331,9 +333,8 @@ class MavenBuildSystem implements BuildSystem { Assert.notNull(module, "Module iteration must not be null!"); Assert.notNull(deploymentInformation, "DeploymentInformation iteration must not be null!"); - if (!module.getIteration().isPublic()) { - - logger.log(module, "Skipping deployment to Maven Central as it's not a public version!"); + if (!module.isPublic()) { + logger.log(module, "Skipping deployment to Maven Central as it's not a public version or a commercial release!"); return; } @@ -352,7 +353,7 @@ class MavenBuildSystem implements BuildSystem { () -> arg("stagingRepositoryId").withValue(deploymentInformation.getStagingRepositoryId())) .andIf(gpg.hasSecretKeyring(), () -> arg("gpg.secretKeyring").withValue(gpg.getSecretKeyring())); - mvn.execute(module.getProject(), arguments); + mvn.execute(module.getSupportedProject(), arguments); } @Override @@ -363,12 +364,13 @@ class MavenBuildSystem implements BuildSystem { logger.log(iteration, "🚬 Running smoke test…"); - boolean mavenCentral = iteration.getIteration().isPublic(); + boolean mavenCentral = iteration.isPublic(); String profile = mavenCentral ? "maven-central" : "artifactory"; ModuleIteration module = iteration.getModule(BUILD); - doWithProjection(workspace.getFile(POM_XML, SMOKE_TESTS), pom -> { + SupportedProject smokeTests = iteration.getSupportedProject(SMOKE_TESTS); + doWithProjection(workspace.getFile(POM_XML, smokeTests), pom -> { Version version = module.getVersion(); String targetBootVersion = version.getMajor() == 2 ? "2.7.8" : "3.0.2"; @@ -381,7 +383,7 @@ class MavenBuildSystem implements BuildSystem { arg("spring-data-bom.version").withValue(iteration.getReleaseTrainNameAndVersion())) // .andIf(mavenCentral, arg("stagingRepository").withValue(stagingRepository.getId())); - mvn.execute(SMOKE_TESTS, arguments); + mvn.execute(smokeTests, arguments); logger.log(iteration, "✅ Smoke tests passed. Do not smoke 🚭. It's unhealthy."); } @@ -390,7 +392,7 @@ class MavenBuildSystem implements BuildSystem { * Perform a {@literal nexus-staging:rc-release}. */ @Override - public void release(StagingRepository stagingRepository) { + public void release(Train train, StagingRepository stagingRepository) { Assert.notNull(stagingRepository, "StagingRepository must not be null"); Assert.isTrue(stagingRepository.isPresent(), "StagingRepository must be present"); @@ -400,17 +402,17 @@ class MavenBuildSystem implements BuildSystem { arg("stagingRepositoryId").withValue(stagingRepository.getId())) .andIf(!ObjectUtils.isEmpty(properties.getSettingsXml()), () -> settingsXml(properties.getSettingsXml())); - mvn.execute(BUILD, arguments); + mvn.execute(train.getSupportedProject(BUILD), arguments); } @Override public M triggerDocumentationBuild(M module) { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); mvn.execute(project, CommandLine.of(Goal.CLEAN, Goal.INSTALL, SKIP_TESTS, profile("distribute"))); - logger.log(project, "Successfully finished documentation build."); + return module; } @@ -431,33 +433,38 @@ class MavenBuildSystem implements BuildSystem { return module; } - if (!isMavenProject(project)) { + SupportedProject supportedProject = module.getSupportedProject(); + + if (!isMavenProject(supportedProject)) { logger.log(project, "Skipping project as no pom.xml could be found in the working directory!"); return module; } logger.log(project, "Triggering distribution build…"); - mvn.execute(project, CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // - SKIP_TESTS, profile("distribute"), Argument.of("-B"), - arg("artifactory.server").withValue(properties.getServer().getUri()), - arg("artifactory.distribution-repository").withValue(properties.getDistributionRepository()), - arg("artifactory.username").withValue(properties.getUsername()), - arg("artifactory.password").withValue(properties.getPassword()))); + Authentication authentication = properties.getAuthentication(module); - mvn.execute(project, CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // + mvn.execute(supportedProject, CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // + SKIP_TESTS, profile("distribute"), Argument.of("-B"), + arg("artifactory.server").withValue(authentication.getServer().getUri()), + arg("artifactory.distribution-repository").withValue(authentication.getDistributionRepository()), + arg("artifactory.username").withValue(authentication.getUsername()), + arg("artifactory.password").withValue(authentication.getPassword()))); + + mvn.execute(supportedProject, CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // SKIP_TESTS, profile("distribute-schema"), Argument.of("-B"), - arg("artifactory.server").withValue(properties.getServer().getUri()), - arg("artifactory.distribution-repository").withValue(properties.getDistributionRepository()), - arg("artifactory.username").withValue(properties.getUsername()), - arg("artifactory.password").withValue(properties.getPassword()))); + arg("artifactory.server").withValue(authentication.getServer().getUri()), + arg("artifactory.distribution-repository").withValue(authentication.getDistributionRepository()), + arg("artifactory.username").withValue(authentication.getUsername()), + arg("artifactory.password").withValue(authentication.getPassword()))); logger.log(project, "Successfully finished distribution build!"); return module; } - private void updateBom(PomUpdater updater, UpdateInformation updateInformation, String file, Project project) { + private void updateBom(PomUpdater updater, UpdateInformation updateInformation, String file, + SupportedProject project) { TrainIteration iteration = updateInformation.getTrain(); @@ -506,23 +513,22 @@ class MavenBuildSystem implements BuildSystem { private void updateParentPom(PomUpdater updater, UpdateInformation information) { // Fix version of shared resources to to-be-released version. - doWithProjection(workspace.getFile("parent/pom.xml", BUILD), ParentPom.class, pom -> { + doWithProjection(workspace.getFile("parent/pom.xml", information.getSupportedProject(BUILD)), ParentPom.class, + pom -> { - logger.log(BUILD, "Setting shared resources version to %s.", information.getParentVersionToSet()); - pom.setSharedResourcesVersion(information.getParentVersionToSet()); + logger.log(BUILD, "Setting shared resources version to %s.", information.getParentVersionToSet()); + pom.setSharedResourcesVersion(information.getParentVersionToSet()); - logger.log(BUILD, "Setting releasetrain property to %s.", information.getReleaseTrainVersion()); - pom.setReleaseTrain(information.getReleaseTrainVersion()); + logger.log(BUILD, "Setting releasetrain property to %s.", information.getReleaseTrainVersion()); + pom.setReleaseTrain(information.getReleaseTrainVersion()); - updater.updateRepository(pom); - }); + updater.updateRepository(pom); + }); } public boolean isMavenProject(ModuleIteration module) { - Project project = module.getProject(); - - if (!isMavenProject(project)) { + if (!isMavenProject(module.getSupportedProject())) { logger.log(module, "No pom.xml file found, skipping project."); return false; } @@ -535,7 +541,7 @@ class MavenBuildSystem implements BuildSystem { * @see org.springframework.data.release.build.BuildSystem#verify() */ @Override - public void verify() { + public void verify(Train train) { logger.log(BUILD, "Verifying Maven Build System…"); @@ -549,21 +555,26 @@ class MavenBuildSystem implements BuildSystem { arg("gpg.passphrase").withValue(gpg.getPassphrase())) // .andIf(gpg.hasSecretKeyring(), () -> arg("gpg.secretKeyring").withValue(gpg.getSecretKeyring())); - mvn.execute(BUILD, arguments); + mvn.execute(train.getSupportedProject(BUILD), arguments); } @Override - public void verifyStagingAuthentication() { + public void verifyStagingAuthentication(Train train) { - logger.log(BUILD, "Verifying Maven Staging Authentication…"); + if (train.isOpenSource()) { - mvn.execute(BUILD, CommandLine.of(goal("nexus-staging:rc-list-profiles"), // - profile("central"))); + logger.log(BUILD, "Verifying Maven Staging Authentication…"); - Assert.notNull(properties.getMavenCentral(), - "Maven Central properties are not set (deployment.maven-central.staging-profile-id=…)"); - Assert.hasText(properties.getMavenCentral().getStagingProfileId(), - "Staging Profile Id is not set (deployment.maven-central.staging-profile-id=…)"); + mvn.execute(train.getSupportedProject(BUILD), // + CommandLine.of(goal("nexus-staging:rc-list-profiles"), // + profile("central"))); + + Assert.notNull(properties.getMavenCentral(), + "Maven Central properties are not set (deployment.maven-central.staging-profile-id=…)"); + Assert.hasText(properties.getMavenCentral().getStagingProfileId(), + "Staging Profile Id is not set (deployment.maven-central.staging-profile-id=…)"); + return; + } } /* @@ -571,11 +582,11 @@ class MavenBuildSystem implements BuildSystem { * @see org.springframework.plugin.core.Plugin#supports(java.lang.Object) */ @Override - public boolean supports(Project project) { + public boolean supports(SupportedProject project) { return isMavenProject(project); } - private boolean isMavenProject(Project project) { + private boolean isMavenProject(SupportedProject project) { return workspace.getFile(POM_XML, project).exists(); } diff --git a/src/main/java/org/springframework/data/release/build/MavenRuntime.java b/src/main/java/org/springframework/data/release/build/MavenRuntime.java index 1cd403c..2cf76b7 100644 --- a/src/main/java/org/springframework/data/release/build/MavenRuntime.java +++ b/src/main/java/org/springframework/data/release/build/MavenRuntime.java @@ -50,7 +50,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.io.JavaRuntimes; import org.springframework.data.release.io.Workspace; import org.springframework.data.release.model.JavaVersion; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.Named; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.utils.Logger; import org.springframework.lang.Nullable; import org.springframework.shell.support.util.StringUtils; @@ -155,8 +156,7 @@ public class MavenRuntime { return matcher.group(1); } - public MavenInvocationResult execute(Project project, CommandLine arguments) { - + public MavenInvocationResult execute(SupportedProject project, CommandLine arguments) { logger.log(project, "📦 Executing mvn %s", arguments.toString()); @@ -173,7 +173,8 @@ public class MavenRuntime { mavenLogger.info(String.format("Java Home: %s", jdk)); mavenLogger.info(String.format("Executing: mvn %s", arguments)); - CommandLine disabledGradleBuildCache = arguments.and(arg("gradle.cache.local.enabled=false")).and(arg("gradle.cache.remote.enabled=false")); + CommandLine disabledGradleBuildCache = arguments.and(arg("gradle.cache.local.enabled=false")) + .and(arg("gradle.cache.remote.enabled=false")); mvn.setGoals(disabledGradleBuildCache.toCommandLine(it -> properties.getFullyQualifiedPlugin(it.getGoal()))); }); @@ -221,7 +222,7 @@ public class MavenRuntime { return jdk.getHome().getAbsoluteFile(); } - private MavenLogger getLogger(Project project, List goals) { + private MavenLogger getLogger(Named project, List goals) { if (this.properties.isConsoleLogger()) { return new SlfLogger(log, project); @@ -258,7 +259,7 @@ public class MavenRuntime { private final String logPrefix; private final List contents; - SlfLogger(org.slf4j.Logger logger, Project project) { + SlfLogger(org.slf4j.Logger logger, Named project) { this.logger = logger; this.logPrefix = StringUtils.padRight(project.getName(), 10); this.contents = new ArrayList<>(); @@ -295,7 +296,7 @@ public class MavenRuntime { private final FileOutputStream outputStream; private final List contents = new ArrayList<>(); - FileLogger(org.slf4j.Logger logger, Project project, File logsDirectory, List goals) { + FileLogger(org.slf4j.Logger logger, Named project, File logsDirectory, List goals) { if (!logsDirectory.exists()) { logsDirectory.mkdirs(); diff --git a/src/main/java/org/springframework/data/release/build/PomUpdater.java b/src/main/java/org/springframework/data/release/build/PomUpdater.java index 4e31c18..35e7aa1 100644 --- a/src/main/java/org/springframework/data/release/build/PomUpdater.java +++ b/src/main/java/org/springframework/data/release/build/PomUpdater.java @@ -24,7 +24,7 @@ import java.util.List; import org.springframework.data.release.build.Pom.RepositoryElementFactory; import org.springframework.data.release.model.ArtifactVersion; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.utils.Logger; import org.springframework.util.Assert; @@ -37,26 +37,26 @@ class PomUpdater { private final Logger logger; private final UpdateInformation information; - private final @Getter Project project; + private final @Getter SupportedProject project; public boolean isBuildProject() { - return BUILD.equals(project); + return BUILD.equals(project.getProject()); } public boolean isBomProject() { - return BOM.equals(project); + return BOM.equals(project.getProject()); } public void updateArtifactVersion(Pom pom) { - ArtifactVersion version = information.getProjectVersionToSet(project); + ArtifactVersion version = information.getProjectVersionToSet(project.getProject()); logger.log(project, "Updated project version to %s.", version); pom.setVersion(version); } public void updateDependencyProperties(Pom pom) { - project.getDependencies().forEach(dependency -> { + project.getProject().getDependencies().forEach(dependency -> { String dependencyProperty = dependency.getDependencyProperty(); diff --git a/src/main/java/org/springframework/data/release/build/Repository.java b/src/main/java/org/springframework/data/release/build/Repository.java index a119d08..a86f0f9 100644 --- a/src/main/java/org/springframework/data/release/build/Repository.java +++ b/src/main/java/org/springframework/data/release/build/Repository.java @@ -27,9 +27,12 @@ public class Repository { static Repository SNAPSHOT = new Repository("spring-snapshot", "https://repo.spring.io/snapshot", true, false); static Repository MILESTONE = new Repository("spring-milestone", "https://repo.spring.io/milestone", null, null); + static Repository COMMERCIAL_SNAPSHOT = new Repository("spring-commercial-snapshot", + "https://repo.spring.vmware.com/artifactory/spring-commercial-snapshot-local", true, false); + static Repository COMMERCIAL_RELEASE = new Repository("spring-commercial-release", + "https://repo.spring.vmware.com/artifactory/spring-commercial", false, true); + String id, url; Boolean snapshots; Boolean releases; - - } diff --git a/src/main/java/org/springframework/data/release/build/UpdateInformation.java b/src/main/java/org/springframework/data/release/build/UpdateInformation.java index b4d36f2..57fd4c9 100644 --- a/src/main/java/org/springframework/data/release/build/UpdateInformation.java +++ b/src/main/java/org/springframework/data/release/build/UpdateInformation.java @@ -29,6 +29,7 @@ import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.util.Assert; @@ -93,16 +94,20 @@ public class UpdateInformation { if (phase == Phase.PREPARE) { Iteration iteration = train.getIteration(); + if (iteration.isMilestone() || iteration.isReleaseCandidate()) { return Collections.singletonList(Repository.MILESTONE); } } if (phase == Phase.CLEANUP || phase == Phase.MAINTENANCE) { - return Arrays.asList(Repository.SNAPSHOT, Repository.MILESTONE); + + return train.isCommercial() + ? Arrays.asList(Repository.COMMERCIAL_SNAPSHOT, Repository.COMMERCIAL_RELEASE) + : Arrays.asList(Repository.SNAPSHOT, Repository.MILESTONE); } - return Collections.emptyList(); + return train.isCommercial() ? Arrays.asList(Repository.COMMERCIAL_RELEASE) : Collections.emptyList(); } /** @@ -142,4 +147,8 @@ public class UpdateInformation { public boolean isBomInBuildProject() { return !train.getTrain().usesCalver(); } + + public SupportedProject getSupportedProject(Project project) { + return train.getSupportedProject(project); + } } diff --git a/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java b/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java index 09c0be4..bf31345 100644 --- a/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java +++ b/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java @@ -15,8 +15,6 @@ */ package org.springframework.data.release.cli; -import static org.springframework.data.release.model.Projects.*; - import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -36,13 +34,10 @@ import org.springframework.data.release.git.GitOperations; import org.springframework.data.release.issues.IssueTrackerCommands; import org.springframework.data.release.issues.github.GitHubCommands; import org.springframework.data.release.misc.ReleaseOperations; -import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; -import org.springframework.data.release.model.ReleaseTrains; -import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; @@ -64,14 +59,6 @@ class ReleaseCommands extends TimedCommand { @NonNull IssueTrackerCommands tracker; @NonNull GitHubCommands gitHub; - @CliCommand("release predict") - public String predictTrainAndIteration() { - - return git.getTags(COMMONS).getLatest().toArtifactVersion().// - map(ReleaseCommands::getTrainNameForCommonsVersion).// - orElse(null); - } - /** * Composite command to prepare a release. * @@ -140,7 +127,7 @@ class ReleaseCommands extends TimedCommand { @CliCommand(value = "repository open") public void repositoryOpen(@CliOption(key = "", mandatory = true) TrainIteration iteration) { - if (iteration.getIteration().isPublic()) { + if (iteration.isPublic()) { build.open(iteration.getModule(Projects.BUILD)); } } @@ -149,7 +136,7 @@ class ReleaseCommands extends TimedCommand { public void repositoryClose(@CliOption(key = "", mandatory = true) TrainIteration iteration, @CliOption(key = "stagingRepositoryId", mandatory = true) String stagingRepositoryId) { - if (iteration.getIteration().isPublic()) { + if (iteration.isPublic()) { build.close(iteration.getModule(Projects.BUILD), StagingRepository.of(stagingRepositoryId)); } } @@ -158,7 +145,7 @@ class ReleaseCommands extends TimedCommand { public void repositoryRelease(@CliOption(key = "", mandatory = true) TrainIteration iteration, @CliOption(key = "stagingRepositoryId", mandatory = true) String stagingRepositoryId) { - if (iteration.getIteration().isPublic()) { + if (iteration.isPublic()) { build.release(iteration.getModule(Projects.BUILD), StagingRepository.of(stagingRepositoryId)); } } @@ -169,8 +156,8 @@ class ReleaseCommands extends TimedCommand { git.checkout(iteration); - if (!iteration.getIteration().isPublic()) { - deployment.verifyAuthentication(); + if (!iteration.isPublic()) { + deployment.verifyAuthentication(iteration); } if (projectName != null) { @@ -293,11 +280,4 @@ class ReleaseCommands extends TimedCommand { build.distributeResources(iteration); } } - - private static String getTrainNameForCommonsVersion(ArtifactVersion version) { - - return ReleaseTrains.TRAINS.stream().// - filter(train -> version.toString().startsWith(train.getModule(COMMONS).getVersion().toString())).// - findFirst().map(Train::getName).orElse(null); - } } diff --git a/src/main/java/org/springframework/data/release/cli/StaticResources.java b/src/main/java/org/springframework/data/release/cli/StaticResources.java index 4bfef4e..7b6c73f 100644 --- a/src/main/java/org/springframework/data/release/cli/StaticResources.java +++ b/src/main/java/org/springframework/data/release/cli/StaticResources.java @@ -23,7 +23,6 @@ import org.springframework.data.release.git.VersionTags; import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.DocumentationMetadata; import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Project; /** * @author Oliver Gierke @@ -40,8 +39,7 @@ public class StaticResources { this.metadata = DocumentationMetadata.of(module, ArtifactVersion.of(module), false); - Project project = module.getProject(); - GitProject gitProject = GitProject.of(project); + GitProject gitProject = GitProject.of(module); Tag tag = VersionTags.empty(module.getProject()).createTag(module); this.releaseUrl = String.format("%s/releases/tag/%s", gitProject.getProjectUri(), tag.getName()); diff --git a/src/main/java/org/springframework/data/release/cli/VerifyCommands.java b/src/main/java/org/springframework/data/release/cli/VerifyCommands.java index dfe6ee8..1021d77 100644 --- a/src/main/java/org/springframework/data/release/cli/VerifyCommands.java +++ b/src/main/java/org/springframework/data/release/cli/VerifyCommands.java @@ -26,6 +26,7 @@ import org.springframework.data.release.build.BuildOperations; import org.springframework.data.release.deployment.DeploymentOperations; import org.springframework.data.release.git.GitOperations; import org.springframework.data.release.issues.github.GitHub; +import org.springframework.data.release.model.Train; import org.springframework.data.release.projectservice.ProjectService; import org.springframework.data.release.utils.Logger; import org.springframework.shell.core.annotation.CliCommand; @@ -50,18 +51,20 @@ class VerifyCommands extends TimedCommand { @NonNull Logger logger; @CliCommand("verify") - public void verifyReleaseTools(@CliOption(key = "", mandatory = false) String mode) { + public void verifyReleaseTools( + @CliOption(key = "", mandatory = false) String mode, + @CliOption(key = "train", mandatory = true) Train train) { if ("local".equals(mode)) { // Git checkout build - git.verify(); + git.verify(train); // Maven interaction - build.verify(); + build.verify(train); // GitHub verification - github.verifyAuthentication(); + github.verifyAuthentication(train); // Projects Service Verification projectService.verifyAuthentication(); @@ -72,23 +75,23 @@ class VerifyCommands extends TimedCommand { if (ObjectUtils.isEmpty(mode) || "git".equals(mode)) { // Git checkout build - git.verify(); + git.verify(train); } if (ObjectUtils.isEmpty(mode) || "build".equals(mode)) { // Maven interaction - build.verify(); - build.verifyStagingAuthentication(); + build.verify(train); + build.verifyStagingAuthentication(train); } if (ObjectUtils.isEmpty(mode) || "deployment".equals(mode)) { // Artifactory verification - deployment.verifyAuthentication(); + deployment.verifyAuthentication(train); } if (ObjectUtils.isEmpty(mode) || "github".equals(mode)) { // GitHub verification - github.verifyAuthentication(); + github.verifyAuthentication(train); } if (ObjectUtils.isEmpty(mode) || "projects".equals(mode)) { @@ -98,5 +101,4 @@ class VerifyCommands extends TimedCommand { logger.log("Verify", "All settings are verified. You can ship a release now."); } - } diff --git a/src/main/java/org/springframework/data/release/deployment/ArtifactoryClient.java b/src/main/java/org/springframework/data/release/deployment/ArtifactoryClient.java index 0f56c61..1ad9d6b 100644 --- a/src/main/java/org/springframework/data/release/deployment/ArtifactoryClient.java +++ b/src/main/java/org/springframework/data/release/deployment/ArtifactoryClient.java @@ -22,7 +22,9 @@ import java.io.IOException; import java.net.URI; import java.util.function.Consumer; +import org.springframework.data.release.deployment.DeploymentProperties.Authentication; import org.springframework.data.release.model.ModuleIteration; +import org.springframework.data.release.model.SupportStatusAware; import org.springframework.data.release.utils.Logger; import org.springframework.util.Assert; import org.springframework.web.client.HttpClientErrorException; @@ -39,9 +41,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; @RequiredArgsConstructor class ArtifactoryClient { - private final RestOperations template; private final Logger logger; private final DeploymentProperties properties; + private final RestOperations operations; /** * Triggers the promotion of the artifacts identified by the given {@link DeploymentInformation}. @@ -53,28 +55,35 @@ class ArtifactoryClient { Assert.notNull(information, "DeploymentInformation must not be null!"); ModuleIteration module = information.getModule(); - URI uri = properties.getServer().getPromotionResource(information); + URI uri = information.getPromotionResource(); + + Authentication authentication = properties.getAuthentication(module); logger.log(module, "Promoting %s %s from %s to %s.", information.getBuildName(), information.getBuildNumber(), - properties.getStagingRepository(), information.getTargetRepository()); + authentication.getStagingRepository(), authentication.getTargetRepository()); try { - template.postForEntity(uri, - new PromotionRequest(information.getTargetRepository(), properties.getStagingRepository()), String.class); + PromotionRequest request = new PromotionRequest(information.getTargetRepository(), + authentication.getStagingRepository()); + operations.postForEntity(uri, request, String.class); + } catch (HttpClientErrorException o_O) { handle(message -> logger.warn(information.getModule(), message), "Promotion failed!", o_O); } } - public void verify() { + public void verify(SupportStatusAware status) { - URI verificationResource = properties.getServer().getVerificationResource(); + URI verificationResource = properties + .getAuthentication(status) + .getServer() + .getVerificationResource(); try { logger.log("Artifactory", "Verifying authentication using a GET call to %s.", verificationResource); - template.getForEntity(verificationResource, String.class); + operations.getForEntity(verificationResource, String.class); logger.log("Artifactory", "Authentication verified!"); @@ -101,7 +110,8 @@ class ArtifactoryClient { } public void deleteArtifacts(DeploymentInformation information) { - template.delete(properties.getServer().getDeleteBuildResource(information)); + + operations.delete(information.getDeleteBuildResource()); } @Value diff --git a/src/main/java/org/springframework/data/release/deployment/ArtifactoryCommands.java b/src/main/java/org/springframework/data/release/deployment/ArtifactoryCommands.java index 7e537cc..36217a2 100644 --- a/src/main/java/org/springframework/data/release/deployment/ArtifactoryCommands.java +++ b/src/main/java/org/springframework/data/release/deployment/ArtifactoryCommands.java @@ -18,8 +18,11 @@ package org.springframework.data.release.deployment; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import java.util.stream.Stream; + import org.springframework.data.release.CliComponent; import org.springframework.data.release.TimedCommand; +import org.springframework.data.release.model.SupportStatus; import org.springframework.shell.core.annotation.CliCommand; /** @@ -35,6 +38,8 @@ class ArtifactoryCommands extends TimedCommand { @CliCommand(value = "artifactory verify", help = "Verifies authentication at Artifactory.") public void verify() { - deployment.verifyAuthentication(); + + Stream.of(SupportStatus.OSS, SupportStatus.COMMERCIAL) + .forEach(deployment::verifyAuthentication); } } diff --git a/src/main/java/org/springframework/data/release/deployment/DefaultDeploymentInformation.java b/src/main/java/org/springframework/data/release/deployment/DefaultDeploymentInformation.java index d7d48af..100ebcf 100644 --- a/src/main/java/org/springframework/data/release/deployment/DefaultDeploymentInformation.java +++ b/src/main/java/org/springframework/data/release/deployment/DefaultDeploymentInformation.java @@ -20,11 +20,13 @@ import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import java.net.URI; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.HashMap; import java.util.Map; +import org.springframework.data.release.deployment.DeploymentProperties.Authentication; import org.springframework.data.release.model.ModuleIteration; import org.springframework.web.util.UriTemplate; @@ -44,6 +46,8 @@ public class DefaultDeploymentInformation implements DeploymentInformation { private final @Getter String buildNumber; private final @Getter StagingRepository stagingRepositoryId; + private final Authentication authentication; + public DefaultDeploymentInformation(ModuleIteration module, DeploymentProperties properties) { this(module, properties, StagingRepository.EMPTY); } @@ -51,17 +55,18 @@ public class DefaultDeploymentInformation implements DeploymentInformation { public DefaultDeploymentInformation(ModuleIteration module, DeploymentProperties properties, String stagingRepositoryId) { this(module, properties, String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)), - StagingRepository.of(stagingRepositoryId)); + StagingRepository.of(stagingRepositoryId), properties.getAuthentication(module)); } public DefaultDeploymentInformation(ModuleIteration module, DeploymentProperties properties, StagingRepository stagingRepository) { - this(module, properties, String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)), stagingRepository); + this(module, properties, String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)), stagingRepository, + properties.getAuthentication(module)); } @Override public DeploymentInformation withModule(ModuleIteration module) { - return new DefaultDeploymentInformation(module, properties, buildNumber, stagingRepositoryId); + return new DefaultDeploymentInformation(module, properties, buildNumber, stagingRepositoryId, authentication); } /* @@ -73,14 +78,22 @@ public class DefaultDeploymentInformation implements DeploymentInformation { return module.getProject().getFullName().concat(" - Release"); } + /* + * (non-Javadoc) + * @see org.springframework.data.release.deployment.DeploymentInformation#getProject() + */ + @Override + public String getProject() { + return authentication.getProject(); + } + /* * (non-Javadoc) * @see org.springframework.data.release.deployment.DeploymentInformation#getTargetRepository() */ @Override public String getTargetRepository() { - return properties.getRepositoryPrefix() - .concat(module.getIteration().isPublic() ? "libs-release-local" : "libs-milestone-local"); + return authentication.getRepositoryPrefix().concat(authentication.getTargetRepository()); } /* @@ -91,7 +104,7 @@ public class DefaultDeploymentInformation implements DeploymentInformation { public String getDeploymentTargetUrl() { Map parameters = new HashMap<>(); - parameters.put("server", properties.getStagingRepositoryUrl()); + parameters.put("server", authentication.getTargetRepository()); parameters.putAll(getBuildInfoParameters()); return REPOSITORY_TEMPLATE.expand(parameters).toString(); @@ -110,4 +123,33 @@ public class DefaultDeploymentInformation implements DeploymentInformation { return parameters; } + + /* + * (non-Javadoc) + * @see org.springframework.data.release.deployment.DeploymentInformation#getPromotionResource() + */ + @Override + public URI getPromotionResource() { + return authentication.getServer().getPromotionResource(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.release.deployment.DeploymentInformation#getDeleteBuildResource() + */ + @Override + public URI getDeleteBuildResource() { + return authentication.getServer().getDeleteBuildResource(this); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.release.deployment.DeploymentInformation#isMavenCentral() + */ + @Override + public boolean isMavenCentral() { + + return !module.isCommercial() + && module.getIteration().isPublic(); + } } diff --git a/src/main/java/org/springframework/data/release/deployment/DeploymentConfiguration.java b/src/main/java/org/springframework/data/release/deployment/DeploymentConfiguration.java index 032d691..e631032 100644 --- a/src/main/java/org/springframework/data/release/deployment/DeploymentConfiguration.java +++ b/src/main/java/org/springframework/data/release/deployment/DeploymentConfiguration.java @@ -18,11 +18,12 @@ package org.springframework.data.release.deployment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.release.deployment.DeploymentProperties.Authentication; import org.springframework.data.release.model.Password; import org.springframework.data.release.utils.HttpBasicCredentials; import org.springframework.data.release.utils.HttpComponentsClientHttpRequestFactoryBuilder; import org.springframework.data.release.utils.Logger; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; /** @@ -36,23 +37,30 @@ class DeploymentConfiguration { @Autowired DeploymentProperties properties; @Bean - public ArtifactoryClient client(Logger logger, RestTemplate artifactoryRestTemplate) { - return new ArtifactoryClient(artifactoryRestTemplate, logger, properties); + ArtifactoryClient client(Logger logger, RestOperations operations) { + return new ArtifactoryClient(logger, properties, operations); } @Bean - public RestTemplate artifactoryRestTemplate() { + RestTemplate artifactoryRestTemplateFactory(DeploymentProperties properties, Logger logger) { - RestTemplate template = new RestTemplate(); + HttpComponentsClientHttpRequestFactoryBuilder builder = HttpComponentsClientHttpRequestFactoryBuilder.builder(); - HttpComponentsClientHttpRequestFactory factory = HttpComponentsClientHttpRequestFactoryBuilder.builder() - .withAuthentication(properties.getServer().getUri(), - new HttpBasicCredentials(properties.getUsername(), Password.of(properties.getApiKey()))) - .build(); + for (Authentication authentication : properties.getAuthentications()) { - template.setRequestFactory(factory); + String uri = authentication.getServer().getUri(); - return template; + if (authentication.hasCredentials()) { + + HttpBasicCredentials credentials = new HttpBasicCredentials(authentication.getUsername(), + Password.of(authentication.getApiKey())); + builder = builder.withAuthentication(uri, credentials); + + } else { + logger.warn("Infrastructure", "No credentials configured for repository %s!", uri); + } + } + + return new RestTemplate(builder.build()); } - } diff --git a/src/main/java/org/springframework/data/release/deployment/DeploymentInformation.java b/src/main/java/org/springframework/data/release/deployment/DeploymentInformation.java index 052f533..2ef2666 100644 --- a/src/main/java/org/springframework/data/release/deployment/DeploymentInformation.java +++ b/src/main/java/org/springframework/data/release/deployment/DeploymentInformation.java @@ -15,6 +15,7 @@ */ package org.springframework.data.release.deployment; +import java.net.URI; import java.util.Map; import org.springframework.data.release.model.ModuleIteration; @@ -39,6 +40,14 @@ public interface DeploymentInformation { */ String getBuildNumber(); + /** + * A project assignment on the server. JFrog uses this to group different builds into build info repositories in + * Artifactory. + * + * @return + */ + String getProject(); + /** * Returns the full URL to be used as deployment target. * @@ -53,6 +62,10 @@ public interface DeploymentInformation { */ String getTargetRepository(); + URI getPromotionResource(); + + URI getDeleteBuildResource(); + /** * Staging repository identifier. * @@ -75,4 +88,6 @@ public interface DeploymentInformation { Map getBuildInfoParameters(); DeploymentInformation withModule(ModuleIteration module); + + boolean isMavenCentral(); } diff --git a/src/main/java/org/springframework/data/release/deployment/DeploymentOperations.java b/src/main/java/org/springframework/data/release/deployment/DeploymentOperations.java index e2b2f9a..d6d4dd2 100644 --- a/src/main/java/org/springframework/data/release/deployment/DeploymentOperations.java +++ b/src/main/java/org/springframework/data/release/deployment/DeploymentOperations.java @@ -17,6 +17,7 @@ package org.springframework.data.release.deployment; import lombok.RequiredArgsConstructor; +import org.springframework.data.release.model.SupportStatusAware; import org.springframework.data.release.utils.Logger; import org.springframework.stereotype.Component; import org.springframework.util.Assert; @@ -34,8 +35,8 @@ public class DeploymentOperations { private final ArtifactoryClient client; private final Logger logger; - public void verifyAuthentication() { - client.verify(); + public void verifyAuthentication(SupportStatusAware status) { + client.verify(status); } /** @@ -47,7 +48,7 @@ public class DeploymentOperations { Assert.notNull(information, "DeploymentInformation must not be null!"); - if (information.getModule().getIteration().isPublic()) { + if (information.isMavenCentral()) { logger.log(information.getModule(), "Skipping build promotion as it's a public version and was staged to OSS Sonatype."); return; diff --git a/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java b/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java index a6a1419..a55fa45 100644 --- a/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java +++ b/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java @@ -15,18 +15,20 @@ */ package org.springframework.data.release.deployment; +import lombok.Data; + import java.net.URI; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.data.release.model.Gpg; import org.springframework.data.release.model.Password; -import org.springframework.data.release.utils.HttpBasicCredentials; +import org.springframework.data.release.model.SupportStatusAware; +import org.springframework.data.util.Streamable; import org.springframework.stereotype.Component; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import org.springframework.web.util.UriTemplate; -import lombok.Data; - /** * @author Oliver Gierke * @author Mark Paluch @@ -36,54 +38,16 @@ import lombok.Data; @ConfigurationProperties(prefix = "deployment") public class DeploymentProperties { - /** - * The Artifactory host. - */ - private Server server; - - /** - * The deployer's username. - */ - private String username; - - private String apiKey; - - /** - * The deployer's password. - */ - private Password password; - - /** - * The repository to deploy the artifacts to. - */ - private String stagingRepository; - - /** - * The repository to deploy docs/schemas to. - */ - private String distributionRepository; - private String settingsXml; - - private String repositoryPrefix = ""; - private MavenCentral mavenCentral; + private Authentication opensource, commercial; - public String getStagingRepository() { - return repositoryPrefix.concat(stagingRepository); + public Authentication getAuthentication(SupportStatusAware status) { + return status.isOpenSource() ? opensource : commercial; } - public String getDistributionRepository() { - return repositoryPrefix.concat(distributionRepository); - } - - /** - * Returns the URI of the staging repository. - * - * @return - */ - public String getStagingRepositoryUrl() { - return server.getUri().concat("/").concat(stagingRepository); + public Streamable getAuthentications() { + return Streamable.of(opensource, commercial); } @Data @@ -91,9 +55,10 @@ public class DeploymentProperties { private static final String PROMOTION_RESOURCE = "/api/build/promote/{buildName}/{buildNumber}"; private static final String DELETE_BUILD_RESOURCE = "/api/build/{buildName}?buildNumbers={buildNumber}&artifacts=1"; - private static final String VERIFICATION_RESOURCE = "/api/storage/temp-private-local"; + private static final String VERIFICATION_RESOURCE = "/api/storage/{verificationResource}"; private String uri; + private String verificationResource; /** * Returns the URI to the resource that a promotion can be triggered at. @@ -114,7 +79,7 @@ public class DeploymentProperties { } public URI getVerificationResource() { - return URI.create(uri.concat(VERIFICATION_RESOURCE)); + return new UriTemplate(uri.concat(VERIFICATION_RESOURCE)).expand(verificationResource); } } @@ -130,4 +95,37 @@ public class DeploymentProperties { } } + @Data + public static class Authentication { + + Server server; + String stagingRepository, targetRepository; + String distributionRepository; + String project; + String username; + Password password; + String apiKey; + String repositoryPrefix = ""; + + public boolean hasCredentials() { + return StringUtils.hasText(username) && password != null; + } + + /** + * Returns the URI of the staging repository. + * + * @return + */ + public String getStagingRepositoryUrl() { + return server.getUri().concat("/").concat(stagingRepository); + } + + public String getStagingRepository() { + return repositoryPrefix.concat(stagingRepository); + } + + public String getDistributionRepository() { + return repositoryPrefix.concat(distributionRepository); + } + } } diff --git a/src/main/java/org/springframework/data/release/documentation/DocumentationCommands.java b/src/main/java/org/springframework/data/release/documentation/DocumentationCommands.java index 6f7f642..8930c68 100644 --- a/src/main/java/org/springframework/data/release/documentation/DocumentationCommands.java +++ b/src/main/java/org/springframework/data/release/documentation/DocumentationCommands.java @@ -100,7 +100,7 @@ public class DocumentationCommands extends TimedCommand { if (preview) { buildOperations.buildDocumentation(module); - File projectDirectory = workspace.getProjectDirectory(module.getProject()); + File projectDirectory = workspace.getProjectDirectory(module.getSupportedProject()); if (!projectDirectory.exists()) { logger.warn(module, "Unable to locate project directory"); @@ -171,9 +171,9 @@ public class DocumentationCommands extends TimedCommand { HttpStatus status = checkedLink.getResult(); if (status.is2xxSuccessful()) { ansi.fg(Color.GREEN); - } else if (status.is4xxClientError()) + } else if (status.is4xxClientError()) { ansi.fg(Color.RED); - else if (status.is3xxRedirection()) { + } else if (status.is3xxRedirection()) { ansi.fg(Color.YELLOW); } diff --git a/src/main/java/org/springframework/data/release/git/BackportTargets.java b/src/main/java/org/springframework/data/release/git/BackportTargets.java index a4b6b3e..5925af2 100644 --- a/src/main/java/org/springframework/data/release/git/BackportTargets.java +++ b/src/main/java/org/springframework/data/release/git/BackportTargets.java @@ -45,7 +45,8 @@ class BackportTargets implements Iterable { this.source = Branch.from(module); - Stream branches = targets.stream().map(target -> target.getModuleIfAvailable(module.getProject()))// + Stream branches = targets.stream() // + .map(target -> target.getModuleIfAvailable(module.getSupportedProject().getProject()))// .flatMap(o -> o.map(Stream::of).orElse(Stream.empty()))// .map(Branch::from); diff --git a/src/main/java/org/springframework/data/release/git/GitCommands.java b/src/main/java/org/springframework/data/release/git/GitCommands.java index 47fab78..3615049 100644 --- a/src/main/java/org/springframework/data/release/git/GitCommands.java +++ b/src/main/java/org/springframework/data/release/git/GitCommands.java @@ -36,6 +36,7 @@ import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; import org.springframework.data.release.model.ReleaseTrains; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; @@ -54,7 +55,7 @@ import org.springframework.util.StringUtils; @RequiredArgsConstructor class GitCommands extends TimedCommand { - private final PluginRegistry trackers; + private final PluginRegistry trackers; private final @NonNull GitOperations git; private final @NonNull Executor executor; @@ -75,11 +76,13 @@ class GitCommands extends TimedCommand { } @CliCommand("git tags") - public String tags(@CliOption(key = { "project" }, mandatory = true) String projectName) throws Exception { + public String tags( + @CliOption(key = { "project" }, mandatory = true) String projectName, + @CliOption(key = { "", "train" }, mandatory = true) Train train) throws Exception { Project project = ReleaseTrains.getProjectByName(projectName); - return StringUtils.collectionToDelimitedString(git.getTags(project).asList(), "\n"); + return StringUtils.collectionToDelimitedString(git.getTags(train.getSupportedProject(project)).asList(), "\n"); } @CliCommand("git previous") @@ -96,7 +99,7 @@ class GitCommands extends TimedCommand { if (StringUtils.hasText(moduleName)) { ModuleIteration module = iteration.getModule(Projects.requiredByName(moduleName)); - List ticketRefs = git.getTicketReferencesBetween(module.getProject(), previousIteration, + List ticketRefs = git.getTicketReferencesBetween(module.getSupportedProject(), previousIteration, iteration); Changelog changelog = Changelog.of(module, toTickets(module, ticketRefs)); @@ -105,15 +108,16 @@ class GitCommands extends TimedCommand { } return ExecutionUtils - .runAndReturn(executor, iteration, module -> changelog(iteration, module.getModule().getProject().getName())) // + .runAndReturn(executor, iteration, + module -> changelog(iteration, module.getModule().getProject().getName())) // .stream() // .collect(Collectors.joining("\n")); } private Tickets toTickets(ModuleIteration module, List ticketReferences) { - IssueTracker issueTracker = trackers.getRequiredPluginFor(module.getProject(), - () -> String.format("No issue tracker found for project %s!", module.getProject())); + IssueTracker issueTracker = trackers.getRequiredPluginFor(module.getSupportedProject(), + () -> String.format("No issue tracker found for project %s!", module.getSupportedProject())); List ticketIds = ticketReferences.stream().map(TicketReference::getId).collect(Collectors.toList()); @@ -174,12 +178,14 @@ class GitCommands extends TimedCommand { * @throws Exception */ @CliCommand("git issuebranches") - public Table issuebranches(@CliOption(key = { "" }, mandatory = true) String projectName, + public Table issuebranches( + @CliOption(key = "", mandatory = true) String projectName, + @CliOption(key = "train", mandatory = true) Train train, @CliOption(key = "resolved", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") Boolean resolved) throws Exception { Project project = ReleaseTrains.getProjectByName(projectName); - TicketBranches ticketBranches = git.listTicketBranches(project); + TicketBranches ticketBranches = git.listTicketBranches(train.getSupportedProject(project)); Table table = new Table(); table.addHeader(1, new TableHeader("Branch")); diff --git a/src/main/java/org/springframework/data/release/git/GitOperations.java b/src/main/java/org/springframework/data/release/git/GitOperations.java index ac1918d..3cbba1b 100644 --- a/src/main/java/org/springframework/data/release/git/GitOperations.java +++ b/src/main/java/org/springframework/data/release/git/GitOperations.java @@ -38,8 +38,10 @@ import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.LogCommand; import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.api.TransportCommand; import org.eclipse.jgit.api.errors.EmptyCommitException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.RefNotFoundException; @@ -65,6 +67,7 @@ import org.springframework.data.release.issues.Ticket; import org.springframework.data.release.issues.TicketReference; import org.springframework.data.release.issues.TicketStatus; import org.springframework.data.release.model.*; +import org.springframework.data.release.model.Module; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.data.release.utils.Logger; import org.springframework.data.util.Pair; @@ -92,20 +95,10 @@ public class GitOperations { Executor executor; Workspace workspace; Logger logger; - PluginRegistry issueTracker; + PluginRegistry issueTracker; GitProperties gitProperties; Gpg gpg; - /** - * Returns the {@link GitProject} for the given {@link Project}. - * - * @param project - * @return - */ - public GitProject getGitProject(Project project) { - return new GitProject(project, server); - } - /** * Resets the repositories for all modules of the given {@link Train}. * @@ -116,7 +109,7 @@ public class GitOperations { Assert.notNull(train, "Train must not be null!"); ExecutionUtils.run(executor, train, module -> { - reset(module.getProject(), Branch.from(module)); + reset(module.getSupportedProject(), Branch.from(module)); }); } @@ -149,9 +142,9 @@ public class GitOperations { update(train); } - ExecutionUtils.run(executor, train, module -> { + ExecutionUtils.run(executor, train.getModules(), module -> { - Project project = module.getProject(); + SupportedProject project = train.getSupportedProject(module); doWithGit(project, git -> { @@ -168,9 +161,9 @@ public class GitOperations { } - private Branch getBranch(Train train, Module module, Project project) { + private Branch getBranch(Train train, Module module, SupportedProject project) { - ModuleIteration gaIteration = train.getModuleIteration(project, Iteration.GA); + ModuleIteration gaIteration = train.getModuleIteration(project.getProject(), Iteration.GA); Optional gaTag = findTagFor(project, ArtifactVersion.of(gaIteration)); if (!gaTag.isPresent()) { @@ -180,7 +173,7 @@ public class GitOperations { return gaTag.isPresent() ? Branch.from(module) : Branch.MAIN; } - private void checkoutBranch(Project project, Git git, Branch branch) throws GitAPIException { + private void checkoutBranch(SupportedProject project, Git git, Branch branch) throws GitAPIException { CheckoutCommand command = git.checkout().setName(branch.toString()).setForced(true); @@ -208,8 +201,9 @@ public class GitOperations { ExecutionUtils.run(executor, iteration, module -> { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); ArtifactVersion artifactVersion = ArtifactVersion.of(module); + Tag tag = findTagFor(project, artifactVersion).orElseThrow(() -> new IllegalStateException( String.format("No tag found for version %s of project %s, aborting.", artifactVersion, project))); @@ -227,7 +221,7 @@ public class GitOperations { ExecutionUtils.run(executor, iteration, module -> { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); Branch branch = Branch.from(module); update(project); @@ -238,9 +232,8 @@ public class GitOperations { doWithGit(project, git -> { logger.log(project, "git pull origin %s", branch); - git.pull()// - .setRebase(true)// - .call(); + + call(git.pull().setRebase(true)); }); logger.log(project, "Pulling updates done!", branch); @@ -250,7 +243,7 @@ public class GitOperations { } public void update(Train train) { - ExecutionUtils.run(executor, train, module -> update(module.getProject())); + ExecutionUtils.run(executor, train, this::update); } public void push(TrainIteration iteration) { @@ -262,21 +255,21 @@ public class GitOperations { Branch branch = Branch.from(module); logger.log(module, "git push origin %s", branch); - if (!branchExists(module.getProject(), branch)) { + SupportedProject project = module.getSupportedProject(); - logger.log(module, "No branch %s in %s, skip push", branch, module.getProject().getName()); + if (!branchExists(project, branch)) { + + logger.log(module, "No branch %s in %s, skip push", branch, project.getName()); return; } - doWithGit(module.getProject(), git -> { + doWithGit(project, git -> { Ref ref = git.getRepository().findRef(branch.toString()); - git.push()// - .setRemote("origin")// - .setRefSpecs(new RefSpec(ref.getName()))// - .setCredentialsProvider(gitProperties.getCredentials())// - .call(); + call(git.push() // + .setRemote("origin") // + .setRefSpecs(new RefSpec(ref.getName()))); }); } @@ -284,15 +277,15 @@ public class GitOperations { ExecutionUtils.run(executor, train.getModules(), module -> { - logger.log(module.getProject(), "git push --tags origin"); + SupportedProject project = train.getSupportedProject(module); - doWithGit(module.getProject(), git -> { + logger.log(project, "git push --tags origin"); - git.push()// - .setRemote("origin")// - .setPushTags()// - .setCredentialsProvider(gitProperties.getCredentials())// - .call(); + doWithGit(project, git -> { + + call(git.push() // + .setRemote("origin") // + .setPushTags()); }); }); } @@ -303,16 +296,16 @@ public class GitOperations { * * @param project must not be {@literal null}. */ - public void update(Project project) { + public void update(SupportedProject project) { Assert.notNull(project, "Project must not be null!"); logger.log(project, "Updating project…"); - GitProject gitProject = new GitProject(project, server); + GitProject gitProject = getGitProject(project); String repositoryName = gitProject.getRepositoryName(); - doWithGit(project, git -> { + doWithGit(gitProject.getProject(), git -> { if (workspace.hasProjectDirectory(project)) { @@ -321,10 +314,12 @@ public class GitOperations { checkout(project, Branch.MAIN); logger.log(project, "git fetch --tags"); - git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call(); + + call(git.fetch() // + .setTagOpt(TagOpt.FETCH_TAGS)); } else { - clone(project); + clone(gitProject); } }); @@ -336,35 +331,44 @@ public class GitOperations { * * @param project must not be {@literal null}. */ - public void fetchTags(Project project) { + public void fetchTags(Project project, Train train) { Assert.notNull(project, "Project must not be null!"); logger.log(project, "Updating project tags…"); - GitProject gitProject = new GitProject(project, server); + GitProject gitProject = getGitProject(train.getSupportedProject(project)); String repositoryName = gitProject.getRepositoryName(); - doWithGit(project, git -> { + doWithGit(gitProject.getProject(), git -> { - if (workspace.hasProjectDirectory(project)) { + if (workspace.hasProjectDirectory(train.getSupportedProject(project))) { logger.log(project, "Found existing repository %s. Obtaining tags…", repositoryName); logger.log(project, "git fetch --tags"); - git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call(); + + call(git.fetch() // + .setTagOpt(TagOpt.FETCH_TAGS)); } else { - clone(project); + clone(gitProject); } }); logger.log(project, "Project tags update done!"); } - public VersionTags getTags(Project project) { + private GitProject getGitProject(SupportedProject project) { + return new GitProject(project, server); + } + + public VersionTags getTags(SupportedProject project) { return doWithGit(project, git -> { - return new VersionTags(project, git.tagList().call().stream()// + + git.tagList().call(); + + return new VersionTags(project.getProject(), git.tagList().call().stream()// .map(ref -> { RevCommit commit = getCommit(git.getRepository(), ref); @@ -403,7 +407,7 @@ public class GitOperations { * @param project must not be {@literal null}. * @return */ - public TicketBranches listTicketBranches(Project project) { + public TicketBranches listTicketBranches(SupportedProject project) { Assert.notNull(project, "Project must not be null!"); @@ -415,7 +419,7 @@ public class GitOperations { update(project); Map ticketIds = getRemoteBranches(project)// - .filter(branch -> branch.isIssueBranch(project.getTracker()))// + .filter(branch -> branch.isIssueBranch(project.getProject().getTracker()))// .collect(Collectors.toMap(Branch::toString, branch -> branch)); Collection tickets = tracker.findTickets(project, ticketIds.keySet()); @@ -442,7 +446,9 @@ public class GitOperations { return trainToUse.getIteration(Iteration.GA); } - Optional mostRecentBefore = getTags(Projects.BUILD) // + SupportedProject build = trainIteration.getSupportedProject(Projects.BUILD); + + Optional mostRecentBefore = getTags(build) // .filter((tag, ti) -> ti.getTrain().equals(trainIteration.getTrain())) // .find((tag, iteration) -> iteration.getIteration().compareTo(trainIteration.getIteration()) < 0, Pair::getSecond); @@ -451,7 +457,8 @@ public class GitOperations { "Cannot determine previous iteration for " + trainIteration.getReleaseTrainNameAndVersion())); } - public List getTicketReferencesBetween(Project project, TrainIteration from, TrainIteration to) { + public List getTicketReferencesBetween(SupportedProject project, TrainIteration from, + TrainIteration to) { VersionTags tags = getTags(project); @@ -459,8 +466,8 @@ public class GitOperations { Repository repo = git.getRepository(); - ModuleIteration toModuleIteration = to.getModule(project); - ObjectId fromTag = resolveLowerBoundary(project, from, tags, repo); + ModuleIteration toModuleIteration = to.getModule(project.getProject()); + ObjectId fromTag = resolveLowerBoundary(project.getProject(), from, tags, repo); ObjectId toTag = resolveUpperBoundary(toModuleIteration, tags, repo); Iterable commits = git.log().addRange(fromTag, toTag).call(); @@ -526,9 +533,13 @@ public class GitOperations { } private static String getFirstCommit(Repository repo) throws IOException { + return getFirstCommit(repo, Branch.MAIN); + } + + private static String getFirstCommit(Repository repo, Branch branch) throws IOException { try (RevWalk revWalk = new RevWalk(repo)) { - return revWalk.parseCommit(repo.resolve("main")).getName(); + return revWalk.parseCommit(repo.resolve(branch.toString())).getName(); } } @@ -547,10 +558,10 @@ public class GitOperations { } private static boolean isGaOrFirstMilestone(Iteration iteration) { - return iteration.isGAIteration() || (iteration.isMilestone() && iteration.getIterationValue() == 1); + return iteration.isGAIteration() || iteration.isMilestone() && iteration.getIterationValue() == 1; } - private Stream getRemoteBranches(Project project) { + private Stream getRemoteBranches(SupportedProject project) { return doWithGit(project, git -> { @@ -576,7 +587,7 @@ public class GitOperations { ExecutionUtils.run(executor, iteration, module -> { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); ObjectId hash = getReleaseHash(module); Tag tag = getTags(project).createTag(module); @@ -646,7 +657,7 @@ public class GitOperations { Assert.notNull(module, "Module iteration must not be null!"); Assert.hasText(summary, "Summary must not be null or empty!"); - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); IssueTracker tracker = issueTracker.getRequiredPluginFor(project, () -> String.format("No issue tracker found for project %s!", project)); Ticket ticket = tracker.getReleaseTicketFor(module); @@ -667,7 +678,7 @@ public class GitOperations { Assert.notNull(module, "Module iteration must not be null!"); Assert.hasText(summary, "Summary must not be null or empty!"); - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); IssueTracker tracker = issueTracker.getRequiredPluginFor(project, () -> String.format("No issue tracker found for project %s!", project)); Ticket ticket = tracker.getReleaseTicketFor(module); @@ -683,11 +694,12 @@ public class GitOperations { * @param summary must not be {@literal null} or empty. * @param details can be {@literal null} or empty. */ - public void commit(ProjectAware module, Ticket ticket, String summary, Optional details, boolean all) { + public void commit(ProjectAware module, Ticket ticket, String summary, Optional details, + boolean all) { Assert.notNull(module, "ProjectAware must not be null!"); - commit(module.getProject(), ticket, summary, details, all); + commit(module.getSupportedProject(), ticket, summary, details, all); } /** @@ -698,7 +710,7 @@ public class GitOperations { * @param summary must not be {@literal null} or empty. * @param details can be {@literal null} or empty. */ - public void commit(Project project, Ticket ticket, String summary, Optional details, boolean all) { + public void commit(SupportedProject project, Ticket ticket, String summary, Optional details, boolean all) { Assert.notNull(project, "Project must not be null!"); Assert.hasText(summary, "Summary must not be null or empty!"); @@ -745,7 +757,7 @@ public class GitOperations { * @param project must not be {@literal null}. * @param filepattern must not be {@literal null} or empty. */ - public void add(Project project, String filepattern) { + public void add(SupportedProject project, String filepattern) { Assert.notNull(project, "Project must not be null!"); @@ -761,14 +773,14 @@ public class GitOperations { } /** - * Checks out the given {@link Branch} of the given {@link Project}. If the given branch doesn't exist yet, a tracking - * branch is created assuming the branch exists in the {@code origin} remote. Pulls the latest changes from the - * checked out branch will be pulled to make sure we see them. + * Checks out the given {@link Branch} of the given {@link SupportedProject}. If the given branch doesn't exist yet, a + * tracking branch is created assuming the branch exists in the {@code origin} remote. Pulls the latest changes from + * the checked out branch will be pulled to make sure we see them. * * @param project must not be {@literal null}. * @param branch must not be {@literal null}. */ - public void checkout(Project project, Branch branch) { + public void checkout(SupportedProject project, Branch branch) { checkout(project, branch, BranchCheckoutMode.CREATE_AND_UPDATE); } @@ -782,7 +794,7 @@ public class GitOperations { * @param branch must not be {@literal null}. * @param mode must not be {@literal null}. */ - private void checkout(Project project, Branch branch, BranchCheckoutMode mode) { + private void checkout(SupportedProject project, Branch branch, BranchCheckoutMode mode) { Assert.notNull(project, "Project must not be null!"); Assert.notNull(branch, "Branch must not be null!"); @@ -822,11 +834,11 @@ public class GitOperations { // Pull latest changes to make sure the branch is up to date logger.log(project, "git pull origin %s", branch); - git.pull()// - .setRemote("origin")// + call(git.pull() // + .setRemote("origin") // .setRebase(true) // - .setRemoteBranchName(branch.toString())// - .call(); + .setRemoteBranchName(branch.toString())); + break; } }); @@ -845,7 +857,7 @@ public class GitOperations { ExecutionUtils.run(executor, iteration, module -> { Branch branch = createMaintenanceBranch(module); - checkout(module.getProject(), branch, BranchCheckoutMode.CREATE_ONLY); + checkout(module.getSupportedProject(), branch, BranchCheckoutMode.CREATE_ONLY); }); } @@ -853,7 +865,7 @@ public class GitOperations { ExecutionUtils.run(executor, iteration, module -> { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); ArtifactVersion artifactVersion = ArtifactVersion.of(module); Optional tag = findTagFor(project, artifactVersion); @@ -875,10 +887,12 @@ public class GitOperations { * Verify general Git operations. */ @SneakyThrows - public void verify() { + public void verify(Train train) { + + SupportedProject project = train.getSupportedProject(Projects.BUILD); - Project project = Projects.BUILD; File projectDirectory = workspace.getProjectDirectory(project); + if (projectDirectory.exists()) { FileUtils.deleteDirectory(projectDirectory); } @@ -891,7 +905,7 @@ public class GitOperations { reset(project, Branch.MAIN); } - private void commitRandomFile(Project project, File projectDirectory) throws IOException { + private void commitRandomFile(SupportedProject project, File projectDirectory) throws IOException { String randomFileName = UUID.randomUUID() + ".txt"; File randomFile = new File(projectDirectory, randomFileName); @@ -925,7 +939,7 @@ public class GitOperations { Branch branch = Branch.from(module.getVersion()); - doWithGit(module.getProject(), git -> { + doWithGit(module.getSupportedProject(), git -> { logger.log(module, "git checkout -b %s", branch); git.branchCreate().setName(branch.toString()).call(); }); @@ -952,14 +966,15 @@ public class GitOperations { Predicate trigger = calculateFilter(module, summary); return findCommit(module, summary).orElseThrow(() -> new IllegalStateException(String - .format("Did not find a commit with summary starting with '%s' for project %s", module.getProject(), trigger))); + .format("Did not find a commit with summary starting with '%s' for project %s", module.getSupportedProject(), + trigger))); } private Optional findCommit(ModuleIteration module, String summary) { - return findCommit(module.getProject(), calculateFilter(module, summary)); + return findCommit(module.getSupportedProject(), calculateFilter(module, summary)); } - private Optional findCommit(Project project, Predicate filter) { + private Optional findCommit(SupportedProject project, Predicate filter) { return doWithGit(project, git -> { @@ -976,7 +991,7 @@ public class GitOperations { private Predicate calculateFilter(ModuleIteration module, String summary) { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); Ticket releaseTicket = issueTracker .getRequiredPluginFor(project, () -> String.format("No issue tracker found for project %s!", project))// .getReleaseTicketFor(module); @@ -999,14 +1014,14 @@ public class GitOperations { * @return * @throws IOException */ - private Optional findTagFor(Project project, ArtifactVersion version) { + private Optional findTagFor(SupportedProject project, ArtifactVersion version) { return getTags(project).stream()// .filter(tag -> tag.toArtifactVersion().map(it -> it.equals(version)).orElse(false))// .findFirst(); } - private Repository getRepository(Project project) throws IOException { + private Repository getRepository(SupportedProject project) throws IOException { Repository repository = FileRepositoryBuilder.create(workspace.getFile(".git", project)); @@ -1017,25 +1032,24 @@ public class GitOperations { return repository; } - private void clone(Project project) throws Exception { + private void clone(GitProject gitProject) throws Exception { - GitProject gitProject = getGitProject(project); + SupportedProject project = gitProject.getProject(); logger.log(project, "No repository found! Cloning from %s…", gitProject.getProjectUri()); - Git git = Git.cloneRepository()// - .setURI(gitProject.getProjectUri())// - .setDirectory(workspace.getProjectDirectory(project))// - .call(); + Git git = call(Git.cloneRepository() // + .setURI(gitProject.getProjectUri()) // + .setDirectory(workspace.getProjectDirectory(project))); - git.checkout()// - .setName(Branch.MAIN.toString())// + git.checkout() // + .setName(Branch.MAIN.toString()) // .call(); logger.log(project, "Cloning done!", project); } - private boolean branchExists(Project project, Branch branch) { + private boolean branchExists(SupportedProject project, Branch branch) { try (Git git = new Git(getRepository(project))) { @@ -1046,7 +1060,7 @@ public class GitOperations { } } - private void reset(Project project, Branch branch) { + private void reset(SupportedProject project, Branch branch) { logger.log(project, "git reset --hard origin/%s", branch); @@ -1063,7 +1077,7 @@ public class GitOperations { return summary.contains("%s") ? String.format(summary, module.getMediumVersionString()) : summary; } - private T doWithGit(Project project, GitCallback callback) { + private T doWithGit(SupportedProject project, GitCallback callback) { try (Git git = new Git(getRepository(project))) { return callback.doWithGit(git); @@ -1081,7 +1095,7 @@ public class GitOperations { } } - private void doWithGit(Project project, VoidGitCallback callback) { + private void doWithGit(SupportedProject project, VoidGitCallback callback) { doWithGit(project, (GitCallback) git -> { callback.doWithGit(git); @@ -1106,6 +1120,13 @@ public class GitOperations { return gpg; } + private > T call(TransportCommand command) throws GitAPIException { + + return command + .setCredentialsProvider(gitProperties.getCredentials()) + .call(); + } + /** * {@link CredentialsProvider} for GPG Keys used with JGit Commit Signing. */ diff --git a/src/main/java/org/springframework/data/release/git/GitProject.java b/src/main/java/org/springframework/data/release/git/GitProject.java index 31ae8eb..2af284e 100644 --- a/src/main/java/org/springframework/data/release/git/GitProject.java +++ b/src/main/java/org/springframework/data/release/git/GitProject.java @@ -17,35 +17,44 @@ package org.springframework.data.release.git; import lombok.AccessLevel; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; /** * @author Oliver Gierke */ @EqualsAndHashCode -@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class GitProject { private static final String PROJECT_PREFIX = "spring-data"; - private final Project project; + private final @Getter SupportedProject project; private final GitServer server; - public static GitProject of(Project project) { + public static GitProject of(SupportedProject project) { return new GitProject(project, GitServer.INSTANCE); } + public static GitProject of(ModuleIteration module) { + return new GitProject(module.getSupportedProject(), GitServer.INSTANCE); + } + /** * Returns the name of the repository the project is using. * * @return */ public String getRepositoryName() { - return String.format("%s-%s", PROJECT_PREFIX, - project == Projects.JDBC ? "relational" : project.getName().toLowerCase()); + + String logicalName = String.format("%s-%s", PROJECT_PREFIX, + project.getProject() == Projects.JDBC ? "relational" : project.getName().toLowerCase()); + + return project.isCommercial() ? logicalName + "-commercial" : logicalName; } /** diff --git a/src/main/java/org/springframework/data/release/git/VersionTags.java b/src/main/java/org/springframework/data/release/git/VersionTags.java index 25307be..60b9165 100644 --- a/src/main/java/org/springframework/data/release/git/VersionTags.java +++ b/src/main/java/org/springframework/data/release/git/VersionTags.java @@ -91,7 +91,7 @@ public class VersionTags implements Streamable { public Tag createTag(ModuleIteration iteration) { - if (iteration.getProject().equals(Projects.BOM)) { + if (iteration.getSupportedProject().equals(Projects.BOM)) { return Tag.of(iteration.getTrainIteration().getReleaseTrainNameAndVersion()); } diff --git a/src/main/java/org/springframework/data/release/infra/DependencyCommands.java b/src/main/java/org/springframework/data/release/infra/DependencyCommands.java index 0422738..e22a57a 100644 --- a/src/main/java/org/springframework/data/release/infra/DependencyCommands.java +++ b/src/main/java/org/springframework/data/release/infra/DependencyCommands.java @@ -34,8 +34,8 @@ import org.springframework.data.release.TimedCommand; import org.springframework.data.release.git.GitOperations; import org.springframework.data.release.issues.Tickets; import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.Logger; import org.springframework.shell.core.annotation.CliCommand; @@ -79,13 +79,14 @@ public class DependencyCommands extends TimedCommand { git.prepare(iteration); - List projects = Projects.all().stream() + List projects = Projects.all().stream() .filter(it -> it != Projects.BOM && it != Projects.BUILD && it != Projects.COMMONS) + .map(iteration::getSupportedProject) .collect(Collectors.toList()); Map dependencies = new TreeMap<>(); - for (Project project : projects) { + for (SupportedProject project : projects) { operations.getCurrentDependencies(project).forEach(dependencies::put); } @@ -113,7 +114,7 @@ public class DependencyCommands extends TimedCommand { ModuleIteration module = iteration.getModule(Projects.BUILD); DependencyVersions dependencyVersions = loadDependencyUpgrades(module); - DependencyVersions upgradesToApply = operations.getDependencyUpgradesToApply(module.getProject(), + DependencyVersions upgradesToApply = operations.getDependencyUpgradesToApply(module.getSupportedProject(), dependencyVersions); if (upgradesToApply.isEmpty()) { @@ -151,12 +152,14 @@ public class DependencyCommands extends TimedCommand { String propertiesFile = "dependency-upgrade-modules.properties"; - List projects = Projects.all().stream().filter(it -> it != Projects.BOM && it != Projects.BUILD) + List projects = Projects.all().stream() + .filter(it -> it != Projects.BOM && it != Projects.BUILD) + .map(iteration::getSupportedProject) .collect(Collectors.toList()); DependencyUpgradeProposals proposals = DependencyUpgradeProposals.empty(); - for (Project project : projects) { + for (SupportedProject project : projects) { proposals = proposals.mergeWith(operations.getDependencyUpgradeProposals(project, iteration.getIteration())); } @@ -172,7 +175,8 @@ public class DependencyCommands extends TimedCommand { String propertiesFile = BUILD_PROPERTIES; - DependencyUpgradeProposals proposals = operations.getDependencyUpgradeProposals(Projects.BUILD, + SupportedProject project = iteration.getSupportedProject(Projects.BUILD); + DependencyUpgradeProposals proposals = operations.getDependencyUpgradeProposals(project, iteration.getIteration()); Files.write(Paths.get(propertiesFile), proposals.asProperties(iteration).getBytes()); diff --git a/src/main/java/org/springframework/data/release/infra/DependencyOperations.java b/src/main/java/org/springframework/data/release/infra/DependencyOperations.java index 0d341b7..a9f4272 100644 --- a/src/main/java/org/springframework/data/release/infra/DependencyOperations.java +++ b/src/main/java/org/springframework/data/release/infra/DependencyOperations.java @@ -55,6 +55,7 @@ import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.data.release.utils.Logger; @@ -65,7 +66,6 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestOperations; - import org.xmlbeam.ProjectionFactory; import org.xmlbeam.annotation.XBRead; import org.xmlbeam.io.FileIO; @@ -102,7 +102,7 @@ public class DependencyOperations { * @param iteration * @return */ - public DependencyUpgradeProposals getDependencyUpgradeProposals(Project project, Iteration iteration) { + public DependencyUpgradeProposals getDependencyUpgradeProposals(SupportedProject project, Iteration iteration) { DependencyVersions currentDependencies = getCurrentDependencies(project); Map proposals = Collections.synchronizedMap(new LinkedHashMap<>()); @@ -132,10 +132,12 @@ public class DependencyOperations { for (ModuleIteration moduleIteration : iteration) { // ensure we have Maven Wrapper for each project. - getMavenWrapperVersion(moduleIteration.getProject()); + getMavenWrapperVersion(moduleIteration.getSupportedProject()); } - return getDependencyUpgradeProposals(Projects.BUILD, DependencyUpgradePolicy.LATEST_STABLE, Dependencies.MAVEN, + SupportedProject build = iteration.getSupportedProject(Projects.BUILD); + + return getDependencyUpgradeProposals(build, DependencyUpgradePolicy.LATEST_STABLE, Dependencies.MAVEN, this::getMavenWrapperVersion); } @@ -154,7 +156,7 @@ public class DependencyOperations { } return doWithDependencyVersionsAndCommit(tickets, module, dependencyVersions, (dependency, version) -> { - upgradeMavenWrapperVersion(module.getProject(), version); + upgradeMavenWrapperVersion(module.getSupportedProject(), version); }); } @@ -164,17 +166,17 @@ public class DependencyOperations { for (ModuleIteration moduleIteration : iteration) { - DependencyVersion currentVersion = getMavenWrapperVersion(moduleIteration.getProject()); + DependencyVersion currentVersion = getMavenWrapperVersion(moduleIteration.getSupportedProject()); if (targetVersion.isNewer(currentVersion)) { - projectsToUpgrade.add(moduleIteration.getProject()); + projectsToUpgrade.add(moduleIteration.getSupportedProject().getProject()); } } return projectsToUpgrade; } - private DependencyVersion getMavenWrapperVersion(Project project) { + private DependencyVersion getMavenWrapperVersion(SupportedProject project) { try { @@ -191,8 +193,8 @@ public class DependencyOperations { } Pattern versionPattern = Pattern.compile(".*/maven2/org/apache/maven/apache-maven/([\\d\\.]+)/.*"); - Matcher matcher = versionPattern.matcher(distributionUrl); + if (!matcher.find()) { throw new IllegalStateException( String.format("Invalid distribution URL in %s: %s", project.getName(), distributionUrl)); @@ -204,7 +206,7 @@ public class DependencyOperations { } } - private void upgradeMavenWrapperVersion(Project project, DependencyVersion dependencyVersion) { + private void upgradeMavenWrapperVersion(SupportedProject project, DependencyVersion dependencyVersion) { String distributionUrlTemplate = "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/%s/apache-maven-%s-bin.zip"; @@ -229,7 +231,7 @@ public class DependencyOperations { } } - private File getMavenWrapperProperties(Project project) throws FileNotFoundException { + private File getMavenWrapperProperties(SupportedProject project) throws FileNotFoundException { File file = workspace.getFile(".mvn/wrapper/maven-wrapper.properties", project); if (!file.exists()) { @@ -238,8 +240,9 @@ public class DependencyOperations { return file; } - public DependencyUpgradeProposals getDependencyUpgradeProposals(Project project, DependencyUpgradePolicy policy, - Dependency dependency, Function currentVersionExtractor) { + public DependencyUpgradeProposals getDependencyUpgradeProposals(SupportedProject project, + DependencyUpgradePolicy policy, Dependency dependency, + Function currentVersionExtractor) { DependencyVersions currentDependencies = new DependencyVersions( Collections.singletonMap(dependency, currentVersionExtractor.apply(project))); @@ -280,7 +283,7 @@ public class DependencyOperations { */ public Tickets upgradeDependencies(Tickets tickets, ModuleIteration module, DependencyVersions dependencyVersions) { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); ProjectDependencies dependencies = ProjectDependencies.get(project); if (dependencyVersions.isEmpty()) { @@ -290,7 +293,7 @@ public class DependencyOperations { return doWithDependencyVersionsAndCommit(tickets, module, dependencyVersions, (dependency, version) -> { String versionProperty = dependencies.getVersionPropertyFor(dependency); - File pom = getPomFile(project); + File pom = getPomFile(module.getSupportedProject()); update(pom, Pom.class, it -> { it.setProperty(versionProperty, version.getIdentifier()); }); @@ -333,7 +336,8 @@ public class DependencyOperations { this.tickets.closeTickets(module, tickets); } - public DependencyVersions getDependencyUpgradesToApply(Project project, DependencyVersions dependencyVersions) { + public DependencyVersions getDependencyUpgradesToApply(SupportedProject project, + DependencyVersions dependencyVersions) { DependencyVersions currentDependencies = getCurrentDependencies(project); Map upgrades = new LinkedHashMap<>(); @@ -452,14 +456,16 @@ public class DependencyOperations { .max(DependencyVersion::compareTo); } - DependencyVersions getCurrentDependencies(Project project) { + DependencyVersions getCurrentDependencies(SupportedProject supportedProject) { + + Project project = supportedProject.getProject(); if (!ProjectDependencies.containsProject(project)) { return DependencyVersions.empty(); } - File pom = getPomFile(project); - ProjectDependencies dependencies = ProjectDependencies.get(project); + File pom = getPomFile(supportedProject); + ProjectDependencies dependencies = ProjectDependencies.get(supportedProject); return doWithPom(pom, Pom.class, it -> { @@ -469,7 +475,7 @@ public class DependencyOperations { Dependency dependency = projectDependency.getDependency(); - if (!((project == Projects.MONGO_DB && projectDependency.getProperty().equals("mongo.reactivestreams")) + if (!(project == Projects.MONGO_DB && projectDependency.getProperty().equals("mongo.reactivestreams") || project == Projects.NEO4J || project == Projects.BUILD)) { if (it.getDependencyVersion(dependency.getArtifactId()) == null @@ -489,8 +495,8 @@ public class DependencyOperations { }); } - private File getPomFile(Project project) { - return workspace.getFile(project == Projects.BUILD ? "parent/pom.xml" : "pom.xml", project); + private File getPomFile(SupportedProject project) { + return workspace.getFile(project.getProject().getProjectDescriptor(), project); } @SneakyThrows @@ -560,7 +566,7 @@ public class DependencyOperations { try { - T pom = (T) io.read(type); + T pom = io.read(type); return callback.apply(pom); } catch (Exception o_O) { @@ -574,7 +580,7 @@ public class DependencyOperations { try { - T pom = (T) io.read(type); + T pom = io.read(type); callback.accept(pom); io.write(pom); diff --git a/src/main/java/org/springframework/data/release/infra/InfrastructureOperations.java b/src/main/java/org/springframework/data/release/infra/InfrastructureOperations.java index 2e8a9c7..2e32249 100644 --- a/src/main/java/org/springframework/data/release/infra/InfrastructureOperations.java +++ b/src/main/java/org/springframework/data/release/infra/InfrastructureOperations.java @@ -30,16 +30,15 @@ import java.util.Properties; import java.util.concurrent.ExecutorService; import org.apache.commons.io.FileUtils; - import org.springframework.data.release.TimedCommand; import org.springframework.data.release.git.Branch; import org.springframework.data.release.git.GitOperations; import org.springframework.data.release.io.Workspace; import org.springframework.data.release.issues.Tickets; -import org.springframework.data.release.model.Module; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; @@ -72,7 +71,7 @@ public class InfrastructureOperations extends TimedCommand { */ void distributeCiProperties(TrainIteration iteration) { - File master = workspace.getFile(CI_PROPERTIES, Projects.BUILD); + File master = workspace.getFile(CI_PROPERTIES, iteration.getSupportedProject(Projects.BUILD)); if (!master.exists()) { throw new IllegalStateException(String.format("CI Properties file %s does not exist", master)); @@ -80,7 +79,7 @@ public class InfrastructureOperations extends TimedCommand { ExecutionUtils.run(executor, iteration, module -> { - Project project = module.getProject(); + SupportedProject project = module.getSupportedProject(); Branch branch = Branch.from(module); git.update(project); @@ -91,12 +90,12 @@ public class InfrastructureOperations extends TimedCommand { ExecutionUtils.run(executor, Streamable.of(iteration.getModulesExcept(Projects.BUILD)), module -> { - File target = workspace.getFile(CI_PROPERTIES, module.getProject()); + File target = workspace.getFile(CI_PROPERTIES, module.getSupportedProject()); target.delete(); FileUtils.copyFile(master, target); - git.add(module.getProject(), CI_PROPERTIES); + git.add(module.getSupportedProject(), CI_PROPERTIES); git.commit(module, "Update CI properties.", Optional.empty(), false); git.push(module); }); @@ -104,8 +103,9 @@ public class InfrastructureOperations extends TimedCommand { private void verifyExistingPropertyFiles(Train train, File master) { - for (Module module : train) { - File target = workspace.getFile(CI_PROPERTIES, module.getProject()); + for (SupportedProject project : train) { + + File target = workspace.getFile(CI_PROPERTIES, project); if (!target.exists()) { throw new IllegalStateException(String.format("CI Properties file %s does not exist", master)); diff --git a/src/main/java/org/springframework/data/release/infra/LicenseHeaderCommands.java b/src/main/java/org/springframework/data/release/infra/LicenseHeaderCommands.java index c5b997b..db22c99 100644 --- a/src/main/java/org/springframework/data/release/infra/LicenseHeaderCommands.java +++ b/src/main/java/org/springframework/data/release/infra/LicenseHeaderCommands.java @@ -38,7 +38,6 @@ import org.apache.commons.io.filefilter.AbstractFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.NameFileFilter; import org.apache.commons.io.filefilter.NotFileFilter; - import org.springframework.data.release.CliComponent; import org.springframework.data.release.TimedCommand; import org.springframework.data.release.git.GitOperations; @@ -49,6 +48,7 @@ import org.springframework.data.release.issues.TicketOperations; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.data.release.utils.Logger; @@ -95,7 +95,7 @@ public class LicenseHeaderCommands extends TimedCommand { if (projectName != null) { Project project = Projects.requiredByName(projectName); - modules = modules.filter(it -> it.getProject().equals(project)); + modules = modules.filter(it -> it.getSupportedProject().equals(project)); } ExecutionUtils.run(executor, modules, module -> { @@ -110,7 +110,7 @@ public class LicenseHeaderCommands extends TimedCommand { private int updateLicense(int year, ModuleIteration module) { - return replaceInFiles(module.getProject(), (file, content) -> { + return replaceInFiles(module.getSupportedProject(), (file, content) -> { String contentToUse = content; @@ -154,7 +154,7 @@ public class LicenseHeaderCommands extends TimedCommand { * @param contentFunction * @return */ - private int replaceInFiles(Project project, Function contentFunction) { + private int replaceInFiles(SupportedProject project, Function contentFunction) { return replaceInFiles(project, (file, s) -> contentFunction.apply(s)); } @@ -165,7 +165,7 @@ public class LicenseHeaderCommands extends TimedCommand { * @param contentFunction * @return */ - private int replaceInFiles(Project project, BiFunction contentFunction) { + private int replaceInFiles(SupportedProject project, BiFunction contentFunction) { File projectDirectory = workspace.getProjectDirectory(project); IOFileFilter fileFilter = new AntPathFileFilter(projectDirectory, filePatterns); diff --git a/src/main/java/org/springframework/data/release/infra/ProjectDependencies.java b/src/main/java/org/springframework/data/release/infra/ProjectDependencies.java index bd49970..82ce9ed 100644 --- a/src/main/java/org/springframework/data/release/infra/ProjectDependencies.java +++ b/src/main/java/org/springframework/data/release/infra/ProjectDependencies.java @@ -22,6 +22,7 @@ import java.util.List; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.util.Streamable; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -104,19 +105,19 @@ public class ProjectDependencies implements Streamable getFiles(String pattern, Project project) { + public Stream getFiles(String pattern, SupportedProject project) { File projectDirectory = getProjectDirectory(project); String patternToLookup = String.format("file:%s/%s", projectDirectory.getAbsolutePath(), pattern); @@ -199,7 +199,7 @@ public class Workspace { } } - public boolean processFile(String filename, Project project, LineCallback callback) { + public boolean processFile(String filename, SupportedProject project, LineCallback callback) { File file = getFile(filename, project); @@ -226,7 +226,7 @@ public class Workspace { return true; } - private void writeContentToFile(String name, Project project, String content) throws IOException { + private void writeContentToFile(String name, SupportedProject project, String content) throws IOException { File file = getFile(name, project); Files.write(file.toPath(), Collections.singleton(content), UTF_8); diff --git a/src/main/java/org/springframework/data/release/issues/IssueTracker.java b/src/main/java/org/springframework/data/release/issues/IssueTracker.java index 2379586..99b7899 100644 --- a/src/main/java/org/springframework/data/release/issues/IssueTracker.java +++ b/src/main/java/org/springframework/data/release/issues/IssueTracker.java @@ -19,10 +19,8 @@ import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.Train; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.plugin.core.Plugin; @@ -32,7 +30,7 @@ import org.springframework.plugin.core.Plugin; * @author Oliver Gierke * @author Mark Paluch */ -public interface IssueTracker extends Plugin { +public interface IssueTracker extends Plugin { /** * Reset internal state (cache, etc). @@ -80,7 +78,7 @@ public interface IssueTracker extends Plugin { * @param ticketIds collection of {@link Ticket#id ticket Ids}, must not be {@literal null}. * @return */ - Collection findTickets(Project project, Collection ticketIds); + Collection findTickets(SupportedProject project, Collection ticketIds); /** * Query the issue tracker for multiple {@link Ticket#id ticket Ids}. Tickets that are not found are not returned. The @@ -133,7 +131,7 @@ public interface IssueTracker extends Plugin { * @param project must not be {@literal null}. * @param ticket must not be {@literal null}. */ - Ticket assignTicketToMe(Project project, Ticket ticket); + Ticket assignTicketToMe(SupportedProject project, Ticket ticket); /** * Assigns the release ticket for the given {@link ModuleIteration} to the current user. diff --git a/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java b/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java index beb7a45..20f450e 100644 --- a/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java +++ b/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java @@ -33,6 +33,7 @@ import org.springframework.data.release.model.Module; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.data.util.Streamable; @@ -50,7 +51,7 @@ import org.springframework.util.StringUtils; @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class IssueTrackerCommands extends TimedCommand { - @NonNull PluginRegistry tracker; + @NonNull PluginRegistry tracker; @NonNull Executor executor; @CliCommand("tracker evict") @@ -199,13 +200,19 @@ public class IssueTrackerCommands extends TimedCommand { } private static Streamable withReleaseProject(TrainIteration iteration) { + + if (iteration.isCommercial()) { + return iteration; + } + ModuleIteration bom = iteration.getModule(Projects.BOM); + return iteration.and(new ModuleIteration(new Module(Projects.RELEASE, bom.getVersion()), iteration)); } private IssueTracker getTrackerFor(ModuleIteration moduleIteration) { - return tracker.getRequiredPluginFor(moduleIteration.getProject(), + return tracker.getRequiredPluginFor(moduleIteration.getSupportedProject(), () -> String.format("No issue tracker found for module %s!", moduleIteration)); } } diff --git a/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java b/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java index a26ea5b..fc83c05 100644 --- a/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java +++ b/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java @@ -15,22 +15,8 @@ */ package org.springframework.data.release.issues; -import java.io.IOException; -import java.net.URI; import java.util.List; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.BasicAuthCache; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cache.CacheManager; @@ -39,16 +25,11 @@ import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.release.issues.github.GitHubProperties; -import org.springframework.data.release.model.Project; -import org.springframework.data.release.utils.HttpBasicCredentials; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.utils.HttpComponentsClientHttpRequestFactoryBuilder; -import org.springframework.data.util.Lazy; -import org.springframework.http.HttpMethod; -import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.plugin.core.OrderAwarePluginRegistry; import org.springframework.plugin.core.PluginRegistry; import com.fasterxml.jackson.annotation.JsonCreator.Mode; @@ -106,8 +87,8 @@ class IssueTrackerConfiguration { } @Bean - PluginRegistry issueTrackers(List plugins) { - return OrderAwarePluginRegistry.of(plugins); + PluginRegistry issueTrackers(List plugins) { + return PluginRegistry.of(plugins); } /** diff --git a/src/main/java/org/springframework/data/release/issues/TicketOperations.java b/src/main/java/org/springframework/data/release/issues/TicketOperations.java index 90f7800..a6e02e6 100644 --- a/src/main/java/org/springframework/data/release/issues/TicketOperations.java +++ b/src/main/java/org/springframework/data/release/issues/TicketOperations.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.Optional; import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.utils.Logger; import org.springframework.plugin.core.PluginRegistry; import org.springframework.stereotype.Component; @@ -40,7 +40,7 @@ public class TicketOperations { Logger logger; - PluginRegistry tracker; + PluginRegistry tracker; /** * Create or look up ticket with a particular summary. @@ -65,8 +65,7 @@ public class TicketOperations { public Tickets getOrCreateTicketsWithSummary(ModuleIteration module, IssueTracker.TicketType ticketType, List summaries) { - Project project = module.getProject(); - + SupportedProject project = module.getSupportedProject(); IssueTracker tracker = this.tracker.getRequiredPluginFor(project); Tickets tickets = tracker.getTicketsFor(module); List results = new ArrayList<>(); @@ -109,7 +108,7 @@ public class TicketOperations { public void closeTickets(ModuleIteration module, Tickets tickets) { - IssueTracker tracker = this.tracker.getRequiredPluginFor(module.getProject()); + IssueTracker tracker = this.tracker.getRequiredPluginFor(module.getSupportedProject()); for (Ticket ticket : tickets) { tracker.closeTicket(module, ticket); diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHub.java b/src/main/java/org/springframework/data/release/issues/github/GitHub.java index 81bc33a..ceca941 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHub.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHub.java @@ -36,14 +36,7 @@ import org.springframework.data.release.issues.IssueTracker; import org.springframework.data.release.issues.Ticket; import org.springframework.data.release.issues.Tickets; import org.springframework.data.release.issues.github.GitHubWorkflows.GitHubWorkflow; -import org.springframework.data.release.model.ArtifactVersion; -import org.springframework.data.release.model.DocumentationMetadata; -import org.springframework.data.release.model.Iteration; -import org.springframework.data.release.model.ModuleIteration; -import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.Projects; -import org.springframework.data.release.model.Tracker; -import org.springframework.data.release.model.TrainIteration; +import org.springframework.data.release.model.*; import org.springframework.data.release.utils.Logger; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -128,7 +121,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { */ @Override @Cacheable("tickets") - public Collection findTickets(Project project, Collection ticketIds) { + public Collection findTickets(SupportedProject project, Collection ticketIds) { String repositoryName = GitProject.of(project).getRepositoryName(); List tickets = new ArrayList<>(); @@ -173,8 +166,8 @@ public class GitHub extends GitHubSupport implements IssueTracker { * @see org.springframework.plugin.core.Plugin#supports(java.lang.Object) */ @Override - public boolean supports(Project project) { - return project.uses(Tracker.GITHUB); + public boolean supports(SupportedProject project) { + return project.getProject().uses(Tracker.GITHUB); } @Override @@ -196,7 +189,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { } Tickets tickets = trainIteration.stream(). // - filter(moduleIteration -> supports(moduleIteration.getProject())). // + filter(moduleIteration -> supports(moduleIteration.getSupportedProject())). // flatMap(moduleIteration -> getTicketsFor(moduleIteration, forCurrentUser).stream()). // collect(Tickets.toTicketsCollector()); @@ -212,7 +205,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { Assert.notNull(moduleIteration, "ModuleIteration must not be null."); - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(moduleIteration).getRepositoryName(); Optional milestone = findMilestone(moduleIteration); if (milestone.isPresent()) { @@ -271,7 +264,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { private Ticket doCreateTicket(ModuleIteration moduleIteration, String text, TicketType ticketType, boolean assignToCurrentUser) { - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(moduleIteration).getRepositoryName(); Milestone milestone = getMilestone(moduleIteration); Label label = TICKET_LABELS.get(ticketType); @@ -298,10 +291,10 @@ public class GitHub extends GitHubSupport implements IssueTracker { /* * (non-Javadoc) - * @see org.springframework.data.release.jira.IssueTracker#assignTicketToMe(org.springframework.data.release.jira.Ticket) + * @see org.springframework.data.release.issues.IssueTracker#assignTicketToMe(org.springframework.data.release.model.SupportedProject, org.springframework.data.release.issues.Ticket) */ @Override - public Ticket assignTicketToMe(Project project, Ticket ticket) { + public Ticket assignTicketToMe(SupportedProject project, Ticket ticket) { Assert.notNull(ticket, "Ticket must not be null."); @@ -332,7 +325,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { Assert.notNull(module, "ModuleIteration must not be null."); - return assignTicketToMe(module.getProject(), getReleaseTicketFor(module)); + return assignTicketToMe(module.getSupportedProject(), getReleaseTicketFor(module)); } /* @@ -362,7 +355,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { private GitHubReadIssue close(ModuleIteration module, Ticket ticket) { - String repositoryName = GitProject.of(module.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(module).getRepositoryName(); Map parameters = newUrlTemplateVariables(); parameters.put("repoName", repositoryName); @@ -390,10 +383,10 @@ public class GitHub extends GitHubSupport implements IssueTracker { Optional milestone = milestoneCache.get(moduleIteration); if (milestone == null) { - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(moduleIteration).getRepositoryName(); milestone = doFindMilestone(moduleIteration, repositoryName, m -> m.matches(moduleIteration)); - if(milestone.isPresent()) { + if (milestone.isPresent()) { milestoneCache.put(moduleIteration, milestone); } } @@ -419,12 +412,12 @@ public class GitHub extends GitHubSupport implements IssueTracker { milestones -> { Optional milestone = milestones.stream(). // - filter(milestonePredicate). // - findFirst(). // - map(m -> { - logger.log(moduleIteration, "Found milestone %s.", m); - return m; - }); + filter(milestonePredicate). // + findFirst(). // + map(m -> { + logger.log(moduleIteration, "Found milestone %s.", m); + return m; + }); if (milestone.isPresent()) { milestoneRef.set(milestone.get()); @@ -460,7 +453,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { HttpHeaders httpHeaders = new HttpHeaders(); - GitProject project = GitProject.of(module.getProject()); + GitProject project = GitProject.of(module); findMilestone(module) // .filter(Milestone::isOpen) // @@ -496,7 +489,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { Map issues = getIssuesFor(moduleIteration, false, true) .collect(Collectors.toMap(GitHubIssue::getId, Function.identity())); - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(moduleIteration).getRepositoryName(); logger.log(moduleIteration, "Looking up GitHub issues …"); Collection foundIssues = ticketIds.stream().filter(it -> it.startsWith("#")).flatMap(it -> { @@ -602,23 +595,23 @@ public class GitHub extends GitHubSupport implements IssueTracker { private String createParticipatingModules(TrainIteration iteration) { Comparator comparator = Comparator - .comparing(moduleIteration -> moduleIteration.getProject().getName()); + .comparing(moduleIteration -> moduleIteration.getSupportedProject().getName()); return iteration.stream().sorted(comparator).map(module -> { Tag tag = VersionTags.empty(module.getProject()).createTag(module); - return String.format("* [Spring Data %s %s](%s%s/releases/tag/%s)%n", module.getProject().getName(), - tag.getName(), GitServer.INSTANCE.getUri(), module.getProject().getFolderName(), tag.getName()); + return String.format("* [Spring Data %s %s](%s%s/releases/tag/%s)%n", module.getSupportedProject().getName(), + tag.getName(), GitServer.INSTANCE.getUri(), module.getSupportedProject().getFolderName(), tag.getName()); }).collect(Collectors.joining()); } /** * Verify GitHub authentication. */ - public void verifyAuthentication() { + public void verifyAuthentication(Train train) { logger.log("GitHub", "Verifying GitHub Authentication…"); - String repositoryName = GitProject.of(Projects.BUILD).getRepositoryName(); + String repositoryName = GitProject.of(train.getSupportedProject(Projects.BUILD)).getRepositoryName(); Map parameters = newUrlTemplateVariables(); parameters.put("repoName", repositoryName); @@ -693,7 +686,8 @@ public class GitHub extends GitHubSupport implements IssueTracker { String referenceDocUrl = documentation.getReferenceDocUrl(); String apiDocUrl = documentation.getApiDocUrl(); - String reference = String.format("* [%s %s Reference documentation](%s)", module.getProject().getFullName(), + String reference = String.format("* [%s %s Reference documentation](%s)", + module.getProject().getFullName(), module.getVersion().toString(), referenceDocUrl); String apidoc = String.format("* [%s %s Javadoc](%s)", module.getProject().getFullName(), @@ -704,7 +698,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { private void createOrUpdateRelease(ModuleIteration module, String body) { - String repositoryName = GitProject.of(module.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(module).getRepositoryName(); Tag tag = VersionTags.empty(module.getProject()).createTag(module); logger.log(module, "Looking up GitHub Release …"); @@ -764,7 +758,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { private Stream getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser, boolean ignoreMissingMilestone) { - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + String repositoryName = GitProject.of(moduleIteration).getRepositoryName(); Optional optionalMilestone = findMilestone(moduleIteration); diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHubCommands.java b/src/main/java/org/springframework/data/release/issues/github/GitHubCommands.java index 0a42f05..68b8f8f 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHubCommands.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHubCommands.java @@ -31,7 +31,9 @@ import org.springframework.data.release.issues.IssueTracker; import org.springframework.data.release.issues.TicketReference; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.model.Tracker; +import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.plugin.core.PluginRegistry; @@ -48,15 +50,17 @@ import org.springframework.shell.core.annotation.CliOption; @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class GitHubCommands extends TimedCommand { - @NonNull PluginRegistry tracker; + @NonNull PluginRegistry tracker; @NonNull GitHub gitHub; @NonNull GitOperations git; @NonNull GitHubLabels gitHubLabels; @NonNull Executor executor; @CliCommand(value = "github update labels") - public void createOrUpdateLabels(@CliOption(key = "", mandatory = true) Project project) { - gitHubLabels.createOrUpdateLabels(project); + public void createOrUpdateLabels( + @CliOption(key = "", mandatory = true) Project project, + @CliOption(key = "train", mandatory = true) Train train) { + gitHubLabels.createOrUpdateLabels(train.getSupportedProject(project)); } @CliCommand(value = "github push") @@ -81,9 +85,9 @@ public class GitHubCommands extends TimedCommand { ExecutionUtils.run(executor, iteration, it -> { - if (it.getProject().getTracker() == Tracker.GITHUB) { + if (it.getSupportedProject().getProject().getTracker() == Tracker.GITHUB) { - List ticketReferences = git.getTicketReferencesBetween(it.getProject(), previousIteration, iteration) + List ticketReferences = git.getTicketReferencesBetween(it.getSupportedProject(), previousIteration, iteration) .stream().map(TicketReference::getId).collect(Collectors.toList()); gitHub.createOrUpdateRelease(iteration, it, ticketReferences); } diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHubLabels.java b/src/main/java/org/springframework/data/release/issues/github/GitHubLabels.java index 66fd428..915f152 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHubLabels.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHubLabels.java @@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.release.git.GitProject; -import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.SupportedProject; import org.springframework.data.release.utils.Logger; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -63,13 +63,15 @@ public class GitHubLabels extends GitHubSupport { * * @param project the project to process. */ - public void createOrUpdateLabels(Project project) { + public void createOrUpdateLabels(SupportedProject project) { logger.log(project, "Obtaining labels…"); - Map parameters = Collections.singletonMap("repoName", GitProject.of(project).getRepositoryName()); + + Map parameters = Collections.singletonMap("repoName", + GitProject.of(project).getRepositoryName()); List