From 84e22a0bf7000eae379e2acb3ad2a551381ba6e4 Mon Sep 17 00:00:00 2001 From: Lee Worrall Date: Mon, 21 Dec 2020 15:15:10 +0800 Subject: [PATCH] If no branch is specified, use any advertised default, not just master If the FetchResult HEAD is a SymbolicRef then that is the default branch, build that, else if there is a master which points to the same object as HEAD, build that, else look for any branch that points to the same object as HEAD and build that. --- pom.xml | 2 +- .../restabuild/build/ProjectManager.java | 57 ++++++++- .../restabuild/web/BuildResource.java | 9 +- src/main/resources/web/index.html | 2 +- src/main/resources/web/restabuild.js | 9 +- .../restabuild/build/ProjectManagerTest.java | 120 +++++++++++++++--- src/test/java/scaffolding/AppRepo.java | 13 ++ 7 files changed, 181 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 29dff13..377129f 100644 --- a/pom.xml +++ b/pom.xml @@ -136,7 +136,7 @@ org.eclipse.jgit org.eclipse.jgit - 5.5.1.201910021850-r + 5.10.0.202012080955-r diff --git a/src/main/java/com/danielflower/restabuild/build/ProjectManager.java b/src/main/java/com/danielflower/restabuild/build/ProjectManager.java index d023dd6..fa44d65 100644 --- a/src/main/java/com/danielflower/restabuild/build/ProjectManager.java +++ b/src/main/java/com/danielflower/restabuild/build/ProjectManager.java @@ -16,6 +16,7 @@ import org.eclipse.jgit.lib.*; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.FetchResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,12 +97,14 @@ static class ExtendedBuildState { public final String commitIDAfterBuild; public final List tagsAdded; public final File workDir; - ExtendedBuildState(BuildState buildState, String commitIDBeforeBuild, String commitIDAfterBuild, List tagsAdded, File workDir) { + public final String branch; + ExtendedBuildState(BuildState buildState, String commitIDBeforeBuild, String commitIDAfterBuild, List tagsAdded, File workDir, String branch) { this.buildState = buildState; this.commitIDBeforeBuild = commitIDBeforeBuild; this.commitIDAfterBuild = commitIDAfterBuild; this.tagsAdded = tagsAdded; this.workDir = workDir; + this.branch = branch; } } @@ -110,10 +113,11 @@ public ExtendedBuildState build(Writer outputHandler, String branch, String buil final File workDir; final ExtendedBuildState extendedBuildState; try (Git git = pullFromGitAndCopyWorkingCopyToNewDir(outputHandler, branch)) { + branch = git.getRepository().getBranch(); workDir = git.getRepository().getWorkTree(); doubleLog(outputHandler, "Created new instance in " + dirPath(workDir)); - Ref headBefore = git.getRepository().exactRef("HEAD"); + Ref headBefore = git.getRepository().exactRef(Constants.HEAD); Ref headAfter = headBefore; ObjectId beforeCommitID = headBefore.getObjectId(); List newTags = new ArrayList<>(); @@ -140,7 +144,7 @@ public ExtendedBuildState build(Writer outputHandler, String branch, String buil ProcessStarter processStarter = new ProcessStarter(outputHandler); result = processStarter.run(outputHandler, command, workDir, TimeUnit.MINUTES.toMillis(buildTimeout), environment); - headAfter = git.getRepository().exactRef("HEAD"); + headAfter = git.getRepository().exactRef(Constants.HEAD); try (RevWalk walk = new RevWalk(git.getRepository())) { walk.markStart(walk.parseCommit(headAfter.getObjectId())); @@ -154,7 +158,7 @@ public ExtendedBuildState build(Writer outputHandler, String branch, String buil newTags.removeAll(tagsBefore); - extendedBuildState = new ExtendedBuildState(result, beforeCommitID.name(), headAfter.getObjectId().name(), Collections.unmodifiableList(newTags), workDir); + extendedBuildState = new ExtendedBuildState(result, beforeCommitID.name(), headAfter.getObjectId().name(), Collections.unmodifiableList(newTags), workDir, branch); } deleteDirectoryQuietly(workDir, StandardDeleteOption.OVERRIDE_READ_ONLY); @@ -169,10 +173,53 @@ public void close() { } private Git pullFromGitAndCopyWorkingCopyToNewDir(Writer writer, String branch) throws GitAPIException, IOException { - git.fetch().setRemote("origin").setProgressMonitor(new TextProgressMonitor(writer)).call(); + FetchResult fetchResult = git.fetch().setRemote("origin").setProgressMonitor(new TextProgressMonitor(writer)).call(); + if (branch == null) { + Ref ref = findBranchToBuild(fetchResult); + if (ref == null) { + throw new RuntimeException("Could not determine default branch to build"); + } else { + branch = StringUtils.removeStart(ref.getName(), Constants.R_HEADS); + } + doubleLog(writer, "Building default branch: "+branch); + } else { + doubleLog(writer, "Building branch: "+branch); + } return copyToNewInstanceDirAndSwitchBranch(branch); } + private Ref findBranchToBuild(FetchResult result) { + final Ref headRef = result.getAdvertisedRef(Constants.HEAD); + if (headRef == null) { + return null; + } + + if (headRef.isSymbolic()) { + return headRef.getTarget(); + } + + final ObjectId headObjectId = headRef.getObjectId(); + if (headObjectId == null) { + return null; + } + + final Ref masterRef = result.getAdvertisedRef(Constants.R_HEADS + Constants.MASTER); + if (masterRef != null && headObjectId.equals(masterRef.getObjectId())) { + return masterRef; + } + + for (Ref adRef : result.getAdvertisedRefs()) { + if (!adRef.getName().startsWith(Constants.R_HEADS)) { + continue; + } + if (headObjectId.equals(adRef.getObjectId())) { + return adRef; + } + } + + return null; + } + private Git copyToNewInstanceDirAndSwitchBranch(String branch) throws GitAPIException, IOException { File dest = new File(instanceDir, String.valueOf(System.currentTimeMillis())); if (!dest.mkdir()) { diff --git a/src/main/java/com/danielflower/restabuild/web/BuildResource.java b/src/main/java/com/danielflower/restabuild/web/BuildResource.java index 051d15e..b29cda0 100644 --- a/src/main/java/com/danielflower/restabuild/web/BuildResource.java +++ b/src/main/java/com/danielflower/restabuild/web/BuildResource.java @@ -12,6 +12,7 @@ import io.muserver.rest.ApiResponse; import io.muserver.rest.Description; import io.muserver.rest.ResponseHeader; +import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; import org.json.JSONObject; @@ -51,7 +52,7 @@ public BuildResource(FileSandbox fileSandbox, BuildQueue buildQueue, BuildDataba @ApiResponse(code = "400", message = "No gitUrl form parameter was specified.", contentType = "text/plain") public Response create(@FormParam("gitUrl") @Description(value = "The URL of a git repo that includes a `build.sh` or `build.bat` file. " + "It can be any type of Git URL (e.g. SSH or HTTPS) that the server has permission for.", example = "https://github.com/3redronin/mu-server-sample.git") String gitUrl, - @DefaultValue("master") @FormParam("branch") @Description(value = "The value of the git branch. This parameter is optional.") String branch, + @FormParam("branch") @Description(value = "The value of the git branch. This parameter is optional.") String branch, @FormParam("buildParam") @Description(value = "The parameter for the `build.sh` or `build.bat` file. This parameter is optional.") String buildParam, @Context UriInfo uriInfo) { BuildResult result = createInternal(gitUrl, branch, buildParam, uriInfo); @@ -69,11 +70,7 @@ private BuildResult createInternal(String gitUrl, String branch, String buildPar throw new BadRequestException("A form parameter named gitUrl must point to a valid git repo"); } - String gitBranch = branch; - if(null == branch || branch.trim().isEmpty()) { - gitBranch = "master"; - } - + String gitBranch = StringUtils.trimToNull(branch); GitRepo gitRepo = new GitRepo(gitUrl, gitBranch); String id = UUID.randomUUID().toString().replace("-", ""); Map environment = getEnrichedEnvironment(id, uriInfo); diff --git a/src/main/resources/web/index.html b/src/main/resources/web/index.html index 7076bcf..f26b7de 100644 --- a/src/main/resources/web/index.html +++ b/src/main/resources/web/index.html @@ -44,7 +44,7 @@

Submit a build