#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:
Oliver Gierke
2016-11-24 15:39:14 +01:00
parent 15935fb9bb
commit 1ddf103be5
3 changed files with 79 additions and 31 deletions

View File

@@ -45,7 +45,7 @@ class GitCommands extends TimedCommand {
private final @NonNull GitOperations git;
@CliCommand("git co train")
@CliCommand("git co-train")
public void checkout(@CliOption(key = "", mandatory = true) Train train) throws Exception {
git.checkout(train);
}
@@ -97,7 +97,7 @@ class GitCommands extends TimedCommand {
public void push(//
@CliOption(key = "", mandatory = true) TrainIteration iteration, //
@CliOption(key = "tags", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") String tags)
throws Exception {
throws Exception {
boolean pushTags = Boolean.parseBoolean(tags);
@@ -135,7 +135,7 @@ class GitCommands extends TimedCommand {
@SuppressWarnings("deprecation")
public Table issuebranches(@CliOption(key = { "" }, mandatory = true) String projectName,
@CliOption(key = "resolved", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") Boolean resolved)
throws Exception {
throws Exception {
Project project = ReleaseTrains.getProjectByName(projectName);
TicketBranches ticketBranches = git.listTicketBranches(project);

View File

@@ -29,6 +29,8 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
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.Git;
import org.eclipse.jgit.api.ResetCommand.ResetType;
@@ -166,8 +168,6 @@ public class GitOperations {
public void prepare(TrainIteration iteration) {
reset(iteration);
ExecutionUtils.run(iteration, module -> {
Project project = module.getProject();
@@ -176,6 +176,8 @@ public class GitOperations {
update(project);
checkout(project, branch);
logger.log(project, "Pulling latest updates for branch %s…", branch);
doWithGit(project, git -> {
logger.log(project, "git pull origin %s", branch);
@@ -183,6 +185,8 @@ public class GitOperations {
.setRebase(true)//
.call();
});
logger.log(project, "Pulling updates done!", branch);
});
reset(iteration);
@@ -240,6 +244,8 @@ public class GitOperations {
Assert.notNull(project, "Project must not be null!");
logger.log(project, "Updating project…");
GitProject gitProject = new GitProject(project, server);
String repositoryName = gitProject.getRepositoryName();
@@ -250,7 +256,6 @@ public class GitOperations {
logger.log(project, "Found existing repository %s. Obtaining latest changes…", repositoryName);
checkout(project, Branch.MASTER);
reset(project, Branch.MASTER);
logger.log(project, "git fetch --tags");
git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call();
@@ -259,12 +264,11 @@ public class GitOperations {
git.pull().call();
} else {
logger.log(project, "No repository found! Cloning from %s…", gitProject.getProjectUri());
clone(project);
}
});
logger.log(project, "Project update done!");
}
public VersionTags getTags(Project project) {
@@ -416,6 +420,7 @@ public class GitOperations {
git.commit()//
.setMessage(commit.toString())//
.setAuthor(author, email)//
.setCommitter(author, email)//
.setAll(true)//
.call();
});
@@ -434,6 +439,8 @@ public class GitOperations {
Assert.notNull(project, "Project must not be null!");
Assert.notNull(branch, "Branch must not be null!");
logger.log(project, "Checking out project…");
doWithGit(project, git -> {
Optional<Ref> ref = Optional.ofNullable(git.getRepository().findRef(branch.toString()));
@@ -466,6 +473,8 @@ public class GitOperations {
.setRemoteBranchName(branch.toString())//
.call();
});
logger.log(project, "Checkout done!");
}
public void createMaintenanceBranches(TrainIteration iteration) {
@@ -525,13 +534,16 @@ public class GitOperations {
doWithGit(project, git -> {
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) {
@@ -546,9 +558,16 @@ public class GitOperations {
return;
}
git.cherryPick().include(id).call();
logger.log(project, "Successfully cherry-picked commit %s to branch %s.", id.getName(), branch);
logger.log(project, "git cp %s", id.getName());
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
*/
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");
}
private ObjectId findCommit(ModuleIteration module, String summary) {
private ObjectId findRequiredCommit(ModuleIteration module, String summary) {
Project project = module.getProject();
Ticket releaseTicket = issueTracker.getPluginFor(project).getReleaseTicketFor(module);
String trigger = String.format("%s - %s", releaseTicket.getId(), summary);
String trigger = calculateTrigger(module, 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()) {
if (commit.getShortMessage().startsWith(trigger)) {
return commit.getId();
return Optional.of(commit.getId());
}
}
throw new IllegalStateException(
String.format("Did not find a commit with summary starting with '%s' for project %s", project, trigger));
return Optional.empty();
});
}
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}.
*
@@ -632,14 +664,20 @@ public class GitOperations {
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()//
.setURI(getGitProject(project).getProjectUri())//
.setURI(gitProject.getProjectUri())//
.setDirectory(workspace.getProjectDirectory(project))//
.call();
git.checkout()//
.setName(Branch.MASTER.toString())//
.call();
logger.log(project, "Cloning done!", project);
}
private boolean branchExists(Project project, Branch branch) {
@@ -657,9 +695,13 @@ public class GitOperations {
logger.log(project, "git reset --hard origin/%s", branch);
try (Git git = new Git(getRepository(project))) {
git.reset().setMode(ResetType.HARD).setRef("origin/".concat(branch.toString())).call();
}
doWithGit(project, git -> {
git.reset()//
.setMode(ResetType.HARD)//
.setRef("origin/".concat(branch.toString()))//
.call();
});
}
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) {
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) {
throw new RuntimeException(o_O);
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.release.utils;
import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
@@ -29,6 +31,7 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
*/
@Slf4j
public class ExecutionUtils {
/**
@@ -49,6 +52,7 @@ public class ExecutionUtils {
try {
consumer.accept(it);
} catch (Exception o_O) {
log.error(o_O.getMessage(), o_O);
throw new RuntimeException(o_O);
}
})).collect(Collectors.toList()).forEach(future -> future.join());