Permalink
Browse files

Fist pass support for cla labels

  • Loading branch information...
anish committed Dec 20, 2015
1 parent 27c840a commit 58e44ec8d8f82f6e6067d33a22411afff392659f
Showing with 90 additions and 3 deletions.
  1. +19 −3 app/controllers/Application.scala
  2. +71 −0 app/utils/GitHub.scala
@@ -276,6 +276,15 @@ class Application @Inject() (env: Environment, gitHub: GitHub, db: Database, cry
externalCommitters.filterNot(clasForCommitters.map(_.contact.gitHubId).contains)
}
val repoLabelsFuture = gitHub.getAllLabels(ownerRepo, gitHub.integrationToken).map(_.value.map(_.\("name").as[String]).distinct.toList)
val labelMap = Map(("cla:missing","c40d0d"),("cla:signed","5ebc41"))
val labelCreatesFuture: Future[Seq[JsValue]] = repoLabelsFuture.flatMap { labels =>
val labelsToCreate: Seq[String] = labelMap.keys.toList.diff(labels)
gitHub.createLabels(ownerRepo, labelMap.filterKeys(labelsToCreate.contains), gitHub.integrationToken)
}
committersWithoutClasFuture.flatMap { committersWithoutClas =>
val state = if (committersWithoutClas.isEmpty) "success" else "failure"
@@ -287,11 +296,18 @@ class Application @Inject() (env: Environment, gitHub: GitHub, db: Database, cry
gitHub.issueComments(ownerRepo, prNumber, gitHub.integrationToken).flatMap { comments =>
val alreadyCommented = comments.value.exists(_.\("user").\("login").as[String] == integrationUserId)
if (committersWithoutClas.nonEmpty && !alreadyCommented) {
val body = s"Thanks for the contribution! Before we can merge this, we need ${committersWithoutClas.map(" @" + _).mkString} to [sign the Salesforce Contributor License Agreement]($claUrl)."
gitHub.commentOnIssue(ownerRepo, prNumber, body, gitHub.integrationToken)
if (committersWithoutClas.nonEmpty) {
gitHub.toggleLabelSafe(ownerRepo, "cla:missing", "cla:signed", alreadyCommented, prNumber, gitHub.integrationToken)
if(!alreadyCommented) {
val body = s"Thanks for the contribution! Before we can merge this, we need ${committersWithoutClas.map(" @" + _).mkString} to [sign the Salesforce Contributor License Agreement]($claUrl)."
gitHub.commentOnIssue(ownerRepo, prNumber, body, gitHub.integrationToken)
} else {
Future.successful(status)
}
}
else {
gitHub.toggleLabelSafe(ownerRepo, "cla:signed", "cla:missing", alreadyCommented, prNumber, gitHub.integrationToken)
Future.successful(status)
}
}
@@ -181,6 +181,77 @@ class GitHub @Inject() (configuration: Configuration, ws: WSClient) (implicit ec
ws(path, accessToken).get().flatMap(ok[JsArray])
}
def getAllLabels(ownerRepo: String, accessToken: String): Future[JsArray] = {
val path = s"repos/$ownerRepo/labels"
ws(path, accessToken).get().flatMap(ok[JsArray])
}
def createLabel(ownerRepo: String, name: String, color: String, accessToken: String): Future[JsValue] = {
val path = s"repos/$ownerRepo/labels"
val json = Json.obj(
"name" -> name,
"color" -> color
)
ws(path, accessToken).post(json).flatMap(created)
}
def createLabels(ownerRepo: String, labels: Map[String,String], accessToken: String): Future[Seq[JsValue]] = {
val labelCreateFutures = labels.map { labelColor =>
createLabel(ownerRepo, labelColor._1, labelColor._2, accessToken)
}
Future.sequence(labelCreateFutures.toList)
}
def getIssueLabels(ownerRepo: String, issueNumber: Int, accessToken: String): Future[JsArray] = {
val path = s"repos/$ownerRepo/issues/$issueNumber/labels"
ws(path, accessToken).get().flatMap(ok[JsArray])
}
def applyLabel(ownerRepo: String, name: String, issueNumber: Int, accessToken: String): Future[JsValue] = {
val path = s"repos/$ownerRepo/issues/$issueNumber/labels"
val json = Json.arr(
name
)
ws(path, accessToken).post(json).flatMap(ok[JsValue])
}
def applyLabelSafe(ownerRepo: String, name: String, issueNumber: Int, accessToken: String): Future[JsValue] = {
val issueLabelsFuture = getIssueLabels(ownerRepo, issueNumber, accessToken).map(_.value.map(_.\("name").as[String]).distinct.toList)
val labelAppliesFuture: Future[JsValue] = issueLabelsFuture.flatMap { labels =>
if (!labels.contains(name)) {
applyLabel(ownerRepo, name, issueNumber, accessToken)
} else {
Future(JsNull)
}
}
labelAppliesFuture
}
def removeLabel(ownerRepo: String, name: String, issueNumber: Int, accessToken: String): Future[JsValue] = {
val path = s"repos/$ownerRepo/issues/$issueNumber/labels/$name"
ws(path, accessToken).delete().flatMap(ok[JsValue])
}
def removeLabelSafe(ownerRepo: String, name: String, issueNumber: Int, accessToken: String): Future[JsValue] = {
val issueLabelsFuture = getIssueLabels(ownerRepo, issueNumber, accessToken).map(_.value.map(_.\("name").as[String]).distinct.toList)
val labelRemovesFuture: Future[JsValue] = issueLabelsFuture.flatMap { labels =>
if (labels.contains(name)) {
removeLabel(ownerRepo, name, issueNumber, accessToken)
} else {
Future(JsNull)
}
}
labelRemovesFuture
}
def toggleLabelSafe(ownerRepo: String, newLabel: String, oldLabel: String, remove: Boolean, issueNumber: Int, accessToken: String): Future[JsValue] = {
if (remove) {
removeLabelSafe(ownerRepo, oldLabel, issueNumber, accessToken)
}
applyLabelSafe(ownerRepo, newLabel, issueNumber, accessToken)
}
def orgWebhooks(org: String, accessToken: String): Future[JsArray] = {
val path = s"orgs/$org/hooks"
ws(path, accessToken).get().flatMap(ok[JsArray])

0 comments on commit 58e44ec

Please sign in to comment.