Skip to content

Commit b106844

Browse files
committed
introduce a builder-style structure for Mergify request_reviews
1 parent dce5a89 commit b106844

File tree

2 files changed

+80
-37
lines changed

2 files changed

+80
-37
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ ThisBuild / mergifyPrRules += MergifyPrRule(
2020
"assign scala-steward's PRs for review",
2121
List(MergifyCondition.Custom("author=typelevel-steward[bot]")),
2222
List(
23-
MergifyAction.RequestReviews("armanbilge")
23+
MergifyAction.RequestReviews.fromUsers("armanbilge")
2424
)
2525
)
2626

mergify/src/main/scala/org/typelevel/sbt/mergify/MergifyAction.scala

Lines changed: 79 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
package org.typelevel.sbt.mergify
1818

19-
import cats.data.*
20-
import cats.syntax.all.*
21-
import io.circe.*
22-
import io.circe.syntax.*
19+
import cats.data._
20+
import cats.syntax.all._
21+
import io.circe._
22+
import io.circe.syntax._
23+
import org.typelevel.sbt.mergify.MergifyAction.RequestReviews._
2324
import sbt.librarymanagement.Developer
2425

2526
sealed abstract class MergifyAction {
@@ -62,51 +63,93 @@ object MergifyAction {
6263
}
6364
}
6465

65-
final class RequestReviews(
66-
val users: Either[NonEmptyList[String], NonEmptyMap[String, Int]],
67-
val randomCount: Option[Int])
66+
class RequestReviews private (
67+
private val users: Option[OptionallyWeighted],
68+
private val teams: Option[OptionallyWeighted],
69+
private val usersFromTeams: Option[OptionallyWeighted],
70+
private val randomCount: Option[Int])
6871
extends MergifyAction {
6972
override private[mergify] def name = "request_reviews"
70-
}
7173

72-
object RequestReviews {
73-
def apply(user: String, users: String*) =
74-
new RequestReviews(NonEmptyList.of(user, users: _*).asLeft, None)
74+
private def copy(
75+
users: Option[OptionallyWeighted] = users,
76+
teams: Option[OptionallyWeighted] = teams,
77+
usersFromTeams: Option[OptionallyWeighted] = usersFromTeams,
78+
randomCount: Option[Int] = randomCount): RequestReviews =
79+
new RequestReviews(users, teams, usersFromTeams, randomCount) {}
7580

76-
def apply(weightedUser: (String, Int), weightedUsers: (String, Int)*) =
77-
new RequestReviews(NonEmptyMap.of(weightedUser, weightedUsers: _*).asRight, None)
81+
def andUsers(user: String, users: String*): RequestReviews =
82+
copy(users = Unweighted(NonEmptyList.of(user, users: _*)).some)
7883

79-
def apply(randomCount: Int, user: String, users: String*) =
80-
new RequestReviews(NonEmptyList.of(user, users: _*).asLeft, Option(randomCount))
84+
def andUsers(user: (String, Int), users: (String, Int)*): RequestReviews =
85+
copy(users = Weighted(NonEmptyList.of(user, users: _*)).some)
8186

82-
def apply(randomCount: Int, weightedUser: (String, Int), weightedUsers: (String, Int)*) =
83-
new RequestReviews(
84-
NonEmptyMap.of(weightedUser, weightedUsers: _*).asRight,
85-
Option(randomCount)
86-
)
87+
def andTeams(team: String, teams: String*): RequestReviews =
88+
copy(teams = Unweighted(NonEmptyList.of(team, teams: _*)).some)
89+
90+
def andTeams(team: (String, Int), teams: (String, Int)*): RequestReviews =
91+
copy(teams = Weighted(NonEmptyList.of(team, teams: _*)).some)
92+
93+
def andUsersFromTeams(team: String, teams: String*): RequestReviews =
94+
copy(usersFromTeams = Unweighted(NonEmptyList.of(team, teams: _*)).some)
95+
96+
def andUsersFromTeams(team: (String, Int), teams: (String, Int)*): RequestReviews =
97+
copy(usersFromTeams = Weighted(NonEmptyList.of(team, teams: _*)).some)
98+
99+
def withRandomCount(count: Int): RequestReviews =
100+
copy(randomCount = Option(count))
101+
102+
def andDevelopers(developers: List[Developer]): RequestReviews =
103+
copy(users = NonEmptyList.fromList(developers.map(_.id)).map(Unweighted))
104+
}
105+
106+
object RequestReviews {
107+
def fromUsers(user: String, users: String*) =
108+
new RequestReviews(Unweighted(NonEmptyList.of(user, users: _*)).some, None, None, None)
109+
def fromUsers(user: (String, Int), users: (String, Int)*) =
110+
new RequestReviews(Weighted(NonEmptyList.of(user, users: _*)).some, None, None, None)
111+
def fromTeams(team: String, teams: String*) =
112+
new RequestReviews(None, Unweighted(NonEmptyList.of(team, teams: _*)).some, None, None)
113+
def fromTeams(team: (String, Int), teams: (String, Int)*) =
114+
new RequestReviews(None, Weighted(NonEmptyList.of(team, teams: _*)).some, None, None)
115+
def fromUsersOfTeams(team: String, teams: String*) =
116+
new RequestReviews(None, None, Unweighted(NonEmptyList.of(team, teams: _*)).some, None)
117+
def fromUsersOfTeams(team: (String, Int), teams: (String, Int)*) =
118+
new RequestReviews(None, None, Weighted(NonEmptyList.of(team, teams: _*)).some, None)
87119

88120
def apply(developers: List[Developer]) =
89121
new RequestReviews(
90-
developers
91-
.map(_.id)
92-
.toNel
93-
.getOrElse(throw new RuntimeException("developers must be non-empty"))
94-
.asLeft,
122+
Unweighted(
123+
developers
124+
.map(_.id)
125+
.toNel
126+
.getOrElse(throw new RuntimeException("developers must be non-empty"))
127+
).some,
128+
None,
129+
None,
95130
None)
96131

97-
def apply(developers: List[Developer], randomCount: Int) =
98-
new RequestReviews(
99-
developers
100-
.map(_.id)
101-
.toNel
102-
.getOrElse(throw new RuntimeException("developers must be non-empty"))
103-
.asLeft,
104-
randomCount.some)
105-
106132
implicit def encoder: Encoder[RequestReviews] =
107-
Encoder.forProduct2("users", "random_count") { requestReviews =>
108-
(requestReviews.users.fold(_.asJson, _.asJson), requestReviews.randomCount)
133+
Encoder.forProduct4("users", "teams", "users_from_teams", "random_count") {
134+
requestReviews =>
135+
(
136+
requestReviews.users,
137+
requestReviews.teams,
138+
requestReviews.usersFromTeams,
139+
requestReviews.randomCount
140+
)
141+
}
142+
143+
private sealed trait OptionallyWeighted
144+
private case class Weighted(value: NonEmptyList[(String, Int)]) extends OptionallyWeighted
145+
private case class Unweighted(value: NonEmptyList[String]) extends OptionallyWeighted
146+
147+
private object OptionallyWeighted {
148+
implicit val encoder: Encoder[OptionallyWeighted] = {
149+
case Weighted(value) => value.asJson
150+
case Unweighted(value) => value.asJson
109151
}
152+
}
110153
}
111154

112155
object Update extends MergifyAction {

0 commit comments

Comments
 (0)