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

Fix errors and bugs in RevokePriorityModule #768

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,50 @@ package io.github.mojira.arisa.modules

import arrow.core.Either
import arrow.core.extensions.fx
import arrow.core.left
import arrow.core.right
import io.github.mojira.arisa.domain.ChangeLogItem
import io.github.mojira.arisa.domain.Issue
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.time.Instant
import java.time.temporal.ChronoUnit

class RevokePriorityModule : Module {
val log: Logger = LoggerFactory.getLogger("RevokePriorityModule")

override fun invoke(issue: Issue, lastRun: Instant): Either<ModuleError, ModuleResponse> = with(issue) {
Either.fx {
val originalPriority = changeLog
// Check if there are recent changes to priority in the changelog
val recentPriorityChanges = changeLog
.filter { item -> item.created >= lastRun }
.filter(::isPriorityChange)

// If there aren't any recent changes to priority, there's nothing to revoke
assertNotEmpty(recentPriorityChanges).bind()

// Try to recover original priority by getting entries from the changelog
val originalPriorityItem = changeLog
.filter(::isPriorityChange)
.lastOrNull(::changedByStaff)
?.changedTo.getOrDefaultNull("-1")

assertNotEquals(getId(priority), originalPriority).bind()
updatePriority(originalPriority)
val originalPriorityId = originalPriorityItem?.changedTo.getOrDefaultNull("-1")
val originalPriorityName = originalPriorityItem?.changedToString.getOrDefaultNull("None")

// Check whether the original priority differs from the current priority
assertNotEquals(getId(priority), originalPriorityId).bind()
Copy link
Contributor

@Marcono1234 Marcono1234 May 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit worried what happens when a new priority is added, and when a Mojang employee then changes the priority of an issue (which is not "None") to that new priority. To me it looks like this assertion here would erroneously consider them unequal because getId would return "-1", even though the new priority is the same set by originalPriorityItem.

Is there a way to obtain the priority ID from the issue? If not, would one of these implementations make sense?

  • compare priority names instead (or maybe only as fallback if the ID for the priority cannot be determined)
  • change getId to return String? and don't try to revert the priority change if the result of getId for the new priority is null
  • check the changelog to verify that the last change was not done by a staff member (might be error-prone?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, in this case, priority should always be equal to originalPriority, since that's both the most recent staff priority changelog item and the current priority of the issue.

Aka, priority is always the already updated priority, not the priority from before the change. Which is what makes things tricky.

E.g. Mojang developer changes priority from None to Normal:

  • priority is now 11702
  • originalPriorityItem is `None [-1] -> Normal [11702]
  • originalPriorityId is 11702

Thus this check would fail and the module would return OperationNotNeeded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case I was thinking of is:

A new priority "Extremely Important" with ID 11699 is added, and a Mojang developer changes the priority of an issue to "Extremely Important". originalPriorityId is therefore "11699" and priority is "Extremely Important". However, because getId does not know the ID for "Extremely Important", it returns "-1", which is unequal to "11699", and therefore the module erroneously reverts the change.

Or am I misunderstanding something here?


// Ensure that the priority from the changelog is a currently valid priority value
// (e.g. 11602 was the original value for 'Normal', which is no longer valid)
assertValidPriority(originalPriorityId).mapLeft { result ->
log.error(
"[${issue.key}] Cannot revoke change to priority: " +
"Unknown mojang priority value '$originalPriorityName' [$originalPriorityId]"
)
result
}.bind()

updatePriority(originalPriorityId)
}
}

Expand All @@ -29,6 +58,16 @@ class RevokePriorityModule : Module {
else -> "-1"
}

private fun assertValidPriority(priorityId: String) =
if (isValidPriority(priorityId)) {
Unit.right()
} else {
OperationNotNeededModuleResponse.left()
}

private fun isValidPriority(priority: String): Boolean =
setOf("-1", "11700", "11701", "11702", "11703").contains(priority)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid duplication, what about having a map from priority name to ID, which is then used by getId, and isValidPriority could use the values of the map instead.


private fun isPriorityChange(item: ChangeLogItem) =
item.field == "Mojang Priority"

Expand All @@ -38,6 +77,6 @@ class RevokePriorityModule : Module {
private fun updateIsRecent(item: ChangeLogItem) =
item
.created
.plus(1, ChronoUnit.DAYS)
.plus(1, ChronoUnit.YEARS)
.isAfter(Instant.now())
}