Merge branch 'develop'
This commit is contained in:
commit
1c1a106916
|
@ -1,3 +1,6 @@
|
|||
{:production true
|
||||
:port 3000
|
||||
:server-address "http://commiteth.com"}
|
||||
{
|
||||
:production true
|
||||
:port 3000
|
||||
:nrepl-port 7000
|
||||
:server-address "https://commiteth.com"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
{:test true
|
||||
:port 3001
|
||||
;; when :nrepl-port is set the application starts the nREPL server on load
|
||||
:nrepl-port 7001
|
||||
:jdbc-database-url "jdbc:postgresql://localhost/commiteth?user=commiteth&password=commiteth"
|
||||
:server-address "http://localhost:3000"}
|
||||
{
|
||||
:test true
|
||||
:jdbc-database-url "jdbc:postgresql://localhost/commiteth_test?user=commiteth&password=commiteth"
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
:target-path "target/%s/"
|
||||
:main commiteth.core
|
||||
:migratus {:store :database
|
||||
:migration-dir "resources/migrations"
|
||||
:migration-dir "migrations"
|
||||
:db ~(get (System/getenv) "DATABASE_URL")}
|
||||
|
||||
:plugins [[lein-cprop "1.0.1"]
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE public.users ALTER COLUMN created SET DATA TYPE timestamp without time zone using date('20170120') + created;
|
||||
ALTER TABLE public.repositories ALTER COLUMN updated SET DATA TYPE timestamp without time zone using date('20170120') + updated;
|
|
@ -0,0 +1,46 @@
|
|||
(ns commiteth.bounties
|
||||
(:require [commiteth.db.issues :as issues]
|
||||
[commiteth.db.users :as users]
|
||||
[commiteth.db.repositories :as repos]
|
||||
[commiteth.eth.core :as eth]
|
||||
[commiteth.github.core :as github]
|
||||
[commiteth.eth.core :as eth]
|
||||
[clojure.tools.logging :as log]))
|
||||
|
||||
|
||||
(def ^:const label-name "bounty")
|
||||
|
||||
(defn has-bounty-label?
|
||||
[issue]
|
||||
(let [labels (:labels issue)]
|
||||
(some #(= label-name (:name %)) labels)))
|
||||
|
||||
|
||||
(defn add-bounty-for-issue [repo-map issue]
|
||||
(log/debug "add-bounty-for-issue" issue)
|
||||
(let [{issue-id :id
|
||||
issue-number :number
|
||||
issue-title :title} issue
|
||||
{repo :repo
|
||||
repo-id :repo_id
|
||||
user :login} repo-map
|
||||
created-issue (issues/create repo-id issue-id issue-number issue-title)
|
||||
repo-owner (:address (users/get-repo-owner repo-id))]
|
||||
(log/info (format "Issue %s/%s/%s labeled as bounty" user repo issue-number))
|
||||
(if (= 1 created-issue)
|
||||
(let [transaction-hash (eth/deploy-contract repo-owner)]
|
||||
(log/info "Contract deployed, transaction-hash:" transaction-hash )
|
||||
(issues/update-transaction-hash issue-id transaction-hash))
|
||||
(log/debug "Issue already exists in DB, ignoring"))))
|
||||
|
||||
|
||||
(defn add-bounties-for-existing-issues [repo-map]
|
||||
(let [{repo :repo
|
||||
user :login} repo-map
|
||||
issues (github/get-issues user repo)
|
||||
bounty-issues (filter has-bounty-label? issues)]
|
||||
(log/debug bounty-issues)
|
||||
(log/debug "adding bounties for"
|
||||
(count bounty-issues) " existing issues")
|
||||
(doall
|
||||
(map (partial add-bounty-for-issue repo-map) bounty-issues))))
|
|
@ -10,7 +10,7 @@
|
|||
[mount.core :as mount])
|
||||
(:gen-class))
|
||||
|
||||
(def cli-options
|
||||
(def ^:const cli-options
|
||||
[["-p" "--port PORT" "Port number"
|
||||
:parse-fn #(Integer/parseInt %)]])
|
||||
|
||||
|
@ -58,4 +58,3 @@ repl-server
|
|||
(System/exit 0))
|
||||
:else
|
||||
(start-app args)))
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
[clojure.java.jdbc :as jdbc]
|
||||
[conman.core :as conman]
|
||||
[commiteth.config :refer [env]]
|
||||
[mount.core :refer [defstate]])
|
||||
[mount.core :refer [defstate]]
|
||||
[migratus.core :as migratus])
|
||||
(:import org.postgresql.util.PGobject
|
||||
java.sql.Array
|
||||
clojure.lang.IPersistentMap
|
||||
|
@ -15,8 +16,18 @@
|
|||
Timestamp
|
||||
PreparedStatement]))
|
||||
|
||||
|
||||
(defn start []
|
||||
(let [db (env :jdbc-database-url)
|
||||
migratus-config {:store :database
|
||||
:migration-dir "migrations/"
|
||||
:migration-table-name "schema_migrations"
|
||||
:db db}]
|
||||
(migratus/migrate migratus-config)
|
||||
(conman/connect! {:jdbc-url db})))
|
||||
|
||||
(defstate ^:dynamic *db*
|
||||
:start (conman/connect! {:jdbc-url (env :jdbc-database-url)})
|
||||
:start (start)
|
||||
:stop (conman/disconnect! *db*))
|
||||
|
||||
(conman/bind-connection *db* "sql/queries.sql")
|
||||
|
|
|
@ -108,12 +108,12 @@
|
|||
(repos/delete-hook user repo hook-id (auth-params token))))
|
||||
|
||||
(defn github-comment-hash
|
||||
[user repo issue-number balance]
|
||||
(digest/sha-256 (str "SALT_Yoh2looghie9jishah7aiphahphoo6udiju" user repo issue-number balance)))
|
||||
[user repo issue-number]
|
||||
(digest/sha-256 (str "SALT_Yoh2looghie9jishah7aiphahphoo6udiju" user repo issue-number)))
|
||||
|
||||
(defn- get-qr-url
|
||||
[user repo issue-number balance]
|
||||
(let [hash (github-comment-hash user repo issue-number balance)]
|
||||
[user repo issue-number]
|
||||
(let [hash (github-comment-hash user repo issue-number)]
|
||||
(str (server-address) (format "/qr/%s/%s/bounty/%s/%s/qr.png" user repo issue-number hash))))
|
||||
|
||||
(defn- md-url
|
||||
|
@ -127,15 +127,16 @@
|
|||
(str "!" (md-url alt src)))
|
||||
|
||||
(defn generate-comment
|
||||
[user repo issue-number balance]
|
||||
(let [image-url (md-image "QR Code" (get-qr-url user repo issue-number balance))
|
||||
[user repo issue-number contract-address balance]
|
||||
(let [image-url (md-image "QR Code" (get-qr-url user repo issue-number))
|
||||
balance (str balance " ETH")
|
||||
site-url (md-url (server-address) (server-address))]
|
||||
(format "Current balance: %s\n%s\n%s" balance image-url site-url)))
|
||||
(format "Current balance: %s\nContract address: %s\n%s\n%s"
|
||||
balance contract-address image-url site-url)))
|
||||
|
||||
(defn post-comment
|
||||
[user repo issue-number balance]
|
||||
(let [comment (generate-comment user repo issue-number balance)]
|
||||
[user repo issue-number contract-address balance]
|
||||
(let [comment (generate-comment user repo issue-number contract-address balance)]
|
||||
(log/debug "Posting comment to" (str user "/" repo "/" issue-number) ":" comment)
|
||||
(issues/create-comment user repo issue-number comment (self-auth-params))))
|
||||
|
||||
|
@ -158,9 +159,10 @@
|
|||
(assoc req :body (json/generate-string (or raw-query proper-query)))))
|
||||
|
||||
(defn update-comment
|
||||
[user repo comment-id issue-number balance]
|
||||
(let [comment (generate-comment user repo issue-number balance)]
|
||||
(log/debug (str "Updating " user "/" repo "/" issue-number " comment #" comment-id " with contents: " comment))
|
||||
[user repo comment-id issue-number contract-address balance]
|
||||
(let [comment (generate-comment user repo issue-number contract-address balance)]
|
||||
(log/debug (str "Updating " user "/" repo "/" issue-number
|
||||
" comment #" comment-id " with contents: " comment))
|
||||
(let [req (make-patch-request "repos/%s/%s/issues/comments/%s"
|
||||
[user repo comment-id]
|
||||
(assoc (self-auth-params) :body comment))]
|
||||
|
@ -170,6 +172,11 @@
|
|||
[user repo issue-number]
|
||||
(issues/specific-issue user repo issue-number (self-auth-params)))
|
||||
|
||||
(defn get-issues
|
||||
[user repo]
|
||||
(issues/issues user repo))
|
||||
|
||||
|
||||
(defn get-issue-events
|
||||
[user repo issue-id]
|
||||
(issues/issue-events user repo issue-id (self-auth-params)))
|
||||
|
@ -178,4 +185,4 @@
|
|||
[full-repo token]
|
||||
(let [[user repo] (str/split full-repo #"/")]
|
||||
(log/debug "creating bounty label" (str user "/" repo) token)
|
||||
(issues/create-label user repo "bounty" "00ff00" (auth-params token))))
|
||||
(issues/create-label user repo "bounty" "fafad2" (auth-params token))))
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
(context "/qr" []
|
||||
;; user may be an organization here
|
||||
(GET "/:user/:repo/bounty/:issue{[0-9]{1,9}}/:hash/qr.png" [user repo issue hash]
|
||||
(log/debug "qr PNG GET")
|
||||
(log/debug "qr PNG GET" user repo issue hash)
|
||||
(let [{address :contract_address
|
||||
login :login
|
||||
repo :repo
|
||||
|
@ -45,8 +45,11 @@
|
|||
(log/debug "address:" address "balance:" balance)
|
||||
|
||||
(if (and address
|
||||
(= hash (github/github-comment-hash user repo issue balance)))
|
||||
(let [issue-url (str login "/" repo "/issues/" issue-number)]
|
||||
(log/debug "balance:" address)
|
||||
(ok (generate-image address balance issue-url 768 256)))
|
||||
(= hash (github/github-comment-hash user repo issue)))
|
||||
(let [issue-url (str login "/" repo "/issues/" issue-number)
|
||||
image-url (generate-image address balance issue-url 768 256)
|
||||
response (assoc-in (ok image-url)
|
||||
[:headers "cache-control"] "no-cache")]
|
||||
(log/debug "balance:" address "response" response)
|
||||
response)
|
||||
(bad-request))))))
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
[buddy.auth :refer [authenticated?]]
|
||||
[commiteth.db.users :as users]
|
||||
[commiteth.db.repositories :as repositories]
|
||||
[commiteth.db.bounties :as bounties]
|
||||
[commiteth.db.bounties :as bounties-db]
|
||||
[commiteth.bounties :as bounties]
|
||||
[commiteth.github.core :as github]
|
||||
[clojure.tools.logging :as log]
|
||||
[commiteth.eth.core :as eth]))
|
||||
|
@ -56,13 +57,15 @@
|
|||
:current-user user
|
||||
(ok (repositories/get-enabled (:id user))))
|
||||
(GET "/bounties" []
|
||||
(ok (bounties/list-all-bounties)))
|
||||
(ok (bounties-db/list-all-bounties)))
|
||||
(POST "/bounty/:issue{[0-9]{1,9}}/payout" {:keys [params]}
|
||||
:auth-rules authenticated?
|
||||
:current-user user
|
||||
(let [{issue :issue
|
||||
payout-hash :payout-hash} params
|
||||
result (bounties/update-payout-hash (Integer/parseInt issue) payout-hash)]
|
||||
result (bounties-db/update-payout-hash
|
||||
(Integer/parseInt issue)
|
||||
payout-hash)]
|
||||
(if (= 1 result)
|
||||
(ok)
|
||||
(internal-server-error))))
|
||||
|
@ -72,7 +75,7 @@
|
|||
(ok (map #(conj % (let [balance (:balance %)]
|
||||
{:balance-eth (eth/hex->eth balance 6)
|
||||
:balance-wei (eth/hex->big-integer balance)}))
|
||||
(bounties/list-owner-bounties (:id user)))))
|
||||
(bounties-db/list-owner-bounties (:id user)))))
|
||||
(POST "/repository/toggle" {:keys [params]}
|
||||
:auth-rules authenticated?
|
||||
:current-user user
|
||||
|
@ -85,10 +88,11 @@
|
|||
(repositories/create (merge params {:user_id user-id}))
|
||||
(repositories/toggle repo-id))]
|
||||
(if (:enabled result)
|
||||
;; @todo: do we really want to make this call at this moment?
|
||||
(let [created-hook (github/add-webhook repo token)]
|
||||
(log/debug "Created webhook:" created-hook)
|
||||
(github/create-label repo token)
|
||||
(repositories/update-hook-id repo-id (:id created-hook)))
|
||||
(future
|
||||
(github/create-label repo token)
|
||||
(repositories/update-hook-id repo-id (:id created-hook))
|
||||
(bounties/add-bounties-for-existing-issues result)))
|
||||
(github/remove-webhook repo (:hook_id result) token))
|
||||
result)))))
|
||||
|
|
|
@ -4,44 +4,48 @@
|
|||
[commiteth.db.pull-requests :as pull-requests]
|
||||
[commiteth.db.issues :as issues]
|
||||
[commiteth.db.users :as users]
|
||||
[commiteth.eth.core :as eth]
|
||||
[commiteth.bounties :as bounties]
|
||||
[ring.util.http-response :refer [ok]]
|
||||
[clojure.string :refer [join]]
|
||||
[clojure.tools.logging :as log])
|
||||
(:import [java.lang Integer]))
|
||||
|
||||
(def label-name "bounty")
|
||||
|
||||
(defn find-issue-event
|
||||
[events type owner]
|
||||
(first (filter #(and
|
||||
(= owner (get-in % [:actor :login]))
|
||||
(= type (:event %)))
|
||||
events)))
|
||||
events)))
|
||||
|
||||
|
||||
(defn labeled-as-bounty?
|
||||
[action issue]
|
||||
(and
|
||||
(= "labeled" action)
|
||||
(= bounties/label-name (get-in issue [:label :name]))))
|
||||
|
||||
(defn find-commit-id
|
||||
[user repo issue-number event-types]
|
||||
(log/debug "find-commit-id" user repo issue-number event-types)
|
||||
(some identity (map #(->
|
||||
(github/get-issue-events user repo issue-number)
|
||||
(find-issue-event % user)
|
||||
:commit_id)
|
||||
event-types)))
|
||||
event-types)))
|
||||
|
||||
|
||||
(defn handle-issue-labeled
|
||||
[issue]
|
||||
(let [{repo-id :id
|
||||
repo :name
|
||||
{user :login} :owner} (:repository issue)
|
||||
{issue-id :id
|
||||
issue-number :number
|
||||
issue-title :title} (:issue issue)
|
||||
created-issue (issues/create repo-id issue-id issue-number issue-title)
|
||||
repo-owner (:address (users/get-repo-owner repo-id))]
|
||||
(log/debug (format "Issue %s/%s/%s labeled as bounty" user repo issue-number))
|
||||
(when (= 1 created-issue)
|
||||
(issues/update-transaction-hash issue-id (eth/deploy-contract repo-owner)))))
|
||||
[webhook-payload]
|
||||
(let [{issue :issue} webhook-payload
|
||||
{repo-id :id
|
||||
repo-name :name
|
||||
{login :login} :owner} (:repository webhook-payload)
|
||||
repo-map {:repo repo-name :login login :repo_id repo-id}]
|
||||
(bounties/add-bounty-for-issue repo-map issue)))
|
||||
|
||||
(defn handle-issue-closed
|
||||
;; TODO: does not work in case the issue is closed on github web ui
|
||||
[{{{user :login} :owner repo :name} :repository
|
||||
{issue-id :id issue-number :number} :issue}]
|
||||
(future
|
||||
|
@ -49,7 +53,7 @@
|
|||
(log/debug (format "Issue %s/%s/%s closed with commit %s" user repo issue-number commit-id))
|
||||
(issues/close commit-id issue-id))))
|
||||
|
||||
(def keywords
|
||||
(def ^:const keywords
|
||||
[#"(?i)close\s+#(\d+)"
|
||||
#"(?i)closes\s+#(\d+)"
|
||||
#"(?i)closed\s+#(\d+)"
|
||||
|
@ -70,16 +74,12 @@
|
|||
(catch NumberFormatException _)))
|
||||
(re-seq % pr-body)) keywords))
|
||||
|
||||
(defn has-bounty-label?
|
||||
[issue]
|
||||
(let [labels (:labels issue)]
|
||||
(some #(= label-name (:name %)) labels)))
|
||||
|
||||
(defn validate-issue-number
|
||||
"Checks if an issue has a bounty label attached and returns its number"
|
||||
[user repo issue-number]
|
||||
(when-let [issue (github/get-issue user repo issue-number)]
|
||||
(when (has-bounty-label? issue)
|
||||
(when (bounties/has-bounty-label? issue)
|
||||
issue-number)))
|
||||
|
||||
(defn handle-pull-request-closed
|
||||
|
@ -92,40 +92,38 @@
|
|||
id :id
|
||||
pr-number :number
|
||||
pr-body :body} :pull_request}]
|
||||
(log/debug "handle-pull-request-closed" owner repo repo-id login pr-body)
|
||||
(future
|
||||
(let [commit-id (find-commit-id owner repo pr-number ["merged"])
|
||||
issue-number (->>
|
||||
(extract-issue-number pr-body)
|
||||
(first)
|
||||
(validate-issue-number owner repo))
|
||||
(extract-issue-number pr-body)
|
||||
(first)
|
||||
(validate-issue-number owner repo))
|
||||
m {:commit_id commit-id :issue_number issue-number}]
|
||||
(log/debug "handle-pull-request-closed" commit-id issue-number)
|
||||
(when (or commit-id issue-number)
|
||||
(log/debug (format "Pull request %s/%s/%s closed with reference to %s"
|
||||
login repo pr-number
|
||||
(if commit-id (str "commit-id " commit-id)
|
||||
(str "issue-number " issue-number))))
|
||||
login repo pr-number
|
||||
(if commit-id (str "commit-id " commit-id)
|
||||
(str "issue-number " issue-number))))
|
||||
(pull-requests/create (merge m {:repo_id repo-id
|
||||
:pr_id id
|
||||
:pr_number pr-number
|
||||
:user_id user-id}))
|
||||
(users/create-user user-id login name nil nil)))))
|
||||
|
||||
(defn labeled-as-bounty?
|
||||
[action issue]
|
||||
(and
|
||||
(= "labeled" action)
|
||||
(= label-name (get-in issue [:label :name]))))
|
||||
|
||||
(defn handle-issue
|
||||
[issue]
|
||||
(when-let [action (:action issue)]
|
||||
(when (labeled-as-bounty? action issue)
|
||||
(handle-issue-labeled issue))
|
||||
[webhook-payload]
|
||||
(when-let [action (:action webhook-payload)]
|
||||
(log/debug "handle-issue")
|
||||
(when (labeled-as-bounty? action webhook-payload)
|
||||
(handle-issue-labeled webhook-payload))
|
||||
(when (and
|
||||
(= "closed" action)
|
||||
(has-bounty-label? (:issue issue)))
|
||||
(handle-issue-closed issue)))
|
||||
(ok (str issue)))
|
||||
(= "closed" action)
|
||||
(bounties/has-bounty-label? (:issue webhook-payload)))
|
||||
(handle-issue-closed webhook-payload)))
|
||||
(ok (str webhook-payload)))
|
||||
|
||||
(defn handle-pull-request
|
||||
[pull-request]
|
||||
|
@ -135,7 +133,7 @@
|
|||
|
||||
(defroutes webhook-routes
|
||||
(POST "/webhook" {:keys [params headers]}
|
||||
(case (get headers "x-github-event")
|
||||
"issues" (handle-issue params)
|
||||
"pull_request" (handle-pull-request params)
|
||||
(ok))))
|
||||
(case (get headers "x-github-event")
|
||||
"issues" (handle-issue params)
|
||||
"pull_request" (handle-pull-request params)
|
||||
(ok))))
|
||||
|
|
|
@ -24,7 +24,11 @@
|
|||
repo :repo
|
||||
issue-number :issue_number} issue
|
||||
balance (eth/get-balance-eth contract-address 4)
|
||||
{comment-id :id} (github/post-comment user repo issue-number balance)]
|
||||
{comment-id :id} (github/post-comment user
|
||||
repo
|
||||
issue-number
|
||||
contract-address
|
||||
balance)]
|
||||
(issues/update-comment-id issue-id comment-id))))))
|
||||
|
||||
(defn self-sign-bounty
|
||||
|
@ -72,7 +76,12 @@
|
|||
current-balance-eth (eth/hex->eth current-balance-hex 8)]
|
||||
(when-not (= old-balance current-balance-hex)
|
||||
(issues/update-balance contract-address current-balance-hex)
|
||||
(github/update-comment login repo comment-id issue-number current-balance-eth))))))
|
||||
(github/update-comment login
|
||||
repo
|
||||
comment-id
|
||||
issue-number
|
||||
contract-address
|
||||
current-balance-eth))))))
|
||||
|
||||
(def scheduler-thread-name "SCHEDULER_THREAD")
|
||||
|
||||
|
|
Loading…
Reference in New Issue