Skip to content

Commit 6a633ef

Browse files
committed
Implement rechecking of CLA
1 parent e6ca06a commit 6a633ef

File tree

3 files changed

+66
-22
lines changed

3 files changed

+66
-22
lines changed

bot/src/dotty/tools/bot/PullRequestService.scala

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,19 @@ trait PullRequestService {
5454
currentVersion: String
5555
)
5656

57+
private[this] val githubUrl = "https://api.github.com"
58+
5759
def claUrl(userName: String): String =
5860
s"https://www.lightbend.com/contribute/cla/scala/check/$userName"
5961

6062
def commitsUrl(prNumber: Int): String =
61-
s"https://api.github.com/repos/lampepfl/dotty/pulls/$prNumber/commits?per_page=100"
63+
s"$githubUrl/repos/lampepfl/dotty/pulls/$prNumber/commits?per_page=100"
6264

6365
def statusUrl(sha: String): String =
64-
s"https://api.github.com/repos/lampepfl/dotty/statuses/$sha"
66+
s"$githubUrl/repos/lampepfl/dotty/statuses/$sha"
6567

6668
def issueCommentsUrl(issueNbr: Int): String =
67-
s"https://api.github.com/repos/lampepfl/dotty/issues/$issueNbr/comments"
69+
s"$githubUrl/repos/lampepfl/dotty/issues/$issueNbr/comments"
6870

6971
def toUri(url: String): Task[Uri] =
7072
Uri.fromString(url).fold(Task.fail, Task.now)
@@ -201,7 +203,7 @@ trait PullRequestService {
201203
(validStatuses, invalidStatuses) = statuses.partition(_.isValid)
202204
invalidUsers = usersFromInvalid(invalidStatuses)
203205

204-
// Mark the invalid statuses:
206+
// Mark the invalid commits:
205207
_ <- sendStatuses(invalidStatuses, httpClient)
206208

207209
// Set status of last to indicate previous failures or all good:
@@ -220,35 +222,48 @@ trait PullRequestService {
220222

221223
}
222224

223-
// TODO: Could this be done with `issueNbr` instead?
225+
def getStatus(commit: Commit, client: Client): Task[StatusResponse] =
226+
for {
227+
endpoint <- toUri(statusUrl(commit.sha))
228+
req <- getRequest(endpoint)
229+
res <- client.expect(req)(jsonOf[List[StatusResponse]])
230+
} yield res.head
231+
224232
def getStatuses(commits: List[Commit], client: Client): Task[List[StatusResponse]] =
225-
???
233+
Task.gatherUnordered(commits.map(getStatus(_, client)))
226234

227-
private def extractCommit(status: StatusResponse): Task[Commit] =
228-
???
235+
private def extractCommitSha(status: StatusResponse): Task[String] =
236+
Task.delay(status.sha)
237+
238+
def recheckCLA(statuses: List[StatusResponse], commits: List[Commit], client: Client): Task[List[CommitStatus]] = {
239+
/** Return the matching commits from the SHAs */
240+
def prunedCommits(shas: List[String]): Task[List[Commit]] =
241+
Task.delay(commits.filter(cm => shas.contains(cm.sha)))
229242

230-
def recheckCLA(statuses: List[StatusResponse], client: Client): Task[List[CommitStatus]] =
231243
for {
232-
commits <- Task.gatherUnordered(statuses.map(extractCommit))
233-
statuses <- checkCLA(commits, client)
244+
commitShas <- Task.gatherUnordered(statuses.map(extractCommitSha))
245+
commits <- prunedCommits(commitShas)
246+
statuses <- checkCLA(commits, client)
234247
} yield statuses
248+
}
235249

236250
def checkSynchronize(issue: Issue): Task[Response] = {
237251
val httpClient = PooledHttp1Client()
238252

239253
for {
240-
commits <- getCommits(issue.number, httpClient)
241-
statuses <- getStatuses(commits, httpClient)
242-
stillInvalid <- recheckCLA(statuses, httpClient)
254+
commits <- getCommits(issue.number, httpClient)
255+
statuses <- checkCLA(commits, httpClient)
256+
257+
(_, invalid) = statuses.partition(_.isValid)
258+
259+
_ <- sendStatuses(invalid, httpClient)
243260

244-
// Set final commit status based on `stillInvalid`:
261+
// Set final commit status based on `invalid`:
245262
_ <- {
246-
if (stillInvalid.nonEmpty)
247-
setStatus(InvalidPrevious(usersFromInvalid(stillInvalid), commits.last), httpClient)
248-
else {
249-
val lastCommit = commits.last
250-
setStatus(Valid(lastCommit.author.login, lastCommit), httpClient)
251-
}
263+
if (invalid.nonEmpty)
264+
setStatus(InvalidPrevious(usersFromInvalid(invalid), commits.last), httpClient)
265+
else
266+
setStatus(statuses.last, httpClient)
252267
}
253268
_ <- shutdownClient(httpClient)
254269
resp <- Ok("Updated PR checked")

bot/src/dotty/tools/bot/model/Github.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ object Github {
4141
url: String,
4242
id: Long,
4343
state: String
44-
)
44+
) {
45+
def sha: String = url.split('/').last
46+
}
4547

4648
case class Comment(user: Author)
4749
}

bot/test/PRServiceTests.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,31 @@ class PRServiceTests extends PullRequestService {
103103

104104
httpClient.shutdownNow()
105105
}
106+
107+
@Test def canGetStatus = {
108+
val sha = "fa64b4b613fe5e78a5b4185b4aeda89e2f1446ff"
109+
val commit = Commit(sha, Author(None), Author(None), CommitInfo(""))
110+
val status = withClient(getStatus(commit, _))
111+
112+
assert(status.sha == sha, "someting wong")
113+
}
114+
115+
@Test def canRecheckCLA = {
116+
val shas =
117+
"1d62587cb3f41dafd796b0c92ec1c22d95b879f9" ::
118+
"ad60a386f488a16612c093576bf7bf4d9f0073bf" ::
119+
Nil
120+
121+
val commits = shas.map { sha =>
122+
Commit(sha, Author(Some("felixmulder")), Author(Some("felixmulder")), CommitInfo(""))
123+
}
124+
125+
val statuses = shas.map { sha =>
126+
StatusResponse("https://api.github.com/repos/lampepfl/dotty/statuses/" + sha, 0, "failure")
127+
}
128+
129+
val rechecked = withClient(recheckCLA(statuses, commits, _))
130+
131+
assert(rechecked.forall(cs => cs.isValid), s"Should have set all statuses to valid, but got: $rechecked")
132+
}
106133
}

0 commit comments

Comments
 (0)