Jihwan Chun 2015-06-11
Refactored webhook's post-receive event to send right data when push.
@03f0efda614c23e909572611fea887522585d4c6
app/models/NotificationEvent.java
--- app/models/NotificationEvent.java
+++ app/models/NotificationEvent.java
@@ -28,6 +28,7 @@
 import models.resource.GlobalResource;
 import models.resource.Resource;
 import models.resource.ResourceConvertible;
+import models.Webhook;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Predicate;
 import org.apache.commons.lang3.StringUtils;
@@ -863,6 +864,13 @@
         notiEvent.resourceType = project.asResource().getType();
         notiEvent.resourceId = project.asResource().getId();
         NotificationEvent.add(notiEvent);
+
+        List<Webhook> webhookList = Webhook.findByProject(project.id);
+        for (Webhook webhook : webhookList) {
+            // Send push event via webhook payload URLs.
+            String[] eventTypes = {"push"};
+            webhook.sendRequestToPayloadUrl(eventTypes, commits, refNames, sender, title);
+        }
     }
 
     public static NotificationEvent afterReviewed(PullRequest pullRequest, PullRequestReviewAction reviewAction) {
app/models/Webhook.java
--- app/models/Webhook.java
+++ app/models/Webhook.java
@@ -46,6 +46,11 @@
 import java.lang.Object;
 import java.text.SimpleDateFormat;
 
+import playRepository.GitCommit;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import utils.RouteUtil;
+
 /**
  * A webhook to be sent by events in project
  */
@@ -148,8 +153,8 @@
                 .findUnique();
     }
     
-    public void sendRequestToPayloadUrl(String[] eventTypes) {
-        String requestBodyString = buildRequestBody(eventTypes);
+    public void sendRequestToPayloadUrl(String[] eventTypes, List<RevCommit> commits, List<String> refNames, User sender, String title) {
+        String requestBodyString = buildRequestBody(eventTypes, commits, refNames, sender, title);
 
         try {
             WSRequestHolder requestHolder = WS.url(this.payloadUrl);
@@ -176,44 +181,76 @@
         }
     }
 
-    private String buildRequestBody(String[] eventTypes) {
+    private String buildRequestBody(String[] eventTypes, List<RevCommit> commits, List<String> refNames, User sender, String title) {
         ObjectNode requestBody = Json.newObject();
-        ObjectNode configJSON = Json.newObject();
-        ObjectNode hookInfoJSON = Json.newObject();
+        ObjectNode senderJSON = Json.newObject();
+        ObjectNode pusherJSON = Json.newObject();
         ObjectNode repositoryJSON = Json.newObject();
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode eventTypesArray = mapper.createArrayNode();
+        ArrayNode refNamesArray = mapper.createArrayNode();
+        ArrayNode commitsArray = mapper.createArrayNode();
 
-        requestBody.put("hook_id", this.id);
-
-        configJSON.put("url", this.payloadUrl);
-        configJSON.put("content_type", "json");
-        configJSON.put("secret", this.secret);
-
-        hookInfoJSON.put("id", this.id);
-        hookInfoJSON.put("name", "web");
-        hookInfoJSON.put("active", true);
-        for (String eventType : eventTypes) {
-            eventTypesArray.add(eventType);
+        for (String refName : refNames) {
+            refNamesArray.add(refName);
         }
-        hookInfoJSON.put("events", eventTypesArray);
-        hookInfoJSON.put("config", configJSON);
-        hookInfoJSON.put("created_at", new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'").format(this.createdAt));
-        // TODO: put updated_at property when we support editing webhook.
+        requestBody.put("ref", refNamesArray);
 
-        requestBody.put("hook", hookInfoJSON);
+        for (RevCommit commit : commits) {
+            commitsArray.add(buildJSONFromCommit(project, commit));
+        }
+        requestBody.put("commits", commitsArray);
+        requestBody.put("head_commit", commitsArray.get(0));
+
+        senderJSON.put("login", sender.loginId);
+        senderJSON.put("id", sender.id);
+        senderJSON.put("avatar_url", sender.avatarUrl());
+        senderJSON.put("type", "User");
+        senderJSON.put("site_admin", sender.isSiteManager());
+        requestBody.put("sender", senderJSON);
+
+        pusherJSON.put("name", sender.name);
+        pusherJSON.put("email", sender.email);
+        requestBody.put("pusher", pusherJSON);
 
         repositoryJSON.put("id", project.id);
         repositoryJSON.put("name", project.name);
         repositoryJSON.put("owner", project.owner);
-        repositoryJSON.put("html_url", project.siteurl);
-        repositoryJSON.put("overview", project.overview);
-
+        repositoryJSON.put("html_url", RouteUtil.getUrl(project));
+        repositoryJSON.put("overview", project.overview);   // Description.
+        repositoryJSON.put("private", project.isPrivate());
         requestBody.put("repository", repositoryJSON);
 
         return Json.stringify(requestBody);
     }
 
+    private ObjectNode buildJSONFromCommit(Project project, RevCommit commit) {
+        GitCommit gitCommit = new GitCommit(commit);
+        ObjectNode commitJSON = Json.newObject();
+        ObjectNode authorJSON = Json.newObject();
+        ObjectNode committerJSON = Json.newObject();
+
+        commitJSON.put("id", gitCommit.getFullId());
+        commitJSON.put("message", gitCommit.getMessage());
+        commitJSON.put("timestamp",
+                new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").
+                        format(new Date(gitCommit.getCommitTime() * 1000L)));
+        commitJSON.put("url", project.siteurl+"/commit/"+gitCommit.getFullId());
+
+        authorJSON.put("name", gitCommit.getAuthorName());
+        authorJSON.put("email", gitCommit.getAuthorEmail());
+        committerJSON.put("name", gitCommit.getCommitterName());
+        committerJSON.put("email", gitCommit.getCommitterEmail());
+        // TODO : Add 'username' property (howto?)
+
+        commitJSON.put("author", authorJSON);
+        commitJSON.put("committer", committerJSON);
+
+        // TODO : Add added, removed, modified file list (not supported by JGit?)
+
+        return commitJSON;
+    }
+
     /**
      * Remove this webhook from a project.
      *
app/playRepository/GitCommit.java
--- app/playRepository/GitCommit.java
+++ app/playRepository/GitCommit.java
@@ -174,6 +174,10 @@
         return revCommit.abbreviate(7).name();
     }
 
+    public String getFullId() {
+        return revCommit.name();
+    }
+
     // Imported from
     // https://github.com/eclipse/jgit/blob/v3.0.0.201305080800-m7/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
     // and modified by Yi EungJun
app/playRepository/RepositoryService.java
--- app/playRepository/RepositoryService.java
+++ app/playRepository/RepositoryService.java
@@ -271,7 +271,6 @@
         hooks.add(new IssueReferredFromCommitEvent(project, currentUser));
         hooks.add(new PullRequestCheck(currentUser, request, project));
         hooks.add(new NotifyPushedCommits(project, currentUser));
-        hooks.add(new RequestByWebhooks(project, currentUser));
         return PostReceiveHookChain.newChain(hooks);
     }
 
 
app/playRepository/hooks/RequestByWebhooks.java (deleted)
--- app/playRepository/hooks/RequestByWebhooks.java
@@ -1,54 +0,0 @@
-/**
- * Yobi, Project Hosting SW
- *
- * Copyright 2015 NAVER Corp.
- * http://yobi.io
- *
- * @author Jihwan Chun
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package playRepository.hooks;
-
-import java.util.Collection;
-
-import models.PostReceiveMessage;
-import models.Project;
-import models.User;
-import models.Webhook;
-
-import org.eclipse.jgit.transport.PostReceiveHook;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.transport.ReceivePack;
-
-import java.util.List;
-
-public class RequestByWebhooks implements PostReceiveHook {
-    private Project project;
-    private User user;
-
-    public RequestByWebhooks(Project project, User user) {
-        this.project = project;
-        this.user = user;
-    }
-
-    @Override
-    public void onPostReceive(ReceivePack receivePack, Collection<ReceiveCommand> commands) {
-        List<Webhook> webhookList = Webhook.findByProject(project.id);
-        for (Webhook webhook : webhookList) {
-            // TODO : When we support more event types, we should get event type list from webhook object
-            String[] eventTypes = {"push"};
-            webhook.sendRequestToPayloadUrl(eventTypes);
-        }
-    }
-}
Add a comment
List