#34 - More logging in GitOperations.
Removed some unnecessary resets along the way. Failed cherry picks now get logged explicitly so that they can be resolved manually.
This commit is contained in:
@@ -45,7 +45,7 @@ class GitCommands extends TimedCommand {
|
|||||||
|
|
||||||
private final @NonNull GitOperations git;
|
private final @NonNull GitOperations git;
|
||||||
|
|
||||||
@CliCommand("git co train")
|
@CliCommand("git co-train")
|
||||||
public void checkout(@CliOption(key = "", mandatory = true) Train train) throws Exception {
|
public void checkout(@CliOption(key = "", mandatory = true) Train train) throws Exception {
|
||||||
git.checkout(train);
|
git.checkout(train);
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ class GitCommands extends TimedCommand {
|
|||||||
public void push(//
|
public void push(//
|
||||||
@CliOption(key = "", mandatory = true) TrainIteration iteration, //
|
@CliOption(key = "", mandatory = true) TrainIteration iteration, //
|
||||||
@CliOption(key = "tags", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") String tags)
|
@CliOption(key = "tags", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") String tags)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
boolean pushTags = Boolean.parseBoolean(tags);
|
boolean pushTags = Boolean.parseBoolean(tags);
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ class GitCommands extends TimedCommand {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public Table issuebranches(@CliOption(key = { "" }, mandatory = true) String projectName,
|
public Table issuebranches(@CliOption(key = { "" }, mandatory = true) String projectName,
|
||||||
@CliOption(key = "resolved", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") Boolean resolved)
|
@CliOption(key = "resolved", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") Boolean resolved)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Project project = ReleaseTrains.getProjectByName(projectName);
|
Project project = ReleaseTrains.getProjectByName(projectName);
|
||||||
TicketBranches ticketBranches = git.listTicketBranches(project);
|
TicketBranches ticketBranches = git.listTicketBranches(project);
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.eclipse.jgit.api.CheckoutCommand;
|
import org.eclipse.jgit.api.CheckoutCommand;
|
||||||
|
import org.eclipse.jgit.api.CherryPickResult;
|
||||||
|
import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
|
||||||
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
import org.eclipse.jgit.api.ResetCommand.ResetType;
|
import org.eclipse.jgit.api.ResetCommand.ResetType;
|
||||||
@@ -166,8 +168,6 @@ public class GitOperations {
|
|||||||
|
|
||||||
public void prepare(TrainIteration iteration) {
|
public void prepare(TrainIteration iteration) {
|
||||||
|
|
||||||
reset(iteration);
|
|
||||||
|
|
||||||
ExecutionUtils.run(iteration, module -> {
|
ExecutionUtils.run(iteration, module -> {
|
||||||
|
|
||||||
Project project = module.getProject();
|
Project project = module.getProject();
|
||||||
@@ -176,6 +176,8 @@ public class GitOperations {
|
|||||||
update(project);
|
update(project);
|
||||||
checkout(project, branch);
|
checkout(project, branch);
|
||||||
|
|
||||||
|
logger.log(project, "Pulling latest updates for branch %s…", branch);
|
||||||
|
|
||||||
doWithGit(project, git -> {
|
doWithGit(project, git -> {
|
||||||
|
|
||||||
logger.log(project, "git pull origin %s", branch);
|
logger.log(project, "git pull origin %s", branch);
|
||||||
@@ -183,6 +185,8 @@ public class GitOperations {
|
|||||||
.setRebase(true)//
|
.setRebase(true)//
|
||||||
.call();
|
.call();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logger.log(project, "Pulling updates done!", branch);
|
||||||
});
|
});
|
||||||
|
|
||||||
reset(iteration);
|
reset(iteration);
|
||||||
@@ -240,6 +244,8 @@ public class GitOperations {
|
|||||||
|
|
||||||
Assert.notNull(project, "Project must not be null!");
|
Assert.notNull(project, "Project must not be null!");
|
||||||
|
|
||||||
|
logger.log(project, "Updating project…");
|
||||||
|
|
||||||
GitProject gitProject = new GitProject(project, server);
|
GitProject gitProject = new GitProject(project, server);
|
||||||
String repositoryName = gitProject.getRepositoryName();
|
String repositoryName = gitProject.getRepositoryName();
|
||||||
|
|
||||||
@@ -250,7 +256,6 @@ public class GitOperations {
|
|||||||
logger.log(project, "Found existing repository %s. Obtaining latest changes…", repositoryName);
|
logger.log(project, "Found existing repository %s. Obtaining latest changes…", repositoryName);
|
||||||
|
|
||||||
checkout(project, Branch.MASTER);
|
checkout(project, Branch.MASTER);
|
||||||
reset(project, Branch.MASTER);
|
|
||||||
|
|
||||||
logger.log(project, "git fetch --tags");
|
logger.log(project, "git fetch --tags");
|
||||||
git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call();
|
git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call();
|
||||||
@@ -259,12 +264,11 @@ public class GitOperations {
|
|||||||
git.pull().call();
|
git.pull().call();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
logger.log(project, "No repository found! Cloning from %s…", gitProject.getProjectUri());
|
|
||||||
|
|
||||||
clone(project);
|
clone(project);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logger.log(project, "Project update done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public VersionTags getTags(Project project) {
|
public VersionTags getTags(Project project) {
|
||||||
@@ -416,6 +420,7 @@ public class GitOperations {
|
|||||||
git.commit()//
|
git.commit()//
|
||||||
.setMessage(commit.toString())//
|
.setMessage(commit.toString())//
|
||||||
.setAuthor(author, email)//
|
.setAuthor(author, email)//
|
||||||
|
.setCommitter(author, email)//
|
||||||
.setAll(true)//
|
.setAll(true)//
|
||||||
.call();
|
.call();
|
||||||
});
|
});
|
||||||
@@ -434,6 +439,8 @@ public class GitOperations {
|
|||||||
Assert.notNull(project, "Project must not be null!");
|
Assert.notNull(project, "Project must not be null!");
|
||||||
Assert.notNull(branch, "Branch must not be null!");
|
Assert.notNull(branch, "Branch must not be null!");
|
||||||
|
|
||||||
|
logger.log(project, "Checking out project…");
|
||||||
|
|
||||||
doWithGit(project, git -> {
|
doWithGit(project, git -> {
|
||||||
|
|
||||||
Optional<Ref> ref = Optional.ofNullable(git.getRepository().findRef(branch.toString()));
|
Optional<Ref> ref = Optional.ofNullable(git.getRepository().findRef(branch.toString()));
|
||||||
@@ -466,6 +473,8 @@ public class GitOperations {
|
|||||||
.setRemoteBranchName(branch.toString())//
|
.setRemoteBranchName(branch.toString())//
|
||||||
.call();
|
.call();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logger.log(project, "Checkout done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createMaintenanceBranches(TrainIteration iteration) {
|
public void createMaintenanceBranches(TrainIteration iteration) {
|
||||||
@@ -525,13 +534,16 @@ public class GitOperations {
|
|||||||
doWithGit(project, git -> {
|
doWithGit(project, git -> {
|
||||||
|
|
||||||
checkout(project, backportTargets.getSource());
|
checkout(project, backportTargets.getSource());
|
||||||
ObjectId objectId = getChangelogUpdate(module);
|
Optional<ObjectId> objectId = getChangelogUpdate(module);
|
||||||
|
|
||||||
|
objectId.ifPresent(it -> backportTargets.forEach(target -> cherryPickCommitToBranch(it, project, target)));
|
||||||
|
|
||||||
|
if (!objectId.isPresent()) {
|
||||||
|
logger.log(project, "No changelog commit found, skipping backports!");
|
||||||
|
}
|
||||||
|
|
||||||
backportTargets.forEach(target -> cherryPickCommitToBranch(objectId, project, target));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
update(iteration.getTrain());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cherryPickCommitToBranch(ObjectId id, Project project, Branch branch) {
|
private void cherryPickCommitToBranch(ObjectId id, Project project, Branch branch) {
|
||||||
@@ -546,9 +558,16 @@ public class GitOperations {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
git.cherryPick().include(id).call();
|
logger.log(project, "git cp %s", id.getName());
|
||||||
logger.log(project, "Successfully cherry-picked commit %s to branch %s.", id.getName(), branch);
|
CherryPickResult result = git.cherryPick().include(id).call();
|
||||||
|
|
||||||
|
if (result.getStatus().equals(CherryPickStatus.OK)) {
|
||||||
|
logger.log(project, "Successfully cherry-picked commit %s to branch %s.", id.getName(), branch);
|
||||||
|
} else {
|
||||||
|
logger.log(project, "Cherry pick failed. aborting…");
|
||||||
|
logger.log(project, "git reset --hard");
|
||||||
|
git.reset().setMode(ResetType.HARD).call();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,34 +602,47 @@ public class GitOperations {
|
|||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private ObjectId getReleaseHash(ModuleIteration module) {
|
private ObjectId getReleaseHash(ModuleIteration module) {
|
||||||
return findCommit(module, "Release");
|
return findRequiredCommit(module, "Release");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectId getChangelogUpdate(ModuleIteration module) {
|
private Optional<ObjectId> getChangelogUpdate(ModuleIteration module) {
|
||||||
return findCommit(module, "Updated changelog");
|
return findCommit(module, "Updated changelog");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectId findCommit(ModuleIteration module, String summary) {
|
private ObjectId findRequiredCommit(ModuleIteration module, String summary) {
|
||||||
|
|
||||||
Project project = module.getProject();
|
String trigger = calculateTrigger(module, summary);
|
||||||
Ticket releaseTicket = issueTracker.getPluginFor(project).getReleaseTicketFor(module);
|
|
||||||
String trigger = String.format("%s - %s", releaseTicket.getId(), summary);
|
|
||||||
|
|
||||||
return doWithGit(module.getProject(), git -> {
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ObjectId> findCommit(ModuleIteration module, String summary) {
|
||||||
|
return findCommitWithTrigger(module.getProject(), calculateTrigger(module, summary));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ObjectId> findCommitWithTrigger(Project project, String trigger) {
|
||||||
|
|
||||||
|
return doWithGit(project, git -> {
|
||||||
|
|
||||||
for (RevCommit commit : git.log().setMaxCount(50).call()) {
|
for (RevCommit commit : git.log().setMaxCount(50).call()) {
|
||||||
|
|
||||||
if (commit.getShortMessage().startsWith(trigger)) {
|
if (commit.getShortMessage().startsWith(trigger)) {
|
||||||
return commit.getId();
|
return Optional.of(commit.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException(
|
return Optional.empty();
|
||||||
String.format("Did not find a commit with summary starting with '%s' for project %s", project, trigger));
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String calculateTrigger(ModuleIteration module, String summary) {
|
||||||
|
|
||||||
|
Project project = module.getProject();
|
||||||
|
Ticket releaseTicket = issueTracker.getPluginFor(project).getReleaseTicketFor(module);
|
||||||
|
return String.format("%s - %s", releaseTicket.getId(), summary);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Tag} that represents the {@link ArtifactVersion} of the given {@link Project}.
|
* Returns the {@link Tag} that represents the {@link ArtifactVersion} of the given {@link Project}.
|
||||||
*
|
*
|
||||||
@@ -632,14 +664,20 @@ public class GitOperations {
|
|||||||
|
|
||||||
private void clone(Project project) throws Exception {
|
private void clone(Project project) throws Exception {
|
||||||
|
|
||||||
|
GitProject gitProject = getGitProject(project);
|
||||||
|
|
||||||
|
logger.log(project, "No repository found! Cloning from %s…", gitProject.getProjectUri());
|
||||||
|
|
||||||
Git git = Git.cloneRepository()//
|
Git git = Git.cloneRepository()//
|
||||||
.setURI(getGitProject(project).getProjectUri())//
|
.setURI(gitProject.getProjectUri())//
|
||||||
.setDirectory(workspace.getProjectDirectory(project))//
|
.setDirectory(workspace.getProjectDirectory(project))//
|
||||||
.call();
|
.call();
|
||||||
|
|
||||||
git.checkout()//
|
git.checkout()//
|
||||||
.setName(Branch.MASTER.toString())//
|
.setName(Branch.MASTER.toString())//
|
||||||
.call();
|
.call();
|
||||||
|
|
||||||
|
logger.log(project, "Cloning done!", project);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean branchExists(Project project, Branch branch) {
|
private boolean branchExists(Project project, Branch branch) {
|
||||||
@@ -657,9 +695,13 @@ public class GitOperations {
|
|||||||
|
|
||||||
logger.log(project, "git reset --hard origin/%s", branch);
|
logger.log(project, "git reset --hard origin/%s", branch);
|
||||||
|
|
||||||
try (Git git = new Git(getRepository(project))) {
|
doWithGit(project, git -> {
|
||||||
git.reset().setMode(ResetType.HARD).setRef("origin/".concat(branch.toString())).call();
|
|
||||||
}
|
git.reset()//
|
||||||
|
.setMode(ResetType.HARD)//
|
||||||
|
.setRef("origin/".concat(branch.toString()))//
|
||||||
|
.call();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String expandSummary(String summary, ModuleIteration module, TrainIteration iteration) {
|
private static String expandSummary(String summary, ModuleIteration module, TrainIteration iteration) {
|
||||||
@@ -669,7 +711,9 @@ public class GitOperations {
|
|||||||
private <T> T doWithGit(Project project, GitCallback<T> callback) {
|
private <T> T doWithGit(Project project, GitCallback<T> callback) {
|
||||||
|
|
||||||
try (Git git = new Git(getRepository(project))) {
|
try (Git git = new Git(getRepository(project))) {
|
||||||
return callback.doWithGit(git);
|
T result = callback.doWithGit(git);
|
||||||
|
Thread.sleep(100);
|
||||||
|
return result;
|
||||||
} catch (Exception o_O) {
|
} catch (Exception o_O) {
|
||||||
throw new RuntimeException(o_O);
|
throw new RuntimeException(o_O);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.release.utils;
|
package org.springframework.data.release.utils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -29,6 +31,7 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class ExecutionUtils {
|
public class ExecutionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +52,7 @@ public class ExecutionUtils {
|
|||||||
try {
|
try {
|
||||||
consumer.accept(it);
|
consumer.accept(it);
|
||||||
} catch (Exception o_O) {
|
} catch (Exception o_O) {
|
||||||
|
log.error(o_O.getMessage(), o_O);
|
||||||
throw new RuntimeException(o_O);
|
throw new RuntimeException(o_O);
|
||||||
}
|
}
|
||||||
})).collect(Collectors.toList()).forEach(future -> future.join());
|
})).collect(Collectors.toList()).forEach(future -> future.join());
|
||||||
|
|||||||
Reference in New Issue
Block a user