Handle issue labeling via github webhooks

This commit is contained in:
kagel 2016-08-26 04:10:05 +03:00
parent 656f7ce84a
commit a6459a2a32
9 changed files with 98 additions and 5 deletions

View File

@ -22,6 +22,7 @@
[org.webjars.bower/tether "1.3.3"]
[org.clojure/tools.logging "0.3.1"]
[compojure "1.5.1"]
[ring/ring-json "0.4.0"]
[ring-webjars "0.1.1"]
[ring/ring-defaults "0.2.1"]
[mount "0.1.10"]

View File

@ -1,2 +1,3 @@
DROP TABLE users;
DROP TABLE repositories;
DROP TABLE issues;

View File

@ -21,3 +21,11 @@ CREATE UNIQUE INDEX repositories_user_repo_pk ON repositories (login, repo);
CREATE UNIQUE INDEX repositories_repo_id_pk ON repositories (repo_id);
CREATE INDEX repositories_login_repo_index ON repositories (login, repo);
CREATE INDEX repositories_repo_id_index ON repositories (repo_id);
CREATE TABLE issues
(
repo_id INTEGER NOT NULL,
issue_id INTEGER NOT NULL,
address VARCHAR(42),
CONSTRAINT issues_repo_id_issue_id_pk PRIMARY KEY (repo_id, issue_id)
);

View File

@ -37,7 +37,7 @@ WHERE login = :login;
UPDATE repositories
SET enabled = NOT enabled
WHERE repo_id = :repo_id
RETURNING repo_id, login, repo, enabled;
RETURNING repo_id, login, repo, enabled, hook_id;
-- :name create-repository! :<! :1
-- :doc creates repository if not exists
@ -56,4 +56,10 @@ RETURNING repo_id, login, repo, enabled;
-- :doc returns enabled repositories for a given login
SELECT repo_id
FROM repositories
WHERE login = :login AND enabled = TRUE
WHERE login = :login AND enabled = TRUE;
-- :name update-hook-id :! :n
-- :doc updates hook_id of a specified repository
UPDATE repositories
SET hook_id = :hook_id
WHERE repo_id = :repo_id;

View File

@ -24,3 +24,9 @@
(jdbc/with-db-connection [con-db *db*]
(db/get-enabled-repositories con-db {:login login}))
(mapcat vals)))
(defn update-hook-id
"Updates github webhook id for a given repository"
[repo-id hook-id]
(jdbc/with-db-connection [con-db *db*]
(db/update-hook-id con-db {:repo_id repo-id :hook_id hook-id})))

View File

@ -1,6 +1,8 @@
(ns commiteth.github.core
(:require [tentacles.repos :as repos]
[tentacles.users :as users]
[tentacles.repos :as repos]
[tentacles.issues :as issues]
[ring.util.codec :as codec]
[clj-http.client :as http])
(:import [java.util UUID]))
@ -9,10 +11,16 @@
(def client-secret "e8e7a088e7769c77e9e2d87c47ef81df51080bf3")
(def redirect-uri "http://localhost:3000/callback")
(def allow-signup true)
(def hook-secret "Mu0eiV8ooy7IogheexathocaiSeLeineiLue0au8")
;; @todo: github user which will post QR codes (already banned)
(def self "h0gL")
(def self-password "Fahh7ithoh8Ahghe")
(defn authorize-url []
(let [params (codec/form-encode {:client_id client-id
:redirect_uri redirect-uri
:scope "admin:repo_hook"
:allow_signup allow-signup
:state (str (UUID/randomUUID))})]
(str "https://github.com/login/oauth/authorize" "?" params)))
@ -63,3 +71,25 @@
(defn get-user
[token]
(users/me (auth-params token)))
(defn add-webhook
[token user repo]
(println "adding webhook")
(repos/create-hook user repo "web"
{:url "http://localhost:3000/webhook"
:content_type "json"}
(merge (auth-params token)
{:events ["issues", "issue_comment", "pull_request"]
:active true})))
(defn remove-webhook
[token user repo hook-id]
(println "removing webhook")
(println token user repo hook-id)
(repos/delete-hook user repo hook-id (auth-params token)))
(defn post-comment
[user repo issue-id]
(issues/create-comment user repo issue-id
"a comment with an image link to the web service"
{:auth (str self ":" self-password)}))

View File

@ -4,7 +4,10 @@
[commiteth.routes.home :refer [home-routes]]
[commiteth.routes.redirect :refer [redirect-routes]]
[commiteth.routes.services :refer [service-routes]]
[commiteth.routes.webhooks :refer [webhook-routes]]
[compojure.route :as route]
[ring.middleware.json :refer [wrap-json-params]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[commiteth.env :refer [defaults]]
[mount.core :as mount]
[commiteth.middleware :as middleware]))
@ -19,6 +22,9 @@
(wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats))
#'redirect-routes
(-> #'webhook-routes
(wrap-routes wrap-json-params)
(wrap-routes wrap-keyword-params))
#'service-routes
(route/not-found
(:body

View File

@ -55,6 +55,17 @@
(POST "/repository/toggle" {:keys [params]}
:auth-rules authenticated?
:current-user user
(ok (or
(repositories/create params)
(repositories/toggle (:id params)))))))
(ok (let [repo-id (:id params)
result (or
(repositories/create params)
(repositories/toggle repo-id))
token (:token user)
login (:login user)
repo (:name params)]
(if (:enabled result)
;; @todo: do we really want to make this call at this moment?
(let [created-hook (github/add-webhook token login repo)]
(println created-hook)
(repositories/update-hook-id repo-id (:id created-hook)))
(github/remove-webhook token login repo (:hook_id result)))
result)))))

View File

@ -0,0 +1,24 @@
(ns commiteth.routes.webhooks
(:require [compojure.core :refer [defroutes POST]]
[commiteth.github.core :as github]
[ring.util.http-response :refer [ok]]))
(def label-name "bounty")
(defn handle-issue
[issue]
(when-let [action (:action issue)]
(when (and
(= "labeled" action)
(= label-name (get-in issue [:label :name])))
(github/post-comment
(get-in issue [:repository :owner :login])
(get-in issue [:repository :name])
(get-in issue [:issue :number]))))
(ok (str issue)))
(defroutes webhook-routes
(POST "/webhook" {:keys [params headers]}
(case (get headers "x-github-event")
"issues" (handle-issue params)
(ok))))