This is an automated email from the ASF dual-hosted git repository. jlahoda pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans-jackpot30.git
The following commit(s) were added to refs/heads/master by this push: new 3aaa0c0 Keeping build output and ability to show it in the web UI. 3aaa0c0 is described below commit 3aaa0c02da33e41063fd446e9c0e74e4fb9cae7e Author: Jan Lahoda <jlah...@netbeans.org> AuthorDate: Tue Jan 28 21:36:29 2020 +0100 Keeping build output and ability to show it in the web UI. --- .../org/netbeans/jackpot/prs/webapp/Config.java | 4 + .../org/netbeans/jackpot/prs/webapp/WebApp.java | 3 + .../jackpot/prs/webapp/WebAppMainPage.java | 4 +- .../netbeans/jackpot/prs/webapp/WebAppNotify.java | 60 +++++++- .../jackpot/prs/webapp/WebAppRepoPullRequests.java | 151 +++++++++++++++++++++ 5 files changed, 214 insertions(+), 8 deletions(-) diff --git a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/Config.java b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/Config.java index cc93a08..ea20368 100644 --- a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/Config.java +++ b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/Config.java @@ -20,6 +20,7 @@ package org.netbeans.jackpot.prs.webapp; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.prefs.Preferences; /** @@ -43,4 +44,7 @@ public class Config { return Preferences.userRoot(); } + public Path getRunDir() { + return Paths.get(getPreferences().node("app").get("run_dir", "")); + } } diff --git a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebApp.java b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebApp.java index e81d724..a8a00b2 100644 --- a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebApp.java +++ b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebApp.java @@ -27,6 +27,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.logging.Logger; import org.glassfish.jersey.server.ServerProperties; import org.glassfish.jersey.servlet.ServletContainer; @@ -81,4 +82,6 @@ public class WebApp { System.out.println("Running on port: " + gws.getSelectorThread().getPortLowLevel()); } } + + public static final Logger LOG = Logger.getLogger(WebApp.class.getName()); } diff --git a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppMainPage.java b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppMainPage.java index 7af0d7c..a8aa61e 100644 --- a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppMainPage.java +++ b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppMainPage.java @@ -24,8 +24,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Map.Entry; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.prefs.Preferences; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; @@ -82,7 +80,7 @@ public class WebAppMainPage { } else { checked = ""; } - page.append("<li><input type='checkbox' onclick='enableDisable(\"" + userLogin + "/" + e.getValue().getName() + "\")'" + checked + "/>"+ e.getValue().getName() + "</li>"); + page.append("<li><input type='checkbox' onclick='enableDisable(\"" + userLogin + "/" + e.getValue().getName() + "\")'" + checked + "/><a href=\"/github/repopullrequests?repositoryName=" + userLogin + "/" + e.getValue().getName() + "\">" + e.getValue().getName() + "</a></li>"); } page.append("</ul>"); Set<String> admins = Set.of(Config.getDefault().getPreferences().node("app").get("admins", "").split(",")); diff --git a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppNotify.java b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppNotify.java index 2b84e6a..167d154 100644 --- a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppNotify.java +++ b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppNotify.java @@ -21,11 +21,13 @@ package org.netbeans.jackpot.prs.webapp; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; import java.util.Map; -import java.util.Set; +import java.util.logging.Level; import java.util.prefs.Preferences; +import java.util.zip.GZIPOutputStream; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -71,7 +73,55 @@ public class WebAppNotify { //XXX: how to handle the access tokens? builder.environment().put("OAUTH_TOKEN", Config.getDefault().getPreferences().node("users").node(userAndRepo[0]).get("access_token", "")); builder.environment().put("OAUTH_APP_TOKEN", Config.getDefault().getPreferences().node("app").get("access_token", "")); - //TODO: logs! - builder.inheritIO().start(); + java.nio.file.Path targetDir = Config.getDefault().getRunDir().resolve("github").resolve((String) repository.get("full_name")); + java.nio.file.Path thisRunDir = targetDir.resolve(String.valueOf((Integer) pullRequest.get("number"))); + Files.createDirectories(thisRunDir); + Files.deleteIfExists(thisRunDir.resolve("finished")); + Files.newOutputStream(thisRunDir.resolve("preparing")).close(); + java.nio.file.Path stdout = thisRunDir.resolve("stdout"); + builder.redirectOutput(stdout.toFile()); + java.nio.file.Path stderr = thisRunDir.resolve("stderr"); + builder.redirectError(stderr.toFile()); + Process process = builder.start(); + Files.newOutputStream(thisRunDir.resolve("running")).close(); + Files.delete(thisRunDir.resolve("preparing")); + new Thread(() -> { + while (true) { + try { + process.waitFor(); + break; + } catch (InterruptedException ex) { + //ignore... + } + } + try { + Files.newOutputStream(thisRunDir.resolve("finished")).close(); + } catch (IOException ex) { + WebApp.LOG.log(Level.SEVERE, null, ex); + } + try { + Files.delete(thisRunDir.resolve("running")); + } catch (IOException ex) { + WebApp.LOG.log(Level.SEVERE, null, ex); + } + pack(stdout); + pack(stderr); + }).start(); + } + + private static void pack(java.nio.file.Path log) { + java.nio.file.Path logGZ = log.getParent().resolve(log.getFileName() + ".gz"); + try (InputStream in = Files.newInputStream(log); + OutputStream out = new GZIPOutputStream(Files.newOutputStream(logGZ))) { + int r; + + while ((r = in.read()) != (-1)) { + out.write(r); + } + + Files.delete(log); + } catch (IOException ex) { + WebApp.LOG.log(Level.SEVERE, null, ex); + } } } diff --git a/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppRepoPullRequests.java b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppRepoPullRequests.java new file mode 100644 index 0000000..7c3f05e --- /dev/null +++ b/prs/webapp/src/main/java/org/netbeans/jackpot/prs/webapp/WebAppRepoPullRequests.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.netbeans.jackpot.prs.webapp; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.util.logging.Level; +import java.util.zip.GZIPInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +/** + * + * @author lahvac + */ +@Path("/github/repopullrequests") +public class WebAppRepoPullRequests { + @GET + @Produces(MediaType.TEXT_HTML) + public static String repoPullRequests(@Context HttpServletRequest request, @QueryParam("repositoryName") String repositoryName) throws IOException { + String userName = (String) request.getSession().getAttribute("user_name"); + if (userName != null) { + if (repositoryName.startsWith(userName + "/")) { + return "<html>" + + "<body>" + + " Repository: " + repositoryName + " not owned by: " + userName + + "</body>"; + } + StringBuilder page = new StringBuilder(); + page.append("<html>"); + page.append("<body>"); + page.append("Pull Requests of: " + repositoryName); + page.append("<ul>"); + java.nio.file.Path targetDir = Config.getDefault().getRunDir().resolve("github").resolve(repositoryName); + try (DirectoryStream<java.nio.file.Path> ds = Files.newDirectoryStream(targetDir)) { + for (java.nio.file.Path p : ds) { + String pr = p.getFileName().toString(); + page.append("<li>"); + page.append(pr); + page.append(" "); + if (Files.exists(p.resolve("preparing"))) { + page.append("preparing"); + } + if (Files.exists(p.resolve("running"))) { + page.append("running"); + } + if (Files.exists(p.resolve("finished"))) { + page.append("finished"); + } + if (Files.exists(p.resolve("stdout")) || Files.exists(p.resolve("stdout.gz"))) { + page.append("<a href=\"/github/repopullrequests/stdout?repositoryName=" + repositoryName + "&pr=" + pr + "\">stdout</a>"); + } + if (Files.exists(p.resolve("stderr")) || Files.exists(p.resolve("stderr.gz"))) { + page.append("<a href=\"/github/repopullrequests/stderr?repositoryName=" + repositoryName + "&pr=" + pr + "\">stderr</a>"); + } + page.append("</li>"); + } + } catch (IOException ex) { + WebApp.LOG.log(Level.FINE, null, ex); + } + page.append("</ul>"); + page.append("</body>"); + return page.toString(); + } else { + String clientId = Config.getDefault().getPreferences().node("app").get("client_id", null); + return "<html>" + + "<body>" + + " <a href=\"https://github.com/login/oauth/authorize?client_id=" + clientId + "&scope=write:repo_hook%20repo:status&state=9843759384\">Login with GitHub.</a>" + + "</body>"; + } + } + + @GET + @Path("/stdout") + public static Response stdout(@Context HttpServletRequest request, @QueryParam("repositoryName") String repositoryName, @QueryParam("pr") String pr) throws IOException { + return log(request, repositoryName, pr, "stdout"); + } + + @GET + @Path("/stderr") + public static Response stderr(@Context HttpServletRequest request, @QueryParam("repositoryName") String repositoryName, @QueryParam("pr") String pr) throws IOException { + return log(request, repositoryName, pr, "stderr"); + } + + private static Response log(HttpServletRequest request, String repositoryName, String pr, String log) throws IOException { + String userName = (String) request.getSession().getAttribute("user_name"); + if (userName != null) { + if (repositoryName.startsWith(userName + "/")) { + return Response.ok("<html>" + + "<body>" + + " Repository: " + repositoryName + " not owned by: " + userName + + "</body>", + MediaType.TEXT_HTML) + .build(); + } + class StreamingOutputImpl implements StreamingOutput { + @Override + public void write(OutputStream out) throws IOException, WebApplicationException { + java.nio.file.Path logFile = Config.getDefault().getRunDir().resolve("github").resolve(repositoryName).resolve(pr).resolve(log); + try (InputStream in = Files.newInputStream(logFile)) { + in.transferTo(out); + } catch (IOException ex) { + java.nio.file.Path logFileGZ = Config.getDefault().getRunDir().resolve("github").resolve(repositoryName).resolve(pr).resolve(log + ".gz"); + try (InputStream in = new GZIPInputStream(Files.newInputStream(logFileGZ))) { + in.transferTo(out); + } + } + } + } + return Response.ok(new StreamingOutputImpl(), MediaType.TEXT_PLAIN) + .build(); + } else { + String clientId = Config.getDefault().getPreferences().node("app").get("client_id", null); + return Response.ok("<html>" + + "<body>" + + " <a href=\"https://github.com/login/oauth/authorize?client_id=" + clientId + "&scope=write:repo_hook%20repo:status&state=9843759384\">Login with GitHub.</a>" + + "</body>", + MediaType.TEXT_HTML) + .build(); + + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists