Update Jenkinsfile after branching.

Closes #99
This commit is contained in:
Mark Paluch
2024-11-13 10:53:02 +01:00
parent 37b7444010
commit 6371024358
7 changed files with 185 additions and 13 deletions

View File

@@ -29,6 +29,7 @@ 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.git.BranchMapping;
import org.springframework.data.release.model.ModuleIteration;
import org.springframework.data.release.model.Phase;
import org.springframework.data.release.model.ProjectAware;
@@ -76,6 +77,16 @@ public class BuildOperations {
logger.log(iteration, "Update Project Descriptors done: %s", summary);
}
public void updateBuildConfig(TrainIteration iteration, BranchMapping branches) throws Exception {
Assert.notNull(iteration, "Train iteration must not be null!");
BuildExecutor.Summary<ModuleIteration> summary = executor.doWithBuildSystemOrdered(iteration,
(system, it) -> system.updateBuildConfig(it, branches));
logger.log(iteration, "Update Build config done: %s", summary);
}
/**
* Prepares the versions of the given {@link TrainIteration} depending on the given {@link Phase}.
*
@@ -414,4 +425,5 @@ public class BuildOperations {
return function.apply(buildSystem.withJavaVersion(executor.detectJavaVersion(module.getSupportedProject())),
module);
}
}

View File

@@ -17,11 +17,12 @@ package org.springframework.data.release.build;
import org.springframework.data.release.deployment.DeploymentInformation;
import org.springframework.data.release.deployment.StagingRepository;
import org.springframework.data.release.git.BranchMapping;
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.SupportedProject;
import org.springframework.data.release.model.ProjectAware;
import org.springframework.data.release.model.SupportedProject;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.plugin.core.Plugin;
@@ -43,6 +44,14 @@ interface BuildSystem extends Plugin<SupportedProject> {
*/
<M extends ProjectAware> M updateProjectDescriptors(M iteration, UpdateInformation updateInformation);
/**
* Updates the project build config for the given {@link ModuleIteration}.
*
* @param iteration must not be {@literal null}.
* @param branches must not be {@literal null}.
*/
ModuleIteration updateBuildConfig(ModuleIteration iteration, BranchMapping branches);
/**
* Prepares the project descriptor of the {@link ModuleIteration} for the given release {@link Phase}.
*
@@ -139,4 +148,5 @@ interface BuildSystem extends Plugin<SupportedProject> {
* @return
*/
BuildSystem withJavaVersion(JavaVersion javaVersion);
}

View File

@@ -21,6 +21,7 @@ import static org.springframework.data.release.model.Projects.*;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.FieldDefaults;
import java.io.BufferedInputStream;
@@ -31,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Pattern;
@@ -51,6 +53,9 @@ 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.git.Branch;
import org.springframework.data.release.git.BranchMapping;
import org.springframework.data.release.git.GitProject;
import org.springframework.data.release.io.Workspace;
import org.springframework.data.release.model.*;
import org.springframework.data.release.utils.Logger;
@@ -126,6 +131,42 @@ class MavenBuildSystem implements BuildSystem {
return module;
}
@Override
@SneakyThrows
public ModuleIteration updateBuildConfig(ModuleIteration module, BranchMapping branches) {
File jenkinsfile = workspace.getFile("Jenkinsfile", module.getSupportedProject());
if (!jenkinsfile.exists()) {
logger.warn(module, "No Jenkinsfile found, skipping Jenkinsfile update.");
}
byte[] bytes = Files.readAllBytes(jenkinsfile.toPath());
String content = new String(bytes, StandardCharsets.UTF_8);
for (ModuleIteration participatingModule : module.getTrainIteration()) {
Branch source = branches.getSourceBranch(participatingModule.getProject());
Branch target = branches.getTargetBranch(participatingModule.getProject());
if (source == null || target == null) {
continue;
}
GitProject project = GitProject.of(participatingModule.getSupportedProject());
String dependency = String.format("%s/%s", project.getRepositoryName(), source);
String replacement = String.format("%s/%s", project.getRepositoryName(), target);
content = content.replace(dependency, replacement);
}
Files.write(jenkinsfile.toPath(), content.getBytes(StandardCharsets.UTF_8));
logger.warn(module, "Jenkinsfile updated.");
return module;
}
/*
* (non-Javadoc)
* @see org.springframework.data.release.build.BuildSystem#prepareVersion(org.springframework.data.release.model.ModuleIteration, org.springframework.data.release.model.Phase)

View File

@@ -30,6 +30,7 @@ import org.springframework.data.release.build.BuildOperations;
import org.springframework.data.release.deployment.DeploymentInformation;
import org.springframework.data.release.deployment.DeploymentOperations;
import org.springframework.data.release.deployment.StagingRepository;
import org.springframework.data.release.git.BranchMapping;
import org.springframework.data.release.git.GitOperations;
import org.springframework.data.release.issues.IssueTrackerCommands;
import org.springframework.data.release.issues.github.GitHubCommands;
@@ -188,7 +189,7 @@ class ReleaseCommands extends TimedCommand {
git.tagRelease(iteration);
if (iteration.getTrain().isAlwaysUseBranch()) {
setupMaintenanceVersions(iteration);
setupMaintenanceVersions(iteration, BranchMapping.NONE);
} else {
build.prepareVersions(iteration, Phase.CLEANUP);
@@ -202,11 +203,14 @@ class ReleaseCommands extends TimedCommand {
if (iteration.getIteration().isGAIteration()) {
// Create bugfix branches
git.createMaintenanceBranches(iteration);
BranchMapping branches = git.createMaintenanceBranches(iteration, true);
// Set project version to maintenance once
setupMaintenanceVersions(iteration);
}
}
setupMaintenanceVersions(iteration, branches);
}
}
}
@@ -229,10 +233,9 @@ class ReleaseCommands extends TimedCommand {
gitHub.triggerAntoraWorkflow(project);
}
});
}
private void setupMaintenanceVersions(TrainIteration iteration) throws Exception {
private void setupMaintenanceVersions(TrainIteration iteration, BranchMapping branches) throws Exception {
// Set project version to maintenance once
build.prepareVersions(iteration, Phase.MAINTENANCE);
@@ -240,6 +243,11 @@ class ReleaseCommands extends TimedCommand {
// Update inter-project dependencies and repositories
build.updateProjectDescriptors(iteration, Phase.MAINTENANCE);
if (branches.hasBranches()) {
build.updateBuildConfig(iteration, branches);
}
git.commit(iteration, "After release cleanups.");
// Back to main branch

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.release.git;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.release.model.Project;
/**
* Value object to capture source and target branches for a {@link Project}
*
* @author Mark Paluch
*/
public class BranchMapping {
public static final BranchMapping NONE = new BranchMapping(Collections.emptyMap(), Collections.emptyMap());
private final Map<Project, Branch> sourceBranches;
private final Map<Project, Branch> targetBranches;
public BranchMapping() {
this(new HashMap<>(), new HashMap<>());
}
private BranchMapping(Map<Project, Branch> sourceBranches, Map<Project, Branch> targetBranches) {
this.sourceBranches = sourceBranches;
this.targetBranches = targetBranches;
}
public void add(Project project, Branch sourceBranch, Branch targetBranch) {
sourceBranches.put(project, sourceBranch);
targetBranches.put(project, targetBranch);
}
public Branch getSourceBranch(Project project) {
return sourceBranches.get(project);
}
public Branch getTargetBranch(Project project) {
return targetBranches.get(project);
}
public boolean hasBranches() {
return !sourceBranches.isEmpty() && !targetBranches.isEmpty();
}
}

View File

@@ -39,6 +39,7 @@ 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.ListBranchCommand;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.TransportCommand;
@@ -925,18 +926,41 @@ public class GitOperations {
logger.log(project, "Checkout done!");
}
public void createMaintenanceBranches(TrainIteration iteration) {
public BranchMapping createMaintenanceBranches(TrainIteration iteration, boolean checkout) {
if (!iteration.getIteration().isGAIteration()) {
return;
if (checkout && !iteration.getIteration().isGAIteration()) {
return BranchMapping.NONE;
}
checkout(iteration);
if (checkout) {
checkout(iteration);
}
return createBranch(iteration);
}
public BranchMapping createBranch(TrainIteration iteration) {
BranchMapping branches = new BranchMapping();
ExecutionUtils.run(executor, iteration, module -> {
Branch branch = createMaintenanceBranch(module);
checkout(module.getSupportedProject(), branch, BranchCheckoutMode.CREATE_ONLY);
Branch current = getCurrentBranch(module);
Branch newBranch = createBranch(module);
checkout(module.getSupportedProject(), newBranch, BranchCheckoutMode.CREATE_ONLY);
synchronized (branches) {
branches.add(module.getProject(), current, newBranch);
}
});
return branches;
}
private Branch getCurrentBranch(ModuleIteration module) {
return doWithGit(module.getSupportedProject(), git -> {
return Branch.from(git.getRepository().getBranch());
});
}
@@ -1012,13 +1036,26 @@ public class GitOperations {
* @param module must not be {@literal null}.
* @return
*/
private Branch createMaintenanceBranch(ModuleIteration module) {
private Branch createBranch(ModuleIteration module) {
Assert.notNull(module, "Module iteration must not be null!");
Branch branch = Branch.from(module.getVersion());
doWithGit(module.getSupportedProject(), git -> {
List<String> existingBranches = git.branchList().setListMode(ListBranchCommand.ListMode.ALL) //
.call() //
.stream() //
.filter(ref -> ref.getName().startsWith("refs/heads/")) //
.map(it -> it.getName().substring(11)) //
.collect(Collectors.toList());
if (existingBranches.contains(branch.toString())) {
logger.log(module, "Branch %s already exists, skipping creation.", branch);
return;
}
logger.log(module, "git checkout -b %s", branch);
git.branchCreate().setName(branch.toString()).call();
});

View File

@@ -126,7 +126,8 @@ public class ReleaseTrains {
.withCalver("2025.0");
Z = Y.next("Z", Transition.MAJOR) //
.withCalver("2025.1");
.withCalver("2025.1") //
.withAlwaysUseBranch(true);
// Trains