Skip to content

Instantly share code, notes, and snippets.

@tivrfoa
Forked from mkouba/MyPullRequests.java
Created October 10, 2020 22:50
Show Gist options
  • Save tivrfoa/f923669cf426896e82cfd9db719249c2 to your computer and use it in GitHub Desktop.
Save tivrfoa/f923669cf426896e82cfd9db719249c2 to your computer and use it in GitHub Desktop.
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS info.picocli:picocli:4.5.0
//DEPS io.smallrye.reactive:smallrye-mutiny-vertx-web-client:1.2.1
//DEPS io.quarkus.qute:qute-core:1.8.2.Final
package com.gihub.mkouba;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import io.quarkus.qute.Engine;
import io.quarkus.qute.Template;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.mutiny.ext.web.client.WebClient;
@Command(name = "My pull requests", mixinStandardHelpOptions = true, version = "1.0", description = "My pull requests made with jbang")
class MyPullRequests implements Callable<Integer> {
static final int PAGE_SIZE = 100;
static final String GITHUB_API_URL = "api.github.com";
static final String USER_PULLS_QUERY = "query userPulls { \n"
+ " user(login: \"{username}\") { \n"
+ " pullRequests(first: {first}{#if cursor}, after:\"{cursor}\"{/}) {\n"
+ " nodes {\n"
+ " repository {\n"
+ " nameWithOwner\n"
+ " }\n"
+ " }\n"
+ " pageInfo {\n"
+ " endCursor\n"
+ " hasNextPage\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}";
static final String RESULTS = "\nUser {username} contributed {totalPullRequests} pull requests to {results.size} repositories:\n\n"
+ "#\tPRs\tRepo\n"
+ "---\t---\t---\n"
+ "{#each results}"
+ "{count}.\t{it.value}\t{it.key}{#if hasNext}\n{/}"
+ "{/each}";
@Parameters(index = "0", description = "GitHub username")
private String username;
@Parameters(index = "1", description = "GitHub personal access token")
private String token;
public static void main(String... args) {
int exitCode = new CommandLine(new MyPullRequests()).execute(args);
System.exit(exitCode);
}
@Override
public Integer call() throws Exception {
Engine engine = Engine.builder().addDefaults().build();
Template queryTemplate = engine.parse(USER_PULLS_QUERY);
Template queryLogtemplate = engine.parse("{count}. query executed in {time} ms [{results} results]");
Vertx vertx = Vertx.vertx();
WebClient client = new WebClient(io.vertx.ext.web.client.WebClient.create(vertx, new WebClientOptions()
.setDefaultPort(443)
.setDefaultHost(GITHUB_API_URL)));
try {
// repository.nameWithOwner -> number of pull requests
Map<String, Long> resultsMap = new HashMap<>();
String cursor = null;
boolean hasNextPage = true;
int queryCount = 0;
while (hasNextPage) {
long start = System.currentTimeMillis();
String query = queryTemplate.data("username", username).data("first", PAGE_SIZE)
.data("cursor", cursor).render();
queryCount++;
JsonObject response = client.post("/graphql").ssl(true).bearerTokenAuthentication(token)
.sendJsonObject(new JsonObject().put("query", query)).await()
.atMost(Duration.ofSeconds(10)).bodyAsJsonObject();
long end = System.currentTimeMillis();
JsonObject data = response.getJsonObject("data");
if (data == null) {
System.err.println("Unable to obtain the pull request data: " + response);
hasNextPage = false;
} else {
JsonObject pullRequests = data.getJsonObject("user").getJsonObject("pullRequests");
JsonArray nodes = pullRequests.getJsonArray("nodes");
System.out.println(queryLogtemplate.data("count", queryCount).data("time", end - start)
.data("results", nodes.size()).render());
for (int i = 0; i < nodes.size(); i++) {
JsonObject pullRequest = nodes.getJsonObject(i);
String repoNameWithOwner = pullRequest.getJsonObject("repository").getString("nameWithOwner");
resultsMap.compute(repoNameWithOwner, (name, count) -> {
if (count == null) {
return 1l;
}
return count + 1;
});
}
JsonObject pageInfo = pullRequests.getJsonObject("pageInfo");
hasNextPage = pageInfo.getBoolean("hasNextPage");
cursor = pageInfo.getString("endCursor");
}
}
// Log the results
List<Entry<String, Long>> results = resultsMap.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).collect(Collectors.toList());
long totalPullRequests = results.stream().mapToLong(Entry::getValue).sum();
System.out.println(engine.parse(RESULTS).data("username", username).data("totalPullRequests", totalPullRequests)
.data("results", results).render());
} finally {
vertx.close();
}
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment