add webhook pull_request synchronize action

This commit is contained in:
nazoking
2015-02-27 13:36:50 +09:00
parent 579ed19949
commit 597f86dc7b
9 changed files with 130 additions and 20 deletions

View File

@@ -24,6 +24,7 @@ import api._
class RepositoryViewerController extends RepositoryViewerControllerBase class RepositoryViewerController extends RepositoryViewerControllerBase
with RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService with RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService
with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService
with WebHookPullRequestService
/** /**
@@ -31,7 +32,8 @@ class RepositoryViewerController extends RepositoryViewerControllerBase
*/ */
trait RepositoryViewerControllerBase extends ControllerBase { trait RepositoryViewerControllerBase extends ControllerBase {
self: RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService self: RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService
with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService => with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService
with WebHookPullRequestService =>
ArchiveCommand.registerFormat("zip", new ZipFormat) ArchiveCommand.registerFormat("zip", new ZipFormat)
ArchiveCommand.registerFormat("tar.gz", new TgzFormat) ArchiveCommand.registerFormat("tar.gz", new TgzFormat)
@@ -562,6 +564,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name) closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name)
// call web hook // call web hook
callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount)
val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId)) val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
callWebHookOf(repository.owner, repository.name, "push") { callWebHookOf(repository.owner, repository.name, "push") {
getAccountByUserName(repository.owner).map{ ownerAccount => getAccountByUserName(repository.owner).map{ ownerAccount =>

View File

@@ -2,7 +2,7 @@ package service
import model.Profile._ import model.Profile._
import profile.simple._ import profile.simple._
import model.{PullRequest, Issue} import model.{PullRequest, Issue, WebHook, Account}
import util.JGitUtil import util.JGitUtil
trait PullRequestService { self: IssuesService => trait PullRequestService { self: IssuesService =>

View File

@@ -116,6 +116,40 @@ trait WebHookPullRequestService extends WebHookService {
} }
} }
} }
def getPullRequestsByRequestForWebhook(userName:String, repositoryName:String, branch:String)
(implicit s: Session): Map[(Issue, PullRequest, Account, Account), List[WebHook]] =
(for{
is <- Issues if is.closed === false.bind
pr <- PullRequests if pr.byPrimaryKey(is.userName, is.repositoryName, is.issueId)
if pr.requestUserName === userName.bind
if pr.requestRepositoryName === repositoryName.bind
if pr.requestBranch === branch.bind
bu <- Accounts if bu.userName === pr.userName
ru <- Accounts if ru.userName === pr.requestUserName
wh <- WebHooks if wh.byRepository(is.userName , is.repositoryName)
} yield {
((is, pr, bu, ru), wh)
}).list.groupBy(_._1).mapValues(_.map(_._2))
def callPullRequestWebHookByRequestBranch(action: String, requestRepository: RepositoryService.RepositoryInfo, requestBranch: String, baseUrl: String, sender: model.Account)(implicit s: Session, context:JsonFormat.Context): Unit = {
import WebHookService._
for{
((issue, pullRequest, baseOwner, headOwner), webHooks) <- getPullRequestsByRequestForWebhook(requestRepository.owner, requestRepository.name, requestBranch)
baseRepo <- getRepository(pullRequest.userName, pullRequest.repositoryName, baseUrl)
} yield {
val payload = WebHookPullRequestPayload(
action = action,
issue = issue,
pullRequest = pullRequest,
headRepository = requestRepository,
headOwner = headOwner,
baseRepository = baseRepo,
baseOwner = baseOwner,
sender = sender)
callWebHook("pull_request", webHooks, payload)
}
}
} }
trait WebHookIssueCommentService extends WebHookPullRequestService { trait WebHookIssueCommentService extends WebHookPullRequestService {

View File

@@ -97,7 +97,8 @@ import scala.collection.JavaConverters._
class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String)(implicit session: Session) class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String)(implicit session: Session)
extends PostReceiveHook with PreReceiveHook extends PostReceiveHook with PreReceiveHook
with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService { with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService
with WebHookPullRequestService {
private val logger = LoggerFactory.getLogger(classOf[CommitLogHook]) private val logger = LoggerFactory.getLogger(classOf[CommitLogHook])
private var existIds: Seq[String] = Nil private var existIds: Seq[String] = Nil
@@ -121,6 +122,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
val pushedIds = scala.collection.mutable.Set[String]() val pushedIds = scala.collection.mutable.Set[String]()
commands.asScala.foreach { command => commands.asScala.foreach { command =>
logger.debug(s"commandType: ${command.getType}, refName: ${command.getRefName}") logger.debug(s"commandType: ${command.getType}, refName: ${command.getRefName}")
implicit val apiContext = api.JsonFormat.Context(baseUrl)
val refName = command.getRefName.split("/") val refName = command.getRefName.split("/")
val branchName = refName.drop(2).mkString("/") val branchName = refName.drop(2).mkString("/")
val commits = if (refName(1) == "tags") { val commits = if (refName(1) == "tags") {
@@ -137,8 +139,10 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
countIssue(IssueSearchCondition(state = "open"), false, owner -> repository) + countIssue(IssueSearchCondition(state = "open"), false, owner -> repository) +
countIssue(IssueSearchCondition(state = "closed"), false, owner -> repository) countIssue(IssueSearchCondition(state = "closed"), false, owner -> repository)
val repositoryInfo = getRepository(owner, repository, baseUrl).get
// Extract new commit and apply issue comment // Extract new commit and apply issue comment
val defaultBranch = getRepository(owner, repository, baseUrl).get.repository.defaultBranch val defaultBranch = repositoryInfo.repository.defaultBranch
val newCommits = commits.flatMap { commit => val newCommits = commits.flatMap { commit =>
if (!existIds.contains(commit.id) && !pushedIds.contains(commit.id)) { if (!existIds.contains(commit.id) && !pushedIds.contains(commit.id)) {
if (issueCount > 0) { if (issueCount > 0) {
@@ -175,16 +179,17 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
ReceiveCommand.Type.UPDATE | ReceiveCommand.Type.UPDATE |
ReceiveCommand.Type.UPDATE_NONFASTFORWARD => ReceiveCommand.Type.UPDATE_NONFASTFORWARD =>
updatePullRequests(owner, repository, branchName) updatePullRequests(owner, repository, branchName)
getAccountByUserName(pusher).map{ pusherAccount =>
callPullRequestWebHookByRequestBranch("synchronize", repositoryInfo, branchName, baseUrl, pusherAccount)
}
case _ => case _ =>
} }
} }
// call web hook // call web hook
implicit val apiContext = api.JsonFormat.Context(baseUrl)
callWebHookOf(owner, repository, "push"){ callWebHookOf(owner, repository, "push"){
for(pusherAccount <- getAccountByUserName(pusher); for(pusherAccount <- getAccountByUserName(pusher);
ownerAccount <- getAccountByUserName(owner); ownerAccount <- getAccountByUserName(owner)) yield {
repositoryInfo <- getRepository(owner, repository, baseUrl)) yield {
WebHookPushPayload(git, pusherAccount, command.getRefName, repositoryInfo, newCommits, ownerAccount) WebHookPushPayload(git, pusherAccount, command.getRefName, repositoryInfo, newCommits, ownerAccount)
} }
} }

View File

@@ -6,11 +6,6 @@ import model._
class AccessTokenServiceSpec extends Specification with ServiceSpecBase { class AccessTokenServiceSpec extends Specification with ServiceSpecBase {
def generateNewAccount(name:String)(implicit s:Session):Account = {
AccountService.createAccount(name, name, name, s"${name}@example.com", false, None)
AccountService.getAccountByUserName(name).get
}
"AccessTokenService" should { "AccessTokenService" should {
"generateAccessToken" in { withTestDB { implicit session => "generateAccessToken" in { withTestDB { implicit session =>
AccessTokenService.generateAccessToken("root", "note") must be like{ AccessTokenService.generateAccessToken("root", "note") must be like{

View File

@@ -6,10 +6,6 @@ import model.Profile._
import profile.simple._ import profile.simple._
class CommitStatusServiceSpec extends Specification with ServiceSpecBase with CommitStatusService class CommitStatusServiceSpec extends Specification with ServiceSpecBase with CommitStatusService
with RepositoryService with AccountService{ with RepositoryService with AccountService{
def generateNewAccount(name:String)(implicit s:Session):Account = {
createAccount(name, name, name, s"${name}@example.com", false, None)
getAccountByUserName(name).get
}
val now = new java.util.Date() val now = new java.util.Date()
val fixture1 = CommitStatus( val fixture1 = CommitStatus(
userName = "root", userName = "root",

View File

@@ -5,10 +5,6 @@ import model._
import model.Profile._ import model.Profile._
import profile.simple._ import profile.simple._
class RepositoryServiceSpec extends Specification with ServiceSpecBase with RepositoryService with AccountService{ class RepositoryServiceSpec extends Specification with ServiceSpecBase with RepositoryService with AccountService{
def generateNewAccount(name:String)(implicit s:Session):Account = {
createAccount(name, name, name, s"${name}@example.com", false, None)
getAccountByUserName(name).get
}
"RepositoryService" should { "RepositoryService" should {
"renameRepository can rename CommitState" in { withTestDB { implicit session => "renameRepository can rename CommitState" in { withTestDB { implicit session =>
val tester = generateNewAccount("tester") val tester = generateNewAccount("tester")

View File

@@ -8,6 +8,7 @@ import java.sql.DriverManager
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import scala.util.Random import scala.util.Random
import java.io.File import java.io.File
import model._
trait ServiceSpecBase { trait ServiceSpecBase {
@@ -24,4 +25,41 @@ trait ServiceSpecBase {
} }
} }
def generateNewAccount(name:String)(implicit s:Session):Account = {
AccountService.createAccount(name, name, name, s"${name}@example.com", false, None)
AccountService.getAccountByUserName(name).get
}
lazy val dummyService = new RepositoryService with AccountService with IssuesService with PullRequestService (){}
def generateNewUserWithDBRepository(userName:String, repositoryName:String)(implicit s:Session):Account = {
val ac = generateNewAccount(userName)
dummyService.createRepository(repositoryName, userName, None, false)
ac
}
def generateNewPullRequest(base:String, request:String)(implicit s:Session):(Issue, PullRequest) = {
val Array(baseUserName, baseRepositoryName, baesBranch)=base.split("/")
val Array(requestUserName, requestRepositoryName, requestBranch)=request.split("/")
val issueId = dummyService.createIssue(
owner = baseUserName,
repository = baseRepositoryName,
loginUser = requestUserName,
title = "issue title",
content = None,
assignedUserName = None,
milestoneId = None,
isPullRequest = true)
dummyService.createPullRequest(
originUserName = baseUserName,
originRepositoryName = baseRepositoryName,
issueId = issueId,
originBranch = baesBranch,
requestUserName = requestUserName,
requestRepositoryName = requestRepositoryName,
requestBranch = requestBranch,
commitIdFrom = baesBranch,
commitIdTo = requestBranch)
dummyService.getPullRequest(baseUserName, baseRepositoryName, issueId).get
}
} }

View File

@@ -0,0 +1,43 @@
package service
import org.specs2.mutable.Specification
import java.util.Date
import model._
class WebHookServiceSpec extends Specification with ServiceSpecBase {
lazy val service = new WebHookPullRequestService with AccountService with RepositoryService with PullRequestService with IssuesService
"WebHookPullRequestService.getPullRequestsByRequestForWebhook" should {
"find from request branch" in { withTestDB { implicit session =>
val user1 = generateNewUserWithDBRepository("user1","repo1")
val user2 = generateNewUserWithDBRepository("user2","repo2")
val user3 = generateNewUserWithDBRepository("user3","repo3")
val (issue1, pullreq1) = generateNewPullRequest("user1/repo1/master1", "user2/repo2/master2")
val (issue3, pullreq3) = generateNewPullRequest("user3/repo3/master3", "user2/repo2/master2")
val (issue32, pullreq32) = generateNewPullRequest("user3/repo3/master32", "user2/repo2/master2")
generateNewPullRequest("user2/repo2/master2", "user1/repo1/master2")
service.addWebHookURL("user1", "repo1", "webhook1-1")
service.addWebHookURL("user1", "repo1", "webhook1-2")
service.addWebHookURL("user2", "repo2", "webhook2-1")
service.addWebHookURL("user2", "repo2", "webhook2-2")
service.addWebHookURL("user3", "repo3", "webhook3-1")
service.addWebHookURL("user3", "repo3", "webhook3-2")
service.getPullRequestsByRequestForWebhook("user1","repo1","master1") must_== Map.empty
var r = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet)
r.size must_== 3
r((issue1, pullreq1, user1, user2)) must_== Set("webhook1-1","webhook1-2")
r((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2")
r((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2")
// when closed, it not founds.
service.updateClosed("user1","repo1",issue1.issueId, true)
var r2 = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet)
r2.size must_== 2
r2((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2")
r2((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2")
} }
}
}