mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 06:25:51 +01:00
add webhook pull-request-review-comment
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
package gitbucket.core.api
|
||||||
|
|
||||||
|
import gitbucket.core.util.RepositoryName
|
||||||
|
import gitbucket.core.model.CommitComment
|
||||||
|
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent
|
||||||
|
*/
|
||||||
|
case class ApiPullRequestReviewComment(
|
||||||
|
id: Int, // 29724692
|
||||||
|
// "diff_hunk": "@@ -1 +1 @@\n-# public-repo",
|
||||||
|
path: String, // "README.md",
|
||||||
|
// "position": 1,
|
||||||
|
// "original_position": 1,
|
||||||
|
commit_id: String, // "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
// "original_commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
user: ApiUser,
|
||||||
|
body: String, // "Maybe you should use more emojji on this line.",
|
||||||
|
created_at: Date, // "2015-05-05T23:40:27Z",
|
||||||
|
updated_at: Date // "2015-05-05T23:40:27Z",
|
||||||
|
)(repositoryName:RepositoryName, issueId: Int) extends FieldSerializable {
|
||||||
|
// "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments/29724692",
|
||||||
|
val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/pulls/comments/${id}")
|
||||||
|
// "html_url": "https://github.com/baxterthehacker/public-repo/pull/1#discussion_r29724692",
|
||||||
|
val html_url = ApiPath(s"/${repositoryName.fullName}/pull/${issueId}#discussion_r${id}")
|
||||||
|
// "pull_request_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1",
|
||||||
|
val pull_request_url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/pulls/${issueId}")
|
||||||
|
|
||||||
|
/*
|
||||||
|
"_links": {
|
||||||
|
"self": {
|
||||||
|
"href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments/29724692"
|
||||||
|
},
|
||||||
|
"html": {
|
||||||
|
"href": "https://github.com/baxterthehacker/public-repo/pull/1#discussion_r29724692"
|
||||||
|
},
|
||||||
|
"pull_request": {
|
||||||
|
"href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
val _links = Map(
|
||||||
|
"self" -> Map("href" -> url),
|
||||||
|
"html" -> Map("href" -> html_url),
|
||||||
|
"pull_request" -> Map("href" -> pull_request_url))
|
||||||
|
}
|
||||||
|
|
||||||
|
object ApiPullRequestReviewComment{
|
||||||
|
def apply(comment: CommitComment, commentedUser: ApiUser, repositoryName: RepositoryName, issueId: Int): ApiPullRequestReviewComment =
|
||||||
|
new ApiPullRequestReviewComment(
|
||||||
|
id = comment.commentId,
|
||||||
|
path = comment.fileName.getOrElse(""),
|
||||||
|
commit_id = comment.commitId,
|
||||||
|
user = commentedUser,
|
||||||
|
body = comment.content,
|
||||||
|
created_at = comment.registeredDate,
|
||||||
|
updated_at = comment.updatedDate
|
||||||
|
)(repositoryName, issueId)
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ import org.scalatra._
|
|||||||
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
|
with WebHookPullRequestService with WebHookPullRequestReviewCommentService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The repository viewer.
|
* The repository viewer.
|
||||||
@@ -40,7 +40,7 @@ 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 =>
|
with WebHookPullRequestService with WebHookPullRequestReviewCommentService =>
|
||||||
|
|
||||||
ArchiveCommand.registerFormat("zip", new ZipFormat)
|
ArchiveCommand.registerFormat("zip", new ZipFormat)
|
||||||
ArchiveCommand.registerFormat("tar.gz", new TgzFormat)
|
ArchiveCommand.registerFormat("tar.gz", new TgzFormat)
|
||||||
@@ -396,12 +396,14 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
val id = params("id")
|
val id = params("id")
|
||||||
val commentId = createCommitComment(repository.owner, repository.name, id, context.loginAccount.get.userName,
|
val commentId = createCommitComment(repository.owner, repository.name, id, context.loginAccount.get.userName,
|
||||||
form.content, form.fileName, form.oldLineNumber, form.newLineNumber, form.issueId.isDefined)
|
form.content, form.fileName, form.oldLineNumber, form.newLineNumber, form.issueId.isDefined)
|
||||||
|
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
|
||||||
form.issueId match {
|
form.issueId match {
|
||||||
case Some(issueId) => recordCommentPullRequestActivity(repository.owner, repository.name, context.loginAccount.get.userName, issueId, form.content)
|
case Some(issueId) =>
|
||||||
|
recordCommentPullRequestActivity(repository.owner, repository.name, context.loginAccount.get.userName, issueId, form.content)
|
||||||
|
callPullRequestReviewCommentWebHook("create", comment, repository, issueId, context.baseUrl, context.loginAccount.get)
|
||||||
case None => recordCommentCommitActivity(repository.owner, repository.name, context.loginAccount.get.userName, id, form.content)
|
case None => recordCommentCommitActivity(repository.owner, repository.name, context.loginAccount.get.userName, id, form.content)
|
||||||
}
|
}
|
||||||
helper.html.commitcomment(getCommitComment(repository.owner, repository.name, commentId.toString).get,
|
helper.html.commitcomment(comment, hasWritePermission(repository.owner, repository.name, context.loginAccount), repository)
|
||||||
hasWritePermission(repository.owner, repository.name, context.loginAccount), repository)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ajaxGet("/:owner/:repository/commit_comments/_data/:id")(readableUsersOnly { repository =>
|
ajaxGet("/:owner/:repository/commit_comments/_data/:id")(readableUsersOnly { repository =>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package gitbucket.core.service
|
package gitbucket.core.service
|
||||||
|
|
||||||
import gitbucket.core.api._
|
import gitbucket.core.api._
|
||||||
import gitbucket.core.model.{WebHook, Account, Issue, PullRequest, IssueComment, WebHookEvent}
|
import gitbucket.core.model.{WebHook, Account, Issue, PullRequest, IssueComment, WebHookEvent, CommitComment}
|
||||||
import gitbucket.core.model.Profile._
|
import gitbucket.core.model.Profile._
|
||||||
import profile.simple._
|
import profile.simple._
|
||||||
import gitbucket.core.util.JGitUtil.CommitInfo
|
import gitbucket.core.util.JGitUtil.CommitInfo
|
||||||
@@ -212,6 +212,35 @@ trait WebHookPullRequestService extends WebHookService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait WebHookPullRequestReviewCommentService extends WebHookService {
|
||||||
|
self: AccountService with RepositoryService with PullRequestService with IssuesService with CommitsService =>
|
||||||
|
def callPullRequestReviewCommentWebHook(action: String, comment: CommitComment, repository: RepositoryService.RepositoryInfo, issueId: Int, baseUrl: String, sender: Account)(implicit s: Session, context:JsonFormat.Context): Unit = {
|
||||||
|
import WebHookService._
|
||||||
|
callWebHookOf(repository.owner, repository.name, WebHook.PullRequestReviewComment){
|
||||||
|
for{
|
||||||
|
(issue, pullRequest) <- getPullRequest(repository.owner, repository.name, issueId)
|
||||||
|
users = getAccountsByUserNames(Set(repository.owner, pullRequest.requestUserName, issue.openedUserName), Set(sender))
|
||||||
|
baseOwner <- users.get(repository.owner)
|
||||||
|
headOwner <- users.get(pullRequest.requestUserName)
|
||||||
|
issueUser <- users.get(issue.openedUserName)
|
||||||
|
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName, baseUrl)
|
||||||
|
} yield {
|
||||||
|
WebHookPullRequestReviewCommentPayload(
|
||||||
|
action = action,
|
||||||
|
comment = comment,
|
||||||
|
issue = issue,
|
||||||
|
issueUser = issueUser,
|
||||||
|
pullRequest = pullRequest,
|
||||||
|
headRepository = headRepo,
|
||||||
|
headOwner = headOwner,
|
||||||
|
baseRepository = repository,
|
||||||
|
baseOwner = baseOwner,
|
||||||
|
sender = sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trait WebHookIssueCommentService extends WebHookPullRequestService {
|
trait WebHookIssueCommentService extends WebHookPullRequestService {
|
||||||
self: AccountService with RepositoryService with PullRequestService with IssuesService =>
|
self: AccountService with RepositoryService with PullRequestService with IssuesService =>
|
||||||
|
|
||||||
@@ -341,4 +370,38 @@ object WebHookService {
|
|||||||
comment = ApiComment(comment, RepositoryName(repository), issue.issueId, ApiUser(commentUser), issue.isPullRequest),
|
comment = ApiComment(comment, RepositoryName(repository), issue.issueId, ApiUser(commentUser), issue.isPullRequest),
|
||||||
sender = ApiUser(sender))
|
sender = ApiUser(sender))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent
|
||||||
|
case class WebHookPullRequestReviewCommentPayload(
|
||||||
|
action: String,
|
||||||
|
comment: ApiPullRequestReviewComment,
|
||||||
|
pull_request: ApiPullRequest,
|
||||||
|
repository: ApiRepository,
|
||||||
|
sender: ApiUser
|
||||||
|
) extends WebHookPayload
|
||||||
|
|
||||||
|
object WebHookPullRequestReviewCommentPayload{
|
||||||
|
def apply(
|
||||||
|
action: String,
|
||||||
|
comment: CommitComment,
|
||||||
|
issue: Issue,
|
||||||
|
issueUser: Account,
|
||||||
|
pullRequest: PullRequest,
|
||||||
|
headRepository: RepositoryInfo,
|
||||||
|
headOwner: Account,
|
||||||
|
baseRepository: RepositoryInfo,
|
||||||
|
baseOwner: Account,
|
||||||
|
sender: Account
|
||||||
|
) : WebHookPullRequestReviewCommentPayload = {
|
||||||
|
val headRepoPayload = ApiRepository(headRepository, headOwner)
|
||||||
|
val baseRepoPayload = ApiRepository(baseRepository, baseOwner)
|
||||||
|
val senderPayload = ApiUser(sender)
|
||||||
|
WebHookPullRequestReviewCommentPayload(
|
||||||
|
action = action,
|
||||||
|
comment = ApiPullRequestReviewComment(comment, senderPayload, RepositoryName(baseRepository), issue.issueId),
|
||||||
|
pull_request = ApiPullRequest(issue, pullRequest, headRepoPayload, baseRepoPayload, ApiUser(issueUser)),
|
||||||
|
repository = baseRepoPayload,
|
||||||
|
sender = senderPayload)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
@import gitbucket.core._
|
@import gitbucket.core._
|
||||||
@import gitbucket.core.view.helpers._
|
@import gitbucket.core.view.helpers._
|
||||||
<div class="@if(comment.fileName.isDefined && (!latestCommitId.isDefined || latestCommitId.get == comment.commitId)){inline-comment}"
|
<div class="@if(comment.fileName.isDefined && (!latestCommitId.isDefined || latestCommitId.get == comment.commitId)){inline-comment}"
|
||||||
|
id="discussion_r@comment.commentId"
|
||||||
@if(comment.fileName.isDefined){filename="@comment.fileName.get"}
|
@if(comment.fileName.isDefined){filename="@comment.fileName.get"}
|
||||||
@if(comment.newLine.isDefined){newline="@comment.newLine.get"}
|
@if(comment.newLine.isDefined){newline="@comment.newLine.get"}
|
||||||
@if(comment.oldLine.isDefined){oldline="@comment.oldLine.get"}>
|
@if(comment.oldLine.isDefined){oldline="@comment.oldLine.get"}>
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ name="@(name).@event.name" value="on" @if(events(event)){checked}
|
|||||||
<label class="checkbox"><input type="checkbox" @check("events",DeploymentStatus) />Deployment status <small class="help-block">Deployment status updated from the API. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",DeploymentStatus) />Deployment status <small class="help-block">Deployment status updated from the API. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Fork) />Fork <small class="help-block">Repository forked. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Fork) />Fork <small class="help-block">Repository forked. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Gollum) />Gollum <small class="help-block">Wiki page updated. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Gollum) />Gollum <small class="help-block">Wiki page updated. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",PullRequestReviewComment) />Pull Request review comment <small class="help-block">Pull Request diff commented on. </small> </label>
|
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Member) />Member <small class="help-block">Collaborator added to a non-organization repository. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Member) />Member <small class="help-block">Collaborator added to a non-organization repository. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",PageBuild) />Page build <small class="help-block">Pages site built. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",PageBuild) />Page build <small class="help-block">Pages site built. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Public) />Public <small class="help-block">Repository changes from private to public. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Public) />Public <small class="help-block">Repository changes from private to public. </small> </label>
|
||||||
@@ -57,6 +56,7 @@ name="@(name).@event.name" value="on" @if(events(event)){checked}
|
|||||||
<label class="checkbox"><input type="checkbox" @check("events",IssueComment) />Issue comment <small class="help-block">Issue commented on. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",IssueComment) />Issue comment <small class="help-block">Issue commented on. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Issues) />Issues <small class="help-block">Issue opened, closed<!-- , assigned, or labeled -->. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Issues) />Issues <small class="help-block">Issue opened, closed<!-- , assigned, or labeled -->. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",PullRequest) />Pull Request <small class="help-block">Pull Request opened, closed<!-- , assigned, labeled -->, or synchronized. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",PullRequest) />Pull Request <small class="help-block">Pull Request opened, closed<!-- , assigned, labeled -->, or synchronized. </small> </label>
|
||||||
|
<label class="checkbox"><input type="checkbox" @check("events",PullRequestReviewComment) />Pull Request review comment <small class="help-block">Pull Request diff commented on. </small> </label>
|
||||||
<label class="checkbox"><input type="checkbox" @check("events",Push) />Push <small class="help-block">Git push to a repository. </small> </label>
|
<label class="checkbox"><input type="checkbox" @check("events",Push) />Push <small class="help-block">Git push to a repository. </small> </label>
|
||||||
<hr />
|
<hr />
|
||||||
@if(!create){
|
@if(!create){
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import org.json4s.jackson.JsonMethods.{pretty, parse}
|
|||||||
import org.json4s._
|
import org.json4s._
|
||||||
import org.specs2.matcher._
|
import org.specs2.matcher._
|
||||||
|
|
||||||
import java.util.{Calendar, TimeZone}
|
import java.util.{Calendar, TimeZone, Date}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -17,6 +17,11 @@ class JsonFormatSpec extends Specification {
|
|||||||
d.set(2011,3,14,16,0,49)
|
d.set(2011,3,14,16,0,49)
|
||||||
d.getTime
|
d.getTime
|
||||||
}
|
}
|
||||||
|
def date(date:String):Date = {
|
||||||
|
val f = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||||
|
f.setTimeZone(TimeZone.getTimeZone("UTC"))
|
||||||
|
f.parse(date)
|
||||||
|
}
|
||||||
val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e"
|
val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e"
|
||||||
val repo1Name = RepositoryName("octocat/Hello-World")
|
val repo1Name = RepositoryName("octocat/Hello-World")
|
||||||
implicit val context = JsonFormat.Context("http://gitbucket.exmple.com")
|
implicit val context = JsonFormat.Context("http://gitbucket.exmple.com")
|
||||||
@@ -305,6 +310,50 @@ class JsonFormatSpec extends Specification {
|
|||||||
// "deletions": 3,
|
// "deletions": 3,
|
||||||
// "changed_files": 5
|
// "changed_files": 5
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
|
val apiPullRequestReviewComment = ApiPullRequestReviewComment(
|
||||||
|
id = 29724692,
|
||||||
|
// "diff_hunk": "@@ -1 +1 @@\n-# public-repo",
|
||||||
|
path = "README.md",
|
||||||
|
// "position": 1,
|
||||||
|
// "original_position": 1,
|
||||||
|
commit_id = "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
// "original_commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
user = apiUser,
|
||||||
|
body = "Maybe you should use more emojji on this line.",
|
||||||
|
created_at = date("2015-05-05T23:40:27Z"),
|
||||||
|
updated_at = date("2015-05-05T23:40:27Z")
|
||||||
|
)(RepositoryName("baxterthehacker/public-repo"), 1)
|
||||||
|
val apiPullRequestReviewCommentJson = s"""{
|
||||||
|
"url": "http://gitbucket.exmple.com/api/v3/repos/baxterthehacker/public-repo/pulls/comments/29724692",
|
||||||
|
"id": 29724692,
|
||||||
|
// "diff_hunk": "@@ -1 +1 @@\\n-# public-repo",
|
||||||
|
"path": "README.md",
|
||||||
|
// "position": 1,
|
||||||
|
// "original_position": 1,
|
||||||
|
"commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
// "original_commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
|
||||||
|
"user": $apiUserJson,
|
||||||
|
"body": "Maybe you should use more emojji on this line.",
|
||||||
|
"created_at": "2015-05-05T23:40:27Z",
|
||||||
|
"updated_at": "2015-05-05T23:40:27Z",
|
||||||
|
"html_url": "http://gitbucket.exmple.com/baxterthehacker/public-repo/pull/1#discussion_r29724692",
|
||||||
|
"pull_request_url": "http://gitbucket.exmple.com/api/v3/repos/baxterthehacker/public-repo/pulls/1",
|
||||||
|
"_links": {
|
||||||
|
"self": {
|
||||||
|
"href": "http://gitbucket.exmple.com/api/v3/repos/baxterthehacker/public-repo/pulls/comments/29724692"
|
||||||
|
},
|
||||||
|
"html": {
|
||||||
|
"href": "http://gitbucket.exmple.com/baxterthehacker/public-repo/pull/1#discussion_r29724692"
|
||||||
|
},
|
||||||
|
"pull_request": {
|
||||||
|
"href": "http://gitbucket.exmple.com/api/v3/repos/baxterthehacker/public-repo/pulls/1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def beFormatted(json2Arg:String) = new Matcher[String] {
|
def beFormatted(json2Arg:String) = new Matcher[String] {
|
||||||
def apply[S <: String](e: Expectable[S]) = {
|
def apply[S <: String](e: Expectable[S]) = {
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
@@ -358,5 +407,8 @@ class JsonFormatSpec extends Specification {
|
|||||||
"apiPullRequest" in {
|
"apiPullRequest" in {
|
||||||
JsonFormat(apiPullRequest) must beFormatted(apiPullRequestJson)
|
JsonFormat(apiPullRequest) must beFormatted(apiPullRequestJson)
|
||||||
}
|
}
|
||||||
|
"apiPullRequestReviewComment" in {
|
||||||
|
JsonFormat(apiPullRequestReviewComment) must beFormatted(apiPullRequestReviewCommentJson)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user