From 26ddeb6b6279493a02c0656ebe007c66f865c005 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Mon, 30 Oct 2023 19:18:44 +0100 Subject: [PATCH 1/4] fix: update dependencies in build.gradle --- github-bot/build.gradle | 8 +- .../martinwitt/laughing_train/github/App.java | 214 ------------------ 2 files changed, 3 insertions(+), 219 deletions(-) delete mode 100644 github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java diff --git a/github-bot/build.gradle b/github-bot/build.gradle index 5b4825deb..871cccfa6 100644 --- a/github-bot/build.gradle +++ b/github-bot/build.gradle @@ -5,16 +5,14 @@ plugins { } dependencies { - implementation 'io.quarkiverse.jgit:quarkus-jgit:3.0.5' + implementation 'io.quarkiverse.jgit:quarkus-jgit:3.0.5' implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") implementation 'io.quarkiverse.githubapi:quarkus-github-api:1.316.0' - implementation 'io.quarkiverse.githubapp:quarkus-github-app:2.1.0' - implementation 'io.quarkiverse.githubapp:quarkus-github-app-command-airline:2.1.0' implementation 'io.quarkus:quarkus-arc' implementation "io.quarkus:quarkus-scheduler" implementation 'io.quarkus:quarkus-smallrye-health' - implementation project(path: ':spoon-analyzer') - testImplementation 'io.quarkus:quarkus-junit5' + implementation project(path: ':spoon-analyzer') + testImplementation 'io.quarkus:quarkus-junit5' implementation project(":code-transformation") implementation 'io.quarkus:quarkus-mongodb-panache:3.5.0' annotationProcessor("io.quarkus:quarkus-panache-common") diff --git a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java b/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java deleted file mode 100644 index ea9f4ebd4..000000000 --- a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java +++ /dev/null @@ -1,214 +0,0 @@ -package io.github.martinwitt.laughing_train.github; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature; -import com.google.common.flogger.FluentLogger; -import com.google.errorprone.annotations.Var; -import io.github.martinwitt.laughing_train.ChangelogPrinter; -import io.github.martinwitt.laughing_train.Config; -import io.github.martinwitt.laughing_train.Constants; -import io.github.martinwitt.laughing_train.MarkdownPrinter; -import io.github.martinwitt.laughing_train.UserWhitelist; -import io.github.martinwitt.laughing_train.services.QodanaService; -import io.quarkiverse.githubapp.event.Issue; -import jakarta.inject.Inject; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.Path; -import java.time.Instant; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.kohsuke.github.GHEventPayload; -import org.kohsuke.github.GHIssue; -import org.kohsuke.github.GHRef; -import org.kohsuke.github.GHRepository; -import spoon.reflect.declaration.CtType; -import xyz.keksdose.spoon.code_solver.history.Change; - -public class App { - - private static final ObjectMapper MAPPER = - new ObjectMapper(new YAMLFactory().disable(Feature.WRITE_DOC_START_MARKER)); - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private static final String RESET_CONFIG_BUTTON = "- [x] "; - private static final String CREATE_FIXES_BUTTON = "- [x] "; - private static final String DISABLE_ALL_RULES_BUTTON = "- [x] "; - private static final String LABEL_NAME = "laughing-train-repair"; - - @Inject BranchNameSupplier branchNameSupplier; - - @Inject ChangelogPrinter changelogPrinter; - - @Inject MarkdownPrinter markdownPrinter; - - @Inject Config config; - - @Inject UserWhitelist userWhitelist; - - @Inject QodanaService qodanaService; - - void onConfigEdit(@Issue.Edited GHEventPayload.Issue issueComment) throws IOException { - System.out.println("onEditConfig"); - if (isNotConfigIssue(issueComment) - || !userWhitelist.isWhitelisted(GitHubUtils.getLogin(issueComment)) - || GitHubUtils.isClosed(issueComment)) { - logger.atInfo().log( - "Ignoring config edit because it is not a config issue or it is from self"); - return; - } - if (containsFlag(issueComment.getIssue(), RESET_CONFIG_BUTTON)) { - issueComment.getIssue().setBody(config.regenerateConfig()); - } - refreshConfig(issueComment); - if (containsFlag(issueComment.getIssue(), DISABLE_ALL_RULES_BUTTON)) { - issueComment - .getIssue() - .setBody(refreshFlag(issueComment.getIssue().getBody(), DISABLE_ALL_RULES_BUTTON)); - disableAllRules(); - issueComment.getIssue().setBody(config.regenerateConfig()); - } - } - - private void refreshConfig(GHEventPayload.Issue issueComment) throws JsonProcessingException { - String body = issueComment.getIssue().getBody(); - @Var - String newConfig = - body.substring(body.indexOf(""), body.indexOf("")); - newConfig = newConfig.replace("```yaml", "").replace("```", ""); - newConfig = newConfig.replace("", "").replace("", ""); - config.fromConfig(MAPPER.readValue(newConfig, Config.class)); - logger.atInfo().log("Refreshed config"); - logger.atInfo().log(config.toString()); - } - - private void disableAllRules() { - config.getRules().entrySet().forEach(entry -> entry.setValue(false)); - } - - private boolean containsFlag(GHIssue issue, String flag) { - return issue.getBody().contains(flag); - } - - private String refreshFlag(String body, String flag) { - return body.replace(flag, flag.replace("[x]", "[ ]")); - } - - private boolean isNotConfigIssue(GHEventPayload.Issue issueComment) { - return !issueComment.getIssue().getTitle().equals(Constants.CONFIG_ISSUE_NAME); - } - - private void createPullRequestForAffectedType( - GHRepository repo, Path dir, Map, List> changesByType) throws IOException { - GHRef mainRef = repo.getRef("heads/" + repo.getDefaultBranch()); - logger.atInfo().log("Found changes for %s types", changesByType.entrySet().size()); - if (changesByType.entrySet().size() > config.getMaximumNumberOfPrs()) { - logger.atInfo().log("Too many changes, skipping, %s", changesByType.entrySet().size()); - return; - } - for (var entry : changesByType.entrySet()) { - String branchName = branchNameSupplier.createBranchName(); - GHRef ref = repo.createRef("refs/heads/" + branchName, mainRef.getObject().getSha()); - StringBuilder body = new StringBuilder(); - body.append(changelogPrinter.printRepairedIssues(entry.getValue())); - createCommit(repo, dir, entry.getKey(), ref); - body.append(changelogPrinter.printChangeLog(entry.getValue())); - createPullRequest(repo, entry.getKey().getQualifiedName(), branchName, body.toString()); - } - } - - private void createSinglePullRequest(GHRepository repo, Path dir, List changes) - throws IOException { - GHRef mainRef = repo.getRef("heads/" + repo.getDefaultBranch()); - logger.atInfo().log("Found changes for %s types", changes.size()); - String branchName = branchNameSupplier.createBranchName(); - GHRef ref = repo.createRef("refs/heads/" + branchName, mainRef.getObject().getSha()); - StringBuilder body = new StringBuilder(); - body.append(changelogPrinter.printRepairedIssues(changes)); - createCommit( - repo, dir, changes.stream().map(Change::getAffectedType).collect(Collectors.toList()), ref); - body.append(changelogPrinter.printChangeLogShort(changes)); - createPullRequest(repo, branchName, body.toString()); - } - - private Map, List> groupChangesByType(List changes) { - return changes.stream().collect(Collectors.groupingBy(Change::getAffectedType)); - } - - private void createPullRequest(GHRepository repo, String typeName, String branchName, String body) - throws IOException { - repo.createPullRequest( - "fix Bad Smells in " + typeName, branchName, repo.getDefaultBranch(), body) - .addLabels(LABEL_NAME); - } - - private void createPullRequest(GHRepository repo, String branchName, String body) - throws IOException { - repo.createPullRequest("fix Bad Smells", branchName, repo.getDefaultBranch(), body) - .addLabels(LABEL_NAME); - } - - private void createCommit(GHRepository repo, Path dir, CtType entry, GHRef ref) - throws IOException { - var tree = - repo.createTree() - .baseTree(ref.getObject().getSha()) - .add( - relativize(dir, getFileForType(entry)), - Files.readString(getFileForType(entry)).replace("\r\n", "\n"), - false) - .create(); - - var commit = - repo.createCommit() - .message("fix Bad Smells in " + entry.getQualifiedName()) - .author("MartinWitt", "wittlinger.martin@gmail.com", Date.from(Instant.now())) - .tree(tree.getSha()) - .parent(ref.getObject().getSha()) - .create(); - ref.updateTo(commit.getSHA1()); - logger.atInfo().log("Created commit %s", commit.getHtmlUrl()); - } - - private void createCommit(GHRepository repo, Path dir, List> types, GHRef ref) - throws IOException { - var treeBuilder = repo.createTree().baseTree(ref.getObject().getSha()); - for (CtType ctType : types) { - treeBuilder.add( - relativize(dir, getFileForType(ctType)), - Files.readString(getFileForType(ctType)).replace("\r\n", "\n"), - false); - } - var tree = treeBuilder.create(); - var commit = - repo.createCommit() - .message("fix Bad Smells in multiple files") - .author("MartinWitt", "wittlinger.martin@gmail.com", Date.from(Instant.now())) - .tree(tree.getSha()) - .parent(ref.getObject().getSha()) - .create(); - ref.updateTo(commit.getSHA1()); - logger.atInfo().log("Created commit %s", commit.getHtmlUrl()); - } - - private Path getFileForType(CtType type) { - return type.getPosition().getFile().toPath(); - } - - private String relativize(Path root, Path child) { - try { - Path relative = - root.toRealPath(LinkOption.NOFOLLOW_LINKS) - .relativize(child.toRealPath(LinkOption.NOFOLLOW_LINKS)); - return relative.toString().replace('\\', '/'); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - } -} From 97f9ad52feeeed614cf274f75f5662c3d053437d Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Mon, 30 Oct 2023 19:22:05 +0100 Subject: [PATCH 2/4] up --- .../github/MentionCommands.java | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 github-bot/src/main/java/io/github/martinwitt/laughing_train/github/MentionCommands.java diff --git a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/MentionCommands.java b/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/MentionCommands.java deleted file mode 100644 index 3569704d6..000000000 --- a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/MentionCommands.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.martinwitt.laughing_train.github; - -import com.google.common.flogger.FluentLogger; -import io.github.martinwitt.laughing_train.Config; -import io.github.martinwitt.laughing_train.Constants; -import io.github.martinwitt.laughing_train.UserWhitelist; -import io.quarkiverse.githubapp.event.IssueComment; -import jakarta.inject.Inject; -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; -import org.kohsuke.github.GHEventPayload; -import org.kohsuke.github.GHIssue; -import org.kohsuke.github.GHPullRequest; -import org.kohsuke.github.GHRepository; - -public class MentionCommands { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - @Inject UserWhitelist whitelist; - - @Inject Config config; - - void mentionCommands(@IssueComment GHEventPayload.IssueComment issueComment) throws IOException { - if (!whitelist.isWhitelisted(issueComment.getComment().getUser().getLogin())) { - return; - } - String comment = issueComment.getComment().getBody(); - logger.atInfo().log("comment: %s", comment); - if (comment.contains("@laughing-train config")) { - var issues = findConfigIssue(issueComment); - if (issues.isEmpty()) { - createConfigIssue(issueComment.getRepository()); - return; - } else { - var issue = issues.get(0); - issue.getComments().get(0).update(config.regenerateConfig()); - } - } - if (comment.contains("@laughing-train close")) { - closePullRequestsWithLabelName( - GitHubUtils.getOpenPullRequests(issueComment), Constants.LABEL_NAME); - return; - } - if (comment.contains("@laughing-train hi")) { - issueComment - .getIssue() - .comment("Hi, I'm a bot. I'm here to help you with your code quality."); - } - } - - private List findConfigIssue(GHEventPayload.IssueComment issueComment) - throws IOException { - return issueComment - .getRepository() - .queryIssues() - .creator(Constants.BOT_NAME) - .list() - .toList() - .stream() - .filter(v -> v.getTitle().contains(Constants.CONFIG_ISSUE_NAME)) - .filter(v -> !v.isLocked()) - .collect(Collectors.toList()); - } - - private void closePullRequestsWithLabelName(List pr, String name) { - for (GHPullRequest ghPullRequest : pr) { - ghPullRequest - .getLabels() - .forEach( - v -> { - if (v.getName().equals(name)) { - try { - ghPullRequest.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - } - } - - private void createConfigIssue(GHRepository repository) throws IOException { - repository.createIssue(Constants.CONFIG_ISSUE_NAME).body(config.regenerateConfig()).create(); - } -} From be41c0d7edd80b94492ff312e549556ed97b116a Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Mon, 30 Oct 2023 19:32:14 +0100 Subject: [PATCH 3/4] up --- github-bot/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/github-bot/build.gradle b/github-bot/build.gradle index 871cccfa6..11ad89b67 100644 --- a/github-bot/build.gradle +++ b/github-bot/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation project(":commons") implementation "io.quarkiverse.loggingmanager:quarkus-logging-manager:3.0.2" testImplementation 'org.mockito:mockito-core:5.6.0' + implementation 'com.fasterxml.jackson.core:jackson-dataformat-yaml:2.13.0' } From 9d4bd5c780de59278cc9ffdc7a9ead94fc55d8f7 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Mon, 30 Oct 2023 19:34:12 +0100 Subject: [PATCH 4/4] Fix Jackson YAML dependency. --- github-bot/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github-bot/build.gradle b/github-bot/build.gradle index 11ad89b67..9530d9798 100644 --- a/github-bot/build.gradle +++ b/github-bot/build.gradle @@ -27,7 +27,7 @@ dependencies { implementation project(":commons") implementation "io.quarkiverse.loggingmanager:quarkus-logging-manager:3.0.2" testImplementation 'org.mockito:mockito-core:5.6.0' - implementation 'com.fasterxml.jackson.core:jackson-dataformat-yaml:2.13.0' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.0' }