bazel: implement bazel build for the development mode.

In addition build bower_components.zip and fonts.zip: these are not
implicitly generated by the bazel build, so they have to be built
explicitly.

Tested:

1) Ran
  rm -rf bazel-bin/polygerrit-ui/polygerrit_components.bower_components.zip && \
  rm -f bazel-bin/polygerrit-ui/fonts.zip && \
  bazel build polygerrit && \
    $(bazel info output_base)/external/local_jdk/bin/java \
    -jar bazel-bin/polygerrit.war daemon --polygerrit-dev \
    -d ../gerrit_testsite --console-log --show-stack-trace

verified that test site loaded.

Change-Id: I3e220eed06bc956956095b946aafb20539ee4acd
This commit is contained in:
Han-Wen Nienhuys 2016-11-13 14:13:38 -08:00
parent 6729b637ef
commit 0d4ea73587
6 changed files with 112 additions and 72 deletions

View File

@ -17,16 +17,15 @@ package com.google.gerrit.httpd.raw;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
public class BazelBuild implements BuildSystem { public class BazelBuild extends BuildSystem {
private final Path sourceRoot;
public BazelBuild(Path sourceRoot) { public BazelBuild(Path sourceRoot) {
this.sourceRoot = sourceRoot; super(sourceRoot);
} }
@Override @Override
public void build(Label l) throws IOException, BuildFailureException { protected ProcessBuilder newBuildProcess(Label label) throws IOException {
throw new BuildFailureException("not implemented yet.".getBytes()); ProcessBuilder proc = new ProcessBuilder("bazel", "build", label.fullName());
return proc;
} }
@Override @Override
@ -54,4 +53,9 @@ public class BazelBuild implements BuildSystem {
public Label fontZipLabel() { public Label fontZipLabel() {
return new Label("polygerrit-ui", "fonts.zip"); return new Label("polygerrit-ui", "fonts.zip");
} }
@Override
public String name() {
return "bazel";
}
} }

View File

@ -19,7 +19,6 @@ import com.google.gerrit.httpd.raw.BuildSystem.Label;
import com.google.gerrit.launcher.GerritLauncher; import com.google.gerrit.launcher.GerritLauncher;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Objects; import java.util.Objects;
@ -28,7 +27,6 @@ class BowerComponentsDevServlet extends ResourceServlet {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Path bowerComponents; private final Path bowerComponents;
private final String buildCommand;
private final Path zip; private final Path zip;
BowerComponentsDevServlet(Cache<Path, Resource> cache, BowerComponentsDevServlet(Cache<Path, Resource> cache,
@ -36,25 +34,21 @@ class BowerComponentsDevServlet extends ResourceServlet {
super(cache, true); super(cache, true);
Objects.requireNonNull(builder); Objects.requireNonNull(builder);
Label pgLabel = builder.polygerritComponents(); Label label = builder.polygerritComponents();
buildCommand = builder.buildCommand(pgLabel); try {
builder.build(label);
} catch (BuildSystem.BuildFailureException e) {
throw new IOException(e);
}
zip = builder.targetPath(pgLabel); zip = builder.targetPath(label);
if (zip == null || !Files.exists(zip)) { bowerComponents = GerritLauncher
bowerComponents = null;
} else {
bowerComponents = GerritLauncher
.newZipFileSystem(zip) .newZipFileSystem(zip)
.getPath("/"); .getPath("/");
}
} }
@Override @Override
protected Path getResourcePath(String pathInfo) throws IOException { protected Path getResourcePath(String pathInfo) throws IOException {
if (bowerComponents == null) {
throw new IOException("No polymer components found: " + zip
+ ". Run `" + buildCommand + "`?");
}
return bowerComponents.resolve(pathInfo); return bowerComponents.resolve(pathInfo);
} }
} }

View File

@ -16,64 +16,28 @@ package com.google.gerrit.httpd.raw;
import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.MoreObjects.firstNonNull;
import com.google.common.io.ByteStreams;
import com.google.gerrit.common.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InterruptedIOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Properties; import java.util.Properties;
class BuckUtils implements BuildSystem { class BuckUtils extends BuildSystem {
private static final Logger log =
LoggerFactory.getLogger(BuckUtils.class);
private final Path sourceRoot;
BuckUtils(Path sourceRoot) { BuckUtils(Path sourceRoot) {
this.sourceRoot = sourceRoot; super(sourceRoot);
} }
@Override @Override
public void build(Label label) protected ProcessBuilder newBuildProcess(Label label) throws IOException {
throws IOException, BuildFailureException {
log.info("buck build " + label.fullName());
Properties properties = loadBuckProperties( Properties properties = loadBuckProperties(
sourceRoot.resolve("buck-out/gen/tools/buck/buck.properties")); sourceRoot.resolve("buck-out/gen/tools/buck/buck.properties"));
String buck = firstNonNull(properties.getProperty("buck"), "buck"); String buck = firstNonNull(properties.getProperty("buck"), "buck");
ProcessBuilder proc = new ProcessBuilder(buck, "build", label.fullName()) ProcessBuilder proc = new ProcessBuilder(buck, "build", label.fullName());
.directory(sourceRoot.toFile())
.redirectErrorStream(true);
if (properties.containsKey("PATH")) { if (properties.containsKey("PATH")) {
proc.environment().put("PATH", properties.getProperty("PATH")); proc.environment().put("PATH", properties.getProperty("PATH"));
} }
long start = TimeUtil.nowMs(); return proc;
Process rebuild = proc.start();
byte[] out;
try (InputStream in = rebuild.getInputStream()) {
out = ByteStreams.toByteArray(in);
} finally {
rebuild.getOutputStream().close();
}
int status;
try {
status = rebuild.waitFor();
} catch (InterruptedException e) {
throw new InterruptedIOException("interrupted waiting for " + buck);
}
if (status != 0) {
throw new BuildFailureException(out);
}
long time = TimeUtil.nowMs() - start;
log.info(String.format("UPDATED %s in %.3fs", label.fullName(),
time / 1000.0));
} }
private static Properties loadBuckProperties(Path propPath) private static Properties loadBuckProperties(Path propPath)
@ -119,6 +83,11 @@ class BuckUtils implements BuildSystem {
@Override @Override
public Label fontZipLabel() { public Label fontZipLabel() {
return new Label("polygerrit-ui", "fonts", "polygerrit-ui/fonts/fonts.zip"); return new Label("polygerrit-ui", "fonts", "polygerrit-ui/fonts/fonts.zip");
}
@Override
public String name() {
return "buck";
} }
} }

View File

@ -18,17 +18,65 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.escape.Escaper; import com.google.common.escape.Escaper;
import com.google.common.html.HtmlEscapers; import com.google.common.html.HtmlEscapers;
import com.google.common.io.ByteStreams;
import com.google.gerrit.common.TimeUtil;
import com.google.gwtexpui.server.CacheHeaders; import com.google.gwtexpui.server.CacheHeaders;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Path; import java.nio.file.Path;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
public interface BuildSystem { public abstract class BuildSystem {
private static final Logger log =
LoggerFactory.getLogger(BuildSystem.class);
protected final Path sourceRoot;
public BuildSystem(Path sourceRoot) {
this.sourceRoot = sourceRoot;
}
protected abstract ProcessBuilder newBuildProcess(Label l) throws IOException;
// builds the given label.
public void build(Label label)
throws IOException, BuildFailureException {
ProcessBuilder proc = newBuildProcess(label);
proc.directory(sourceRoot.toFile())
.redirectErrorStream(true);
log.info("building [" + name() + "] " + label.fullName());
long start = TimeUtil.nowMs();
Process rebuild = proc.start();
byte[] out;
try (InputStream in = rebuild.getInputStream()) {
out = ByteStreams.toByteArray(in);
} finally {
rebuild.getOutputStream().close();
}
int status;
try {
status = rebuild.waitFor();
} catch (InterruptedException e) {
throw new InterruptedIOException("interrupted waiting for " + proc.toString());
}
if (status != 0) {
log.warn("build failed: " + new String(out));
throw new BuildFailureException(out);
}
long time = TimeUtil.nowMs() - start;
log.info(String.format("UPDATED %s in %.3fs", label.fullName(),
time / 1000.0));
}
// Represents a label in either buck or bazel. // Represents a label in either buck or bazel.
class Label { class Label {
@ -95,20 +143,20 @@ public interface BuildSystem {
} }
/** returns the command to build given target */ /** returns the command to build given target */
String buildCommand(Label l); abstract String buildCommand(Label l);
/** builds the given label. */
void build(Label l) throws IOException, BuildFailureException;
/** returns the root relative path to the artifact for the given label */ /** returns the root relative path to the artifact for the given label */
Path targetPath(Label l); abstract Path targetPath(Label l);
/** Label for the agent specific GWT zip. */ /** Label for the agent specific GWT zip. */
Label gwtZipLabel(String agent); abstract Label gwtZipLabel(String agent);
/** Label for the polygerrit component zip. */ /** Label for the polygerrit component zip. */
Label polygerritComponents(); abstract Label polygerritComponents();
/** Label for the fonts zip file. */ /** Label for the fonts zip file. */
Label fontZipLabel(); abstract Label fontZipLabel();
/** Build system name. */
abstract String name();
} }

View File

@ -32,7 +32,14 @@ class FontsDevServlet extends ResourceServlet {
super(cache, true); super(cache, true);
Objects.requireNonNull(builder); Objects.requireNonNull(builder);
Path zip = builder.targetPath(builder.fontZipLabel()); BuildSystem.Label zipLabel = builder.fontZipLabel();
try {
builder.build(zipLabel);
} catch (BuildSystem.BuildFailureException e) {
throw new IOException(e);
}
Path zip = builder.targetPath(zipLabel);
Objects.requireNonNull(zip); Objects.requireNonNull(zip);
fonts = GerritLauncher.newZipFileSystem(zip).getPath("/"); fonts = GerritLauncher.newZipFileSystem(zip).getPath("/");

View File

@ -22,3 +22,21 @@ bower_component_bundle(
'//lib/js:polymer', '//lib/js:polymer',
'//lib/js:promise-polyfill', '//lib/js:promise-polyfill',
]) ])
genrule2(
name = 'fonts',
cmd = ' && '.join([
'mkdir -p $$TMP/fonts',
'cp $(SRCS) $$TMP/fonts/',
'cd $$TMP',
"find fonts/ -exec touch -t 198001010000 '{}' ';'",
'zip -qr $$ROOT/$@ fonts',
]),
srcs = [
'//lib/fonts:sourcecodepro',
],
outs = ['fonts.zip',],
visibility = ['//visibility:public'],
output_to_bindir = 1,
)