Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize ArC subclasses when getting the overriding options #353

Merged
merged 1 commit into from Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -28,6 +28,8 @@

import io.quarkiverse.githubapp.command.airline.runtime.util.Commandline;
import io.quarkiverse.githubapp.command.airline.runtime.util.Reactions;
import io.quarkus.arc.ClientProxy;
import io.quarkus.arc.Subclass;

public abstract class AbstractCommandDispatcher<C> {

Expand Down Expand Up @@ -80,7 +82,7 @@ protected Optional<CommandExecutionContext<C>> getCommand(GHEventPayload.IssueCo
ParseResult<C> parseResult = cli.parseWithResult(commandLine);

if (parseResult.wasSuccessful()) {
String commandClassName = parseResult.getCommand().getClass().getName();
String commandClassName = normalizeCommandClass(parseResult.getCommand().getClass()).getName();

CommandConfig commandConfig = commandConfigs.getOrDefault(commandClassName,
cliConfig.getDefaultCommandConfig());
Expand Down Expand Up @@ -111,6 +113,17 @@ protected Optional<CommandExecutionContext<C>> getCommand(GHEventPayload.IssueCo
return Optional.empty();
}

private static Class<?> normalizeCommandClass(Class<?> commandClass) {
if (Subclass.class.isAssignableFrom(commandClass)) {
return commandClass.getSuperclass();
}
if (ClientProxy.class.isAssignableFrom(commandClass)) {
return commandClass.getSuperclass();
}

return commandClass;
}

private boolean matches(String cli) {
for (String alias : cliConfig.getAliases()) {
if (alias.equals(cli)) {
Expand Down
@@ -0,0 +1,111 @@
package io.quarkiverse.githubapp.it.command.airline;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.annotation.Priority;
import javax.enterprise.context.ApplicationScoped;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InterceptorBinding;
import javax.interceptor.InvocationContext;

import org.kohsuke.github.GHEventPayload;
import org.kohsuke.github.GHEventPayload.IssueComment;

import com.github.rvesse.airline.annotations.Cli;
import com.github.rvesse.airline.annotations.Command;

import io.quarkiverse.githubapp.command.airline.CliOptions;
import io.quarkiverse.githubapp.command.airline.CommandOptions;
import io.quarkiverse.githubapp.command.airline.CommandOptions.CommandScope;
import io.quarkiverse.githubapp.it.command.airline.ArcSubclassesCli.TestApplicationScopedCommand1;
import io.quarkiverse.githubapp.it.command.airline.ArcSubclassesCli.TestApplicationScopedCommand2;
import io.quarkiverse.githubapp.it.command.airline.ArcSubclassesCli.TestSubclassCommand1;
import io.quarkiverse.githubapp.it.command.airline.ArcSubclassesCli.TestSubclassCommand2;
import io.quarkiverse.githubapp.it.command.airline.DefaultCommandOptionsCli.TestCommand;

@Cli(name = "@arc", commands = { TestApplicationScopedCommand1.class, TestApplicationScopedCommand2.class,
TestSubclassCommand1.class, TestSubclassCommand2.class })
@CliOptions(defaultCommandOptions = @CommandOptions(scope = CommandScope.ISSUES))
public class ArcSubclassesCli {

@Command(name = "application-scoped-command1")
@ApplicationScoped
static class TestApplicationScopedCommand1 implements TestCommand {

@Override
public void run(IssueComment issueCommentPayload) throws IOException {
issueCommentPayload.getIssue().comment("hello from @arc application-scoped-command1");
}
}

@Command(name = "application-scoped-command2")
@CommandOptions(scope = CommandScope.ISSUES_AND_PULL_REQUESTS)
@ApplicationScoped
static class TestApplicationScopedCommand2 implements TestCommand {

@Override
public void run(IssueComment issueCommentPayload) throws IOException {
issueCommentPayload.getIssue().comment("hello from @arc application-scoped-command2");
}
}

// we add an interceptor to generate a `_Subclass`
@Command(name = "subclass-command1")
@DoNothing
static class TestSubclassCommand1 implements TestCommand {

@Override
public void run(IssueComment issueCommentPayload) throws IOException {
issueCommentPayload.getIssue().comment("hello from @arc subclass-command1");
}
}

// we add an interceptor to generate a `_Subclass`
@Command(name = "subclass-command2")
@CommandOptions(scope = CommandScope.ISSUES_AND_PULL_REQUESTS)
@DoNothing
static class TestSubclassCommand2 implements TestCommand {

@Override
public void run(IssueComment issueCommentPayload) throws IOException {
issueCommentPayload.getIssue().comment("hello from @arc subclass-command2");
}
}

public interface DefaultCommand {

void run(GHEventPayload.IssueComment issueCommentPayload) throws IOException;
}

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
@InterceptorBinding
public @interface DoNothing {
}

@DoNothing
@Priority(2020)
@Interceptor
public static class LoggingInterceptor {

@AroundInvoke
Object logInvocation(InvocationContext context) {
// do nothing specific, we just want an interceptor

try {
return context.proceed();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
@@ -0,0 +1,88 @@
package io.quarkiverse.githubapp.it.command.airline;

import static io.quarkiverse.githubapp.it.command.airline.util.CommandTestUtils.verifyCommandExecution;
import static io.quarkiverse.githubapp.testing.GitHubAppTesting.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import java.io.IOException;

import org.junit.jupiter.api.Test;
import org.kohsuke.github.GHEvent;
import org.kohsuke.github.ReactionContent;

import io.quarkiverse.githubapp.testing.GitHubAppTest;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@GitHubAppTest
public class ArcSubclassesCliTest {

@Test
void testApplicationScopedScopeIssues() throws IOException {
when().payloadFromClasspath("/issue-comment-arc-application-scoped-command1-issue.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verify(mocks.issueComment(1093016219))
.createReaction(ReactionContent.ROCKET);
verify(mocks.issue(1168785554))
.comment("hello from @arc application-scoped-command1");
verify(mocks.issueComment(1093016219))
.createReaction(ReactionContent.PLUS_ONE);
verifyNoMoreInteractions(mocks.ghObjects());
});
when().payloadFromClasspath("/issue-comment-arc-application-scoped-command1-pr.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyNoMoreInteractions(mocks.ghObjects());
});
}

@Test
void testApplicationScopedScopeIssuesAndPullRequests() throws IOException {
when().payloadFromClasspath("/issue-comment-arc-application-scoped-command2-issue.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyCommandExecution(mocks, "hello from @arc application-scoped-command2");
});
when().payloadFromClasspath("/issue-comment-arc-application-scoped-command2-pr.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyCommandExecution(mocks, "hello from @arc application-scoped-command2");
});
}

@Test
void testSubclassScopeIssues() throws IOException {
when().payloadFromClasspath("/issue-comment-arc-subclass-command1-issue.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verify(mocks.issueComment(1093016219))
.createReaction(ReactionContent.ROCKET);
verify(mocks.issue(1168785554))
.comment("hello from @arc subclass-command1");
verify(mocks.issueComment(1093016219))
.createReaction(ReactionContent.PLUS_ONE);
verifyNoMoreInteractions(mocks.ghObjects());
});
when().payloadFromClasspath("/issue-comment-arc-subclass-command1-pr.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyNoMoreInteractions(mocks.ghObjects());
});
}

@Test
void testSubclassScopeIssuesAndPullRequests() throws IOException {
when().payloadFromClasspath("/issue-comment-arc-subclass-command2-issue.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyCommandExecution(mocks, "hello from @arc subclass-command2");
});
when().payloadFromClasspath("/issue-comment-arc-subclass-command2-pr.json")
.event(GHEvent.ISSUE_COMMENT)
.then().github(mocks -> {
verifyCommandExecution(mocks, "hello from @arc subclass-command2");
});
}
}