Skip to content
Permalink
Browse files
166: Add /solves command
Reviewed-by: ehelin
  • Loading branch information
rwestberg committed Nov 22, 2019
1 parent 2f8cfc9 commit a77b854b234fba3b1f1e8dd824b0e9e1dee393db
@@ -282,7 +282,7 @@ private String getStatusMessage(List<Review> reviews, PullRequestCheckIssueVisit
progressBody.append("\n");
} else {
progressBody.append("⚠️ Failed to retrieve information on issue `");
progressBody.append(issue.get().toString());
progressBody.append(issue.get().id());
progressBody.append("`.\n");
}
}
@@ -48,7 +48,8 @@ public class CommandWorkItem extends PullRequestWorkItem {
"integrate", new IntegrateCommand(),
"sponsor", new SponsorCommand(),
"contributor", new ContributorCommand(),
"summary", new SummaryCommand()
"summary", new SummaryCommand(),
"solves", new SolvesCommand()
);

static class HelpCommand implements CommandHandler {
@@ -82,11 +82,15 @@ private String commitMessage(List<Review> activeReviews, Namespace namespace, bo
.map(email -> Author.fromString(email.toString()))
.collect(Collectors.toList());

var additionalIssues = SolvesTracker.currentSolved(pr.repository().forge().currentUser(), comments);
var summary = Summary.summary(pr.repository().forge().currentUser(), comments);
var issue = Issue.fromString(pr.title());
var commitMessageBuilder = issue.map(CommitMessage::title).orElseGet(() -> CommitMessage.title(isMerge ? "Merge" : pr.title()));
if (issue.isPresent()) {
commitMessageBuilder.issues(additionalIssues);
}
commitMessageBuilder.contributors(additionalContributors)
.reviewers(reviewers);
.reviewers(reviewers);
summary.ifPresent(commitMessageBuilder::summary);

return String.join("\n", commitMessageBuilder.format(CommitMessageFormatters.v1));
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.skara.bots.pr;

import org.openjdk.skara.forge.PullRequest;
import org.openjdk.skara.issuetracker.Comment;
import org.openjdk.skara.vcs.openjdk.Issue;

import java.io.PrintWriter;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;

public class SolvesCommand implements CommandHandler {
private void showHelp(PrintWriter reply) {
reply.println("To add an additional issue to the list of issues that this PR solves: `/solves <id>: <description>`." +
"To remove a previously added additional issue: `/solves <id>`.");
}

@Override
public void handle(PullRequest pr, CensusInstance censusInstance, Path scratchPath, String args, Comment comment, List<Comment> allComments, PrintWriter reply) {
if (!comment.author().equals(pr.author())) {
reply.println("Only the author (@" + pr.author().userName() + ") is allowed to issue the `solves` command.");
return;
}

if (args.isBlank()) {
showHelp(reply);
return;
}

var currentSolved = SolvesTracker.currentSolved(pr.repository().forge().currentUser(), allComments)
.stream()
.map(Issue::id)
.collect(Collectors.toSet());

var issue = Issue.fromString(args);
if (issue.isEmpty()) {
issue = Issue.fromString(args + ": deleteme");
if (issue.isEmpty()) {
reply.println("Invalid command syntax.");
showHelp(reply);
return;
}

if (currentSolved.contains(issue.get().id())) {
reply.println(SolvesTracker.removeSolvesMarker(issue.get()));;
reply.println("Removing additional issue from solves list: `" + issue.get().id() + "`.");
} else {
reply.println("Could not find issue `" + issue.get().id() + "` in the list of additional solved issues.");
}
return;
}

var titleIssue = Issue.fromString(pr.title());
if (titleIssue.isEmpty()) {
reply.print("The primary solved issue for a PR is set through the PR title. Since the current title does ");
reply.println("not contain an issue reference, it will now be updated.");
pr.setTitle(issue.get().toString());
return;
}
if (titleIssue.get().id().equals(issue.get().id())) {
reply.println("This issue is referenced in the PR title - it will now be updated.");
pr.setTitle(issue.get().toString());
return;
}
reply.println(SolvesTracker.setSolvesMarker(issue.get()));
if (currentSolved.contains(issue.get().id())) {
reply.println("Updating description of additional solved issue: `" + issue.get().toString() + "`.");
} else {
reply.println("Adding additional issue to solves list: `" + issue.get().toString() + "`.");
}
}

@Override
public String description() {
return "add an additional issue that this PR solves";
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.skara.bots.pr;

import org.openjdk.skara.host.HostUser;
import org.openjdk.skara.issuetracker.Comment;
import org.openjdk.skara.vcs.openjdk.Issue;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.*;
import java.util.stream.Collectors;

public class SolvesTracker {
private final static String solvesMarker = "<!-- solves: '%s' '%s' -->";
private final static Pattern markerPattern = Pattern.compile("<!-- solves: '(.*?)' '(.*?)' -->");

static String setSolvesMarker(Issue issue) {
var encodedDescription = Base64.getEncoder().encodeToString(issue.description().getBytes(StandardCharsets.UTF_8));
return String.format(solvesMarker, issue.id(), encodedDescription);
}

static String removeSolvesMarker(Issue issue) {
return String.format(solvesMarker, issue.id(), "");
}

static List<Issue> currentSolved(HostUser botUser, List<Comment> comments) {
var solvesActions = comments.stream()
.filter(comment -> comment.author().equals(botUser))
.map(comment -> markerPattern.matcher(comment.body()))
.filter(Matcher::find)
.collect(Collectors.toList());
var current = new LinkedHashMap<String, Issue>();
for (var action : solvesActions) {
var key = action.group(1);
if (action.group(2).equals("")) {
current.remove(key);
} else {
var decodedDescription = new String(Base64.getDecoder().decode(action.group(2)), StandardCharsets.UTF_8);
var issue = new Issue(key, decodedDescription);
current.put(key, issue);
}
}

return new ArrayList<>(current.values());
}
}

0 comments on commit a77b854

Please sign in to comment.