Skip to content

Commit

Permalink
Allow Modules to see isues that have been resolved or reopened as las…
Browse files Browse the repository at this point in the history
…t action. (#149)

* Modules can see all issues now

* There is always gonna be a ktlint commit

* Adjust awaiting response

* Add possibility to register module without lastRun

* cleanup after merge

* fix build after merge
  • Loading branch information
NeunEinser authored Apr 23, 2020
1 parent 9139426 commit 113d251
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 108 deletions.
23 changes: 2 additions & 21 deletions src/main/kotlin/io/github/mojira/arisa/ModuleExecutor.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package io.github.mojira.arisa

import arrow.core.Either
import arrow.syntax.function.partially2
import com.uchuhimo.konf.Config
import io.github.mojira.arisa.infrastructure.Cache
import io.github.mojira.arisa.infrastructure.config.Arisa
import io.github.mojira.arisa.modules.FailedModuleResponse
import io.github.mojira.arisa.modules.ModuleError
import io.github.mojira.arisa.modules.ModuleResponse
import io.github.mojira.arisa.modules.OperationNotNeededModuleResponse
import net.rcarz.jiraclient.ChangeLogEntry
import net.rcarz.jiraclient.Issue
import net.rcarz.jiraclient.JiraClient

Expand Down Expand Up @@ -36,7 +36,7 @@ class ModuleExecutor(
lastRun,
startAt,
{ missingResultsPage = true },
exec
exec.partially2(lastRun)
)
}

Expand Down Expand Up @@ -110,24 +110,5 @@ class ModuleExecutor(

return searchResult
.issues
.filter(::lastActionWasNotAResolve)
}

private fun lastActionWasNotAResolve(issue: Issue): Boolean {
val latestChange = issue.changeLog.entries.lastOrNull()

return latestChange == null ||
latestChange.isNotATransition() ||
latestChange.wasDoneByTheBot() ||
latestChange.commentAfterIt(issue)
}

private fun ChangeLogEntry.commentAfterIt(issue: Issue) =
(issue.comments.isNotEmpty() && issue.comments.last().updatedDate > created)

private fun ChangeLogEntry.wasDoneByTheBot() =
author.name == config[Arisa.Credentials.username]

private fun ChangeLogEntry.isNotATransition() =
!items.any { it.field == "resolution" }
}
31 changes: 26 additions & 5 deletions src/main/kotlin/io/github/mojira/arisa/ModuleRegistry.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import java.text.SimpleDateFormat
class ModuleRegistry(jiraClient: JiraClient, private val config: Config) {
data class Entry(
val config: ModuleConfigSpec,
val execute: (Issue) -> Pair<String, Either<ModuleError, ModuleResponse>>
val execute: (Issue, Long) -> Pair<String, Either<ModuleError, ModuleResponse>>
)

private val modules = mutableListOf<Entry>()
Expand All @@ -69,8 +69,15 @@ class ModuleRegistry(jiraClient: JiraClient, private val config: Config) {
config: ModuleConfigSpec,
module: Module<T>,
requestCreator: (Issue) -> T
) = { issue: Issue ->
name to ({ issue pipe requestCreator pipe module::invoke } pipe ::tryExecuteModule)
) = register(name, config, module) { issue, _ -> requestCreator(issue) }

private fun <T> register(
name: String,
config: ModuleConfigSpec,
module: Module<T>,
requestCreator: (Issue, Long) -> T
) = { issue: Issue, lastRun: Long ->
name to ({ lastRun pipe (issue pipe2 requestCreator) pipe module::invoke } pipe ::tryExecuteModule)
} pipe (config pipe2 ModuleRegistry::Entry) pipe modules::add

private fun tryExecuteModule(executeModule: () -> Either<ModuleError, ModuleResponse>) = try {
Expand Down Expand Up @@ -159,8 +166,10 @@ class ModuleRegistry(jiraClient: JiraClient, private val config: Config) {
"Empty",
Modules.Empty,
EmptyModule()
) { issue ->
) { issue, lastRun ->
EmptyModule.Request(
issue.createdDate.toInstant().toEpochMilli(),
lastRun,
issue.attachments.size,
issue.description,
issue.getFieldAsString("environment"),
Expand Down Expand Up @@ -248,8 +257,10 @@ class ModuleRegistry(jiraClient: JiraClient, private val config: Config) {
"Language",
Modules.Language,
LanguageModule(lengthThreshold = config[Modules.Language.lengthThreshold])
) { issue ->
) { issue, lastRun ->
LanguageModule.Request(
issue.createdDate.toInstant().toEpochMilli(),
lastRun,
issue.summary,
issue.description,
issue.security?.id,
Expand Down Expand Up @@ -331,6 +342,16 @@ class ModuleRegistry(jiraClient: JiraClient, private val config: Config) {
getGroups(c.author.name)
)
},
issue.changeLog.entries
.flatMap { e ->
e.items
.map { i ->
ReopenAwaitingModule.ChangeLogItem(
e.created.toInstant().toEpochMilli(),
i.toString
)
}
},
::reopenIssue.partially1(issue)
)
}
Expand Down
36 changes: 25 additions & 11 deletions src/main/kotlin/io/github/mojira/arisa/modules/EmptyModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,25 @@ import arrow.core.extensions.fx
import arrow.core.left
import arrow.core.right

const val DESCDEFAULT = "Put the summary of the bug you're having here\r\n\r\n*What I expected to happen was...:*\r\nDescribe what you thought should happen here\r\n\r\n*What actually happened was...:*\r\nDescribe what happened here\r\n\r\n*Steps to Reproduce:*\r\n1. Put a step by step guide on how to trigger the bug here\r\n2. ...\r\n3. ..."
const val ENVDEFAULT = "Put your operating system (Windows 7, Windows XP, OSX) and Java version if you know it here"
const val MINLENGTH = 5
const val DESC_DEFAULT = """Put the summary of the bug you're having here
*What I expected to happen was...:*
Describe what you thought should happen here
*What actually happened was...:*
Describe what happened here
*Steps to Reproduce:*
1. Put a step by step guide on how to trigger the bug here
2. ...
3. ..."""
const val ENV_DEFAULT = "Put your operating system (Windows 7, Windows XP, OSX) and Java version if you know it here"
const val MIN_LENGTH = 5

class EmptyModule : Module<EmptyModule.Request> {
data class Request(
val created: Long,
val lastRun: Long,
val numAttachments: Int,
val description: String?,
val environment: String?,
Expand All @@ -20,31 +33,32 @@ class EmptyModule : Module<EmptyModule.Request> {

override fun invoke(request: Request): Either<ModuleError, ModuleResponse> = Either.fx {
with(request) {
if (description != DESCDEFAULT && environment != ENVDEFAULT) {
assertNotBigger(description, MINLENGTH).bind()
assertNotBigger(environment, MINLENGTH).bind()
assertGreaterThan(created, lastRun).bind()
if (description != DESC_DEFAULT && environment != ENV_DEFAULT) {
assertNotBigger(description, MIN_LENGTH).bind()
assertNotBigger(environment, MIN_LENGTH).bind()
} else {
assertNotEqual(description, DESCDEFAULT).bind()
assertNotEqual(environment, ENVDEFAULT).bind()
assertNotEqual(description, DESC_DEFAULT).bind()
assertNotEqual(environment, ENV_DEFAULT).bind()
}
assertNoAttachments(numAttachments).bind()
addEmptyComment().toFailedModuleEither().bind()
resolveAsIncomplete().toFailedModuleEither().bind()
}
}

fun assertNoAttachments(i: Int) = when {
private fun assertNoAttachments(i: Int) = when {
i != 0 -> OperationNotNeededModuleResponse.left()
else -> Unit.right()
}

fun assertNotBigger(s: String?, size: Int) = when {
private fun assertNotBigger(s: String?, size: Int) = when {
s.isNullOrBlank() -> Unit.right()
s.length > size -> OperationNotNeededModuleResponse.left()
else -> Unit.right()
}

fun assertNotEqual(s: String?, default: String) = when {
private fun assertNotEqual(s: String?, default: String) = when {
s.isNullOrBlank() -> Unit.right()
s != default -> OperationNotNeededModuleResponse.left()
else -> Unit.right()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class LanguageModule(
) : Module<LanguageModule.Request> {

data class Request(
val created: Long,
val lastRun: Long,
val summary: String?,
val description: String?,
val securityLevel: String?,
Expand All @@ -22,6 +24,7 @@ class LanguageModule(

override fun invoke(request: Request): Either<ModuleError, ModuleResponse> = with(request) {
Either.fx {
assertGreaterThan(created, lastRun).bind()
assertIsPublic(securityLevel, privateLevel).bind()

val combinedText = "${(summary ?: "").trim()} ${(description ?: "").trim()}"
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/io/github/mojira/arisa/modules/Module.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ fun <T> assertNotEquals(o1: T, o2: T) = if (o1 == o2) {
} else {
Unit.right()
}

fun <T : Comparable<T>> assertGreaterThan(o1: T, o2: T) = if (o1 > o2) {
Unit.right()
} else {
OperationNotNeededModuleResponse.left()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ class ReopenAwaitingModule(
val authorGroups: List<String>?
)

data class ChangeLogItem(
val created: Long,
val changedTo: String?
)

data class Request(
val resolution: String?,
val created: Instant,
val updated: Instant,
val comments: List<Comment>,
val changeLog: List<ChangeLogItem>,
val reopen: () -> Either<Throwable, Unit>
)

Expand All @@ -31,7 +37,12 @@ class ReopenAwaitingModule(
assertEquals(resolution, "Awaiting Response").bind()
assertNotEmpty(comments).bind()
assertCreationIsNotRecent(updated.toEpochMilli(), created.toEpochMilli()).bind()
val resolveTime = changeLog
.filter(::isAwaitingResolve)
.last()
.created
val lastComment = comments.last()
assertGreaterThan(lastComment.created, resolveTime).bind()
assertUpdateWasNotCausedByEditingComment(
updated.toEpochMilli(), lastComment.updated, lastComment.created
).bind()
Expand All @@ -42,6 +53,9 @@ class ReopenAwaitingModule(
}
}

private fun isAwaitingResolve(change: ChangeLogItem) =
change.changedTo == "Awaiting Response"

private fun assertCreationIsNotRecent(updated: Long, created: Long) = when {
(updated - created) < 2000 -> OperationNotNeededModuleResponse.left()
else -> Unit.right()
Expand Down
Loading

0 comments on commit 113d251

Please sign in to comment.