Skip to content

Commit

Permalink
Introduce Report an Issue menu in DevUI
Browse files Browse the repository at this point in the history
- This opens up the GitHub issue with some prefilled data
- Fixes quarkusio#32431
  • Loading branch information
gastaldi committed Jan 6, 2025
1 parent 35ccb2e commit d1b1c85
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.devui.deployment.menu;

import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.devui.deployment.InternalPageBuildItem;
import io.quarkus.devui.runtime.ReportIssuesJsonRPCService;
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
import io.quarkus.devui.spi.page.Page;

public class ReportIssuesProcessor {
@BuildStep(onlyIf = IsDevelopment.class)
JsonRPCProvidersBuildItem registerJsonRpcService() {
return new JsonRPCProvidersBuildItem("report-issues", ReportIssuesJsonRPCService.class);
}

@BuildStep(onlyIf = IsDevelopment.class)
InternalPageBuildItem createReportIssuePage() {
InternalPageBuildItem item = new InternalPageBuildItem("Report an Issue", 99);

item.addPage(Page.webComponentPageBuilder().internal()
.namespace("devui-report-issues")
.title("Report an issue")
.icon("font-awesome-solid:bug")
.componentLink("qwc-report-issues.js"));

return item;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { LitElement, html, css} from 'lit';
import { JsonRpc } from 'jsonrpc';
import '@vaadin/button';

/**
* This component shows the Report Issues Page
*/
export class QwcReportIssues extends LitElement {

jsonRpc = new JsonRpc("report-issues", true);

static styles = css`
.todo {
padding-left: 10px;
height: 100%;
}`;

constructor() {
super();
}

render() {
return html`
<vaadin-horizontal-layout theme="spacing" style="align-items: baseline">
<vaadin-button @click="${this._reportBug}">Report a bug in upstream Quarkus</vaadin-button>
<vaadin-button @click="${this._reportFeature}">Request a new feature/enhancement in upstream Quarkus</vaadin-button>
</vaadin-horizontal-layout>
`;
}

_reportBug(event){
event.preventDefault();
this.jsonRpc.reportBug().then(e => {
window.open(e.result.url, "_blank");
});
}

_reportFeature(event) {
event.preventDefault();
window.open("https://github.com/quarkusio/quarkus/issues/new?assignees=&labels=kind%2Fenhancement&template=feature_request.yml", "_blank");
}

}
customElements.define('qwc-report-issues', QwcReportIssues);
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package io.quarkus.devui.runtime;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

import jakarta.enterprise.context.Dependent;

import io.quarkus.logging.Log;
import io.smallrye.common.os.OS;
import io.vertx.core.json.JsonObject;

@Dependent
public class ReportIssuesJsonRPCService {

public JsonObject reportBug() {
URLBuilder urlBuilder = new URLBuilder(
"https://github.com/quarkusio/quarkus/issues/new?labels=kind%2Fbug&template=bug_report.yml");
gatherInfo(urlBuilder);
return new JsonObject(
Map.of("url", urlBuilder.toString()));
}

String run(String... command) {
Process process = null;
StringBuilder responseBuilder = new StringBuilder();
try {
ProcessBuilder processBuilder = new ProcessBuilder().command(command);

process = processBuilder.start();
try (InputStream inputStream = process.getInputStream()) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
responseBuilder.append(line);
}
safeWaitFor(process);
}
} catch (Throwable t) {
safeWaitFor(process);
throw t;
}
} catch (Exception e) {
Log.warn("Error while running command: " + Arrays.toString(command), e);
return "";
} finally {
if (process != null && process.isAlive()) {
process.destroy();
}
}
return responseBuilder.toString();
}

private static void safeWaitFor(Process process) {
boolean intr = false;
try {
for (;;)
try {
process.waitFor();
return;
} catch (InterruptedException ex) {
intr = true;
}
} finally {
if (intr) {
Thread.currentThread().interrupt();
}
}
}

void gatherInfo(URLBuilder builder) {
builder.addQueryParameter("java_version", System.getProperty("java.version"))
.addQueryParameter("quarkus_version",
Objects.toString(getClass().getPackage().getImplementationVersion(), "999-SNAPSHOT"));
if (OS.WINDOWS.isCurrent()) {
builder.addQueryParameter("uname", run("cmd.exe", "/C", "ver"));
if (isMavenProject()) {
if (Files.exists(Path.of("mvnw.cmd"))) {
builder.addQueryParameter("build_tool", run("./mvnw.cmd", "--version"));
} else {
// Use the system Maven
builder.addQueryParameter("build_tool", run("mvn", "--version"));
}
} else if (isGradleProject()) {
if (Files.exists(Path.of("gradlew.bat"))) {
builder.addQueryParameter("build_tool", run("./gradlew.bat", "--version"));
} else {
// Use the system Gradle
builder.addQueryParameter("build_tool", run("gradle", "--version"));
}
}
} else {
builder.addQueryParameter("uname", run("uname", "-a"));
if (isMavenProject()) {
if (Files.exists(Path.of("mvnw"))) {
builder.addQueryParameter("build_tool", run("./mvnw", "--version"));
} else {
// Use the system Maven
builder.addQueryParameter("build_tool", run("mvn", "--version"));
}
} else if (isGradleProject()) {
if (Files.exists(Path.of("gradlew"))) {
builder.addQueryParameter("build_tool", run("./gradlew", "--version"));
} else {
// Use the system Gradle
builder.addQueryParameter("build_tool", run("gradle", "--version"));
}
}
}
}

private static boolean isMavenProject() {
return Files.exists(Path.of("pom.xml"));
}

private static boolean isGradleProject() {
return Files.exists(Path.of("build.gradle")) || Files.exists(Path.of("build.gradle.kts"));
}

static class URLBuilder {
private final StringBuilder url;

public URLBuilder(String url) {
this.url = new StringBuilder(url);
}

public URLBuilder addQueryParameter(String key, String value) {
if (this.url.indexOf("?") == -1) {
this.url.append("?");
} else {
this.url.append("&");
}

this.url.append(encodeToUTF(key).replaceAll("[+]", "%20")).append("=")
.append(encodeToUTF(value.replaceAll(System.lineSeparator(), "%20")).replaceAll("[+]", "%20"));
return this;
}

static String encodeToUTF(String value) {
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.displayName());
} catch (UnsupportedEncodingException var2) {
throw new RuntimeException(var2);
}
}

public String toString() {
return this.url.toString();
}
}

}

0 comments on commit d1b1c85

Please sign in to comment.