Skip to content

Commit

Permalink
Added the commit ID of the build (both before and after) and any adde…
Browse files Browse the repository at this point in the history
…d tags to the rest APIs
  • Loading branch information
danielflower committed Mar 31, 2019
1 parent 8f5822f commit a9a0331
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 28 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ root = true
charset = utf-8
indent_style = space
indent_size = 4

[*.sh]
end_of_line = lf

[*.bat]
end_of_line = crlf
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.danielflower.apprunner</groupId>
<artifactId>restabuild</artifactId>
<version>0.4-SNAPSHOT</version>
<version>0.5-SNAPSHOT</version>

<name>RestaBuild</name>
<description>Builds Git-hosted projects via a REST API</description>
Expand Down Expand Up @@ -97,7 +97,7 @@
<dependency>
<groupId>io.muserver</groupId>
<artifactId>mu-server</artifactId>
<version>0.25.8</version>
<version>0.26.0</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
Expand Down Expand Up @@ -139,7 +139,7 @@
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.10.0.201712302008-r</version>
<version>5.3.0.201903130848-r</version>
</dependency>
<!-- end git stuff -->

Expand Down
2 changes: 1 addition & 1 deletion sample-apps/maven/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
set -e

mvn --version
mvn releaser:next
mvn releaser:release
16 changes: 16 additions & 0 deletions sample-apps/tagger/build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
git tag -a annnotated1 -m "Annotated tag 1"
git tag lightweight1

echo Hello > hello.txt
git add hello.txt
git commit -m "Adding hello.txt during build"

git tag lightweight2
git tag -a annnotated2 -m "Annotated tag 2"

echo Goodbye > goodbye.txt
git add goodbye.txt
git commit -m "Adding goodbye.txt during build"

git tag -a annnotated3 -m "Annotated tag 3"
git tag lightweight3
16 changes: 16 additions & 0 deletions sample-apps/tagger/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
git tag -a annnotated1 -m "Annotated tag 1"
git tag lightweight1

echo Hello > hello.txt
git add hello.txt
git commit -m "Adding hello.txt during build"

git tag lightweight2
git tag -a annnotated2 -m "Annotated tag 2"

echo Goodbye > goodbye.txt
git add goodbye.txt
git commit -m "Adding goodbye.txt during build"

git tag -a annnotated3 -m "Annotated tag 3"
git tag lightweight3
20 changes: 18 additions & 2 deletions src/main/java/com/danielflower/restabuild/build/BuildResult.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.danielflower.restabuild.build;

import com.danielflower.restabuild.FileSandbox;
import io.muserver.Mutils;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
Expand All @@ -24,6 +27,9 @@ public class BuildResult {
public final long queueStart = System.currentTimeMillis();
private long buildStart = -1;
private long buildComplete = -1;
private String commitIDBeforeBuild;
private String commitIDAfterBuild;
private List<String> createdTags;

public BuildResult(FileSandbox sandbox, GitRepo gitRepo) {
this.sandbox = sandbox;
Expand Down Expand Up @@ -57,7 +63,10 @@ public JSONObject toJson() {
.put("gitBranch", gitRepo.branch)
.put("status", state.name())
.put("queuedAt", Instant.ofEpochMilli(queueStart).toString())
.put("queueDurationMillis", queueDuration);
.put("queueDurationMillis", queueDuration)
.put("commitIDBeforeBuild", this.commitIDBeforeBuild)
.put("commitIDAfterBuild", this.commitIDAfterBuild)
.put("tagsCreated", new JSONArray(Mutils.coalesce(createdTags, Collections.<String>emptyList())));
if (buildStart > 0) {
long buildDuration = buildComplete < 0 ? (System.currentTimeMillis() - buildStart) : (buildComplete - buildStart);
build.put("buildDurationMillis", buildDuration);
Expand All @@ -67,12 +76,14 @@ public JSONObject toJson() {

public void run() throws Exception {
BuildState newState = state = BuildState.IN_PROGRESS;
ProjectManager.ExtendedBuildState extendedBuildState = null;
buildStart = System.currentTimeMillis();
try (FileWriter logFileWriter = new FileWriter(buildLogFile);
Writer writer = new MultiWriter(logFileWriter)) {
try {
ProjectManager pm = ProjectManager.create(gitRepo.url, sandbox, writer);
newState = pm.build(writer, gitRepo.branch);
extendedBuildState = pm.build(writer, gitRepo.branch);
newState = extendedBuildState.buildState;
} catch (Exception ex) {
writer.write("\n\nERROR: " + ex.getMessage());
ex.printStackTrace(new PrintWriter(writer));
Expand All @@ -84,6 +95,11 @@ public void run() throws Exception {
synchronized (lock) {
state = newState;
buildLog = null;
if (extendedBuildState != null) {
this.commitIDBeforeBuild = extendedBuildState.commitIDBeforeBuild;
this.commitIDAfterBuild = extendedBuildState.commitIDAfterBuild;
this.createdTags = extendedBuildState.tagsAdded;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@

import com.danielflower.restabuild.FileSandbox;
import com.jcraft.jsch.JSch;
import io.muserver.Mutils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.danielflower.restabuild.FileSandbox.dirPath;

Expand Down Expand Up @@ -81,18 +86,40 @@ private ProjectManager(Git git, File instanceDir, String gitUrl, File repoDir) {
this.repoDir = repoDir;
}

static class ExtendedBuildState {
public final BuildState buildState;
public final String commitIDBeforeBuild;
public final String commitIDAfterBuild;
public final List<String> tagsAdded;
ExtendedBuildState(BuildState buildState, String commitIDBeforeBuild, String commitIDAfterBuild, List<String> tagsAdded) {
this.buildState = buildState;
this.commitIDBeforeBuild = commitIDBeforeBuild;
this.commitIDAfterBuild = commitIDAfterBuild;
this.tagsAdded = tagsAdded;
}
}

public BuildState build(Writer outputHandler, String branch) throws Exception {
public ExtendedBuildState build(Writer outputHandler, String branch) throws Exception {
doubleLog(outputHandler, "Fetching latest changes from git...");
File workDir = pullFromGitAndCopyWorkingCopyToNewDir(outputHandler, branch);
doubleLog(outputHandler, "Created new instance in " + dirPath(workDir));

Git git = Git.open(workDir);


Ref headBefore = git.getRepository().exactRef("HEAD");
Ref headAfter = headBefore;
ObjectId beforeCommitID = headBefore.getObjectId();
List<String> newTags = new ArrayList<>();
List<String> tagsBefore = getTagsAt(git, beforeCommitID);

File f = new File(workDir, buildFile);
BuildState result;
if (!f.isFile()) {
outputHandler.write("Please place a file called " + buildFile + " in the root of your repo");
result = BuildState.FAILURE;
} else {

CommandLine command;
if (SystemUtils.IS_OS_WINDOWS) {
command = new CommandLine(f);
Expand All @@ -103,10 +130,26 @@ public BuildState build(Writer outputHandler, String branch) throws Exception {
}
ProcessStarter processStarter = new ProcessStarter(outputHandler);
result = processStarter.run(outputHandler, command, workDir, TimeUnit.MINUTES.toMillis(30));

headAfter = git.getRepository().exactRef("HEAD");

try (RevWalk walk = new RevWalk(git.getRepository())) {
walk.markStart(walk.parseCommit(headAfter.getObjectId()));
walk.markUninteresting(walk.parseCommit(headBefore.getObjectId()));
for (RevCommit commit : walk) {
getTagsAt(git, commit.getId()).forEach(s -> newTags.add(0, s));
}
}
getTagsAt(git, beforeCommitID).forEach(s -> newTags.add(0, s));
}

FileUtils.deleteQuietly(workDir);

return result;
for (String existingTag : tagsBefore) {
newTags.remove(existingTag);
}

return new ExtendedBuildState(result, beforeCommitID.name(), headAfter.getObjectId().name(), Collections.unmodifiableList(newTags));
}


Expand All @@ -129,7 +172,6 @@ private File copyToNewInstanceDirAndSwitchBranch(String branch) throws GitAPIExc


String currentBranch = copy.getRepository().getBranch();
log.info("currently branch {}", currentBranch);
if(!branch.equals(currentBranch)) {
throw new RuntimeException("Failed to switch to branch " + branch + " the current branch is " + currentBranch);
}
Expand All @@ -138,6 +180,28 @@ private File copyToNewInstanceDirAndSwitchBranch(String branch) throws GitAPIExc
return dest;
}

private static List<String> getTagsAt(Git git, ObjectId commitID) throws GitAPIException {
RefDatabase refDatabase = git.getRepository().getRefDatabase();
return git.tagList().call()
.stream()
.map(tag -> {
try {
return refDatabase.peel(tag);
} catch (IOException e) {
return null;
}
})
.filter(tag -> tag != null && Mutils.coalesce(tag.getPeeledObjectId(), tag.getObjectId()).equals(commitID))
.map(tag -> {
String name = tag.getName();
int lastSlash = name.lastIndexOf('/');
if (lastSlash > -1) {
name = name.substring(lastSlash + 1);
}
return name;
})
.collect(Collectors.toList());
}

private static void doubleLog(Writer writer, String message) {
log.info(message);
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/com/danielflower/restabuild/web/WebServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ private WebServer(MuServer server) {
}

public static WebServer start(int port, String context, BuildResource buildResource) throws IOException {
boolean hasContext = !Mutils.nullOrEmpty(context);
MuServer server = muServer()
.withHttpPort(port)
.addHandler((request, response) -> {
log.info(request.toString());
if (request.uri().getPath().equals("/")) {
response.redirect("/" + context + "/");
return true;
if (hasContext) {
if (request.uri().getPath().equals("/")) {
response.redirect("/" + context + "/");
return true;
}
}
return false;
})
Expand Down
6 changes: 6 additions & 0 deletions src/test/java/com/danielflower/restabuild/SystemTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public void theRestApiCanBeUsedToBuildStuff() throws Exception {
assertThat(build.getString("url"),
equalTo("http://localhost:8080/restabuild/api/v1/builds/" + build.getString("id")));
waitForBuildToFinish(build);

JSONObject afterBuild = new JSONObject(client.GET(build.getString("url")).getContentAsString());
assertThat(afterBuild.has("commitIDBeforeBuild"), is(true));
assertThat(afterBuild.getString("commitIDBeforeBuild"),
equalTo(afterBuild.getString("commitIDAfterBuild")));
assertThat(afterBuild.getJSONArray("tagsCreated").get(0), is("my-maven-app-1.0.0"));
}

private JSONObject waitForBuildToFinish(JSONObject build) throws InterruptedException, ExecutionException, TimeoutException {
Expand Down
Loading

0 comments on commit a9a0331

Please sign in to comment.