Merge branch 'develop' into fix/reduce-confirm-wait-time-353
This commit is contained in:
commit
8c550a4b64
|
@ -5,7 +5,7 @@
|
||||||
:exclusions [joda-time]]
|
:exclusions [joda-time]]
|
||||||
[re-frame "0.10.2"]
|
[re-frame "0.10.2"]
|
||||||
[cljs-ajax "0.7.2"]
|
[cljs-ajax "0.7.2"]
|
||||||
[secretary "1.2.3"]
|
[funcool/bide "1.6.0"]
|
||||||
[reagent-utils "0.2.1"]
|
[reagent-utils "0.2.1"]
|
||||||
[reagent "0.7.0"]
|
[reagent "0.7.0"]
|
||||||
[org.clojure/clojurescript "1.9.946"]
|
[org.clojure/clojurescript "1.9.946"]
|
||||||
|
|
|
@ -102,19 +102,16 @@ WHERE i.repo_id = :repo_id
|
||||||
AND i.confirm_hash is null
|
AND i.confirm_hash is null
|
||||||
AND i.is_open = true;
|
AND i.is_open = true;
|
||||||
|
|
||||||
-- :name update-repo-generic :! :n
|
-- :name update-repo-name :! :n
|
||||||
/* :require [clojure.string :as string]
|
|
||||||
[hugsql.parameters :refer [identifier-param-quote]] */
|
|
||||||
UPDATE repositories
|
UPDATE repositories
|
||||||
SET
|
SET repo = :repo_name
|
||||||
/*~
|
WHERE repo_id = :repo_id
|
||||||
(string/join ","
|
AND repo != :repo_name
|
||||||
(for [[field _] (:updates params)]
|
|
||||||
(str (identifier-param-quote (name field) options)
|
|
||||||
" = :v:updates." (name field))))
|
|
||||||
~*/
|
|
||||||
where repo_id = :repo_id;
|
|
||||||
|
|
||||||
|
-- :name update-repo-state :! :n
|
||||||
|
UPDATE repositories
|
||||||
|
SET state = :repo_state
|
||||||
|
WHERE repo_id = :repo_id
|
||||||
|
|
||||||
|
|
||||||
-- Issues --------------------------------------------------------------------------
|
-- Issues --------------------------------------------------------------------------
|
||||||
|
@ -412,6 +409,14 @@ SELECT exists(SELECT 1
|
||||||
FROM issues
|
FROM issues
|
||||||
WHERE issue_id = :issue_id);
|
WHERE issue_id = :issue_id);
|
||||||
|
|
||||||
|
-- :name get-issue :? :1
|
||||||
|
-- :doc get issue from DB by repo-id and issue-number
|
||||||
|
SELECT issue_id, issue_number, is_open, winner_login, commit_sha
|
||||||
|
FROM issues
|
||||||
|
WHERE repo_id = :repo_id
|
||||||
|
AND issue_number = :issue_number;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- :name open-bounties :? :*
|
-- :name open-bounties :? :*
|
||||||
-- :doc all open bounty issues
|
-- :doc all open bounty issues
|
||||||
|
|
|
@ -65,6 +65,7 @@ height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||||
src="https://www.facebook.com/tr?id=293089407869419&ev=PageView&noscript=1"
|
src="https://www.facebook.com/tr?id=293089407869419&ev=PageView&noscript=1"
|
||||||
/></noscript>
|
/></noscript>
|
||||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css" rel="stylesheet" type="text/css" />
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="https://unpkg.com/tachyons@4.9.1/css/tachyons.min.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/css/style.css?v={{commiteth-version}}" rel="stylesheet" type="text/css" />
|
<link href="/css/style.css?v={{commiteth-version}}" rel="stylesheet" type="text/css" />
|
||||||
<script type="text/javascript" src="/js/app.js?v={{commiteth-version}}"></script>
|
<script type="text/javascript" src="/js/app.js?v={{commiteth-version}}"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -101,3 +101,9 @@
|
||||||
first
|
first
|
||||||
:exists
|
:exists
|
||||||
boolean)))
|
boolean)))
|
||||||
|
|
||||||
|
(defn get-issue
|
||||||
|
[repo-id issue-number]
|
||||||
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
|
(db/get-issue con-db {:repo_id repo-id
|
||||||
|
:issue_number issue-number})))
|
||||||
|
|
|
@ -25,13 +25,17 @@
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
(db/get-enabled-repositories con-db {:user_id user-id}))))
|
(db/get-enabled-repositories con-db {:user_id user-id}))))
|
||||||
|
|
||||||
(defn update-repo
|
(defn update-repo-name
|
||||||
[repo-id updates]
|
[repo-id repo-name]
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
(db/update-repo-generic con-db {:repo_id repo-id
|
(db/update-repo-name con-db {:repo_id repo-id
|
||||||
:updates updates})))
|
:repo_name repo-name})))
|
||||||
|
|
||||||
|
|
||||||
|
(defn update-repo-state
|
||||||
|
[repo-id repo-state]
|
||||||
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
|
(db/update-repo-name con-db {:repo_id repo-id
|
||||||
|
:repo_state repo-state})))
|
||||||
(defn get-repo
|
(defn get-repo
|
||||||
"Get a repo from DB given it's full name (owner/repo-name)"
|
"Get a repo from DB given it's full name (owner/repo-name)"
|
||||||
[full-name]
|
[full-name]
|
||||||
|
|
|
@ -219,7 +219,7 @@
|
||||||
(str "Tokens: "
|
(str "Tokens: "
|
||||||
(str/join " " (map (fn [[tla balance]] (format "%s: %.2f"
|
(str/join " " (map (fn [[tla balance]] (format "%s: %.2f"
|
||||||
(subs (str tla) 1)
|
(subs (str tla) 1)
|
||||||
(float balance)))
|
(double balance)))
|
||||||
token-balances))
|
token-balances))
|
||||||
"\n")))
|
"\n")))
|
||||||
|
|
||||||
|
|
|
@ -46,67 +46,6 @@
|
||||||
(log/debug "token" token "member?" member?)
|
(log/debug "token" token "member?" member?)
|
||||||
member?))
|
member?))
|
||||||
|
|
||||||
(defn enable-repo [repo-id repo full-repo token]
|
|
||||||
(log/debug "enable-repo" repo-id repo)
|
|
||||||
(when (github/webhook-exists? full-repo token)
|
|
||||||
(github/remove-our-webhooks full-repo token))
|
|
||||||
|
|
||||||
(let [hook-secret (random/base64 32)]
|
|
||||||
(repositories/update-repo repo-id {:state 1
|
|
||||||
:hook_secret hook-secret})
|
|
||||||
(let [created-hook (github/add-webhook full-repo token hook-secret)]
|
|
||||||
(log/debug "Created webhook:" created-hook)
|
|
||||||
(repositories/update-repo repo-id {:hook_id (:id created-hook)})))
|
|
||||||
(github/create-label full-repo token)
|
|
||||||
(repositories/update-repo repo-id {:state 2})
|
|
||||||
(when (add-bounties-for-existing-issues?)
|
|
||||||
(bounties/add-bounties-for-existing-issues full-repo)))
|
|
||||||
|
|
||||||
(defn disable-repo [repo-id full-repo hook-id token]
|
|
||||||
(log/debug "disable-repo" repo-id full-repo)
|
|
||||||
(github/remove-webhook full-repo hook-id token)
|
|
||||||
(repositories/update-repo repo-id {:hook_secret ""
|
|
||||||
:state 0
|
|
||||||
:hook_id nil}))
|
|
||||||
|
|
||||||
;; NOTE(oskarth): This and above two functions about to be deprecated with Github App
|
|
||||||
(defn handle-toggle-repo [user params can-create?]
|
|
||||||
(log/info "XXX handle-toggle-repo" (pr-str user) (pr-str params))
|
|
||||||
(let [{user-id :id} user
|
|
||||||
{repo-id :id
|
|
||||||
full-repo :full_name
|
|
||||||
owner-avatar-url :owner-avatar-url
|
|
||||||
token :token
|
|
||||||
repo :name} params
|
|
||||||
[owner _] (str/split full-repo #"/")
|
|
||||||
db-user (users/get-user (:id user))]
|
|
||||||
|
|
||||||
(cond (not can-create?)
|
|
||||||
{:status 400
|
|
||||||
:body "Please join our Riot - chat.status.im/#/register and request
|
|
||||||
access in our #openbounty room to have your account whitelisted"}
|
|
||||||
|
|
||||||
(empty? (:address db-user))
|
|
||||||
{:status 400
|
|
||||||
:body "Please add your ethereum address to your profile first"}
|
|
||||||
|
|
||||||
:else
|
|
||||||
(try
|
|
||||||
(let [_ (println "CREATING")
|
|
||||||
db-item (repositories/create (merge params {:user_id user-id
|
|
||||||
:owner owner}))
|
|
||||||
is-enabled (= 2 (:state db-item))]
|
|
||||||
(if is-enabled
|
|
||||||
(disable-repo repo-id full-repo (:hook_id db-item) token)
|
|
||||||
(enable-repo repo-id repo full-repo token))
|
|
||||||
(ok (merge
|
|
||||||
{:enabled (not is-enabled)}
|
|
||||||
(select-keys params [:id :full_name]))))
|
|
||||||
(catch Exception e
|
|
||||||
(log/error "exception when enabling repo" e)
|
|
||||||
(repositories/update-repo repo-id {:state -1})
|
|
||||||
(internal-server-error))))))
|
|
||||||
|
|
||||||
(defn in? [coll elem]
|
(defn in? [coll elem]
|
||||||
(some #(= elem %) coll))
|
(some #(= elem %) coll))
|
||||||
|
|
||||||
|
@ -286,9 +225,4 @@
|
||||||
:auth-rules authenticated?
|
:auth-rules authenticated?
|
||||||
:current-user user
|
:current-user user
|
||||||
(log/debug "/user/bounties")
|
(log/debug "/user/bounties")
|
||||||
(ok (user-bounties user)))
|
(ok (user-bounties user))))))
|
||||||
(POST "/repository/toggle" {:keys [params]}
|
|
||||||
;; NOTE: Don't allow anyone to create repos; manual add
|
|
||||||
:auth-rules authenticated?
|
|
||||||
:current-user user
|
|
||||||
(handle-toggle-repo user params (user-whitelisted? (:login user)))))))
|
|
||||||
|
|
|
@ -109,26 +109,17 @@
|
||||||
(extract pr-title))))
|
(extract pr-title))))
|
||||||
|
|
||||||
|
|
||||||
(defn ensure-bounty-issue
|
|
||||||
"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 (bounties/has-bounty-label? issue)
|
|
||||||
issue-number)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn handle-claim
|
(defn handle-claim
|
||||||
[user-id login name avatar_url owner repo repo-id bounty-issue-number pr-id pr-number head-sha merged? event-type]
|
[issue user-id login name avatar_url owner repo repo-id pr-id pr-number head-sha merged? event-type]
|
||||||
(users/create-user user-id login name nil avatar_url)
|
(users/create-user user-id login name nil avatar_url)
|
||||||
(let [issue (github/get-issue owner repo bounty-issue-number)
|
(let [open-or-edit? (contains? #{:opened :edited} event-type)
|
||||||
open-or-edit? (contains? #{:opened :edited} event-type)
|
|
||||||
close? (= :closed event-type)
|
close? (= :closed event-type)
|
||||||
pr-data {:repo_id repo-id
|
pr-data {:repo_id repo-id
|
||||||
:pr_id pr-id
|
:pr_id pr-id
|
||||||
:pr_number pr-number
|
:pr_number pr-number
|
||||||
:user_id user-id
|
:user_id user-id
|
||||||
:issue_number bounty-issue-number
|
:issue_number (:issue_number issue)
|
||||||
:issue_id (:id issue)
|
:issue_id (:issue_id issue)
|
||||||
:state event-type}]
|
:state event-type}]
|
||||||
|
|
||||||
;; TODO: in the opened case if the submitting user has no
|
;; TODO: in the opened case if the submitting user has no
|
||||||
|
@ -138,18 +129,18 @@
|
||||||
(cond
|
(cond
|
||||||
open-or-edit? (do
|
open-or-edit? (do
|
||||||
(log/info "PR with reference to bounty issue"
|
(log/info "PR with reference to bounty issue"
|
||||||
bounty-issue-number "opened")
|
(:issue_number issue) "opened")
|
||||||
(pull-requests/save (merge pr-data {:state :opened
|
(pull-requests/save (merge pr-data {:state :opened
|
||||||
:commit_sha head-sha})))
|
:commit_sha head-sha})))
|
||||||
close? (if merged?
|
close? (if merged?
|
||||||
(do (log/info "PR with reference to bounty issue"
|
(do (log/info "PR with reference to bounty issue"
|
||||||
bounty-issue-number "merged")
|
(:issue_number issue) "merged")
|
||||||
(pull-requests/save
|
(pull-requests/save
|
||||||
(merge pr-data {:state :merged
|
(merge pr-data {:state :merged
|
||||||
:commit_sha head-sha}))
|
:commit_sha head-sha}))
|
||||||
(issues/update-commit-sha (:id issue) head-sha))
|
(issues/update-commit-sha (:issue_id issue) head-sha))
|
||||||
(do (log/info "PR with reference to bounty issue"
|
(do (log/info "PR with reference to bounty issue"
|
||||||
bounty-issue-number "closed with no merge")
|
(:issue_number issue) "closed with no merge")
|
||||||
(pull-requests/save
|
(pull-requests/save
|
||||||
(merge pr-data {:state :closed
|
(merge pr-data {:state :closed
|
||||||
:commit_sha head-sha})))))))
|
:commit_sha head-sha})))))))
|
||||||
|
@ -177,26 +168,27 @@
|
||||||
pr-number :number
|
pr-number :number
|
||||||
pr-body :body
|
pr-body :body
|
||||||
pr-title :title} :pull_request}]
|
pr-title :title} :pull_request}]
|
||||||
(log/debug "handle-pull-request-event" event-type owner repo repo-id login pr-body pr-title)
|
(log/info "handle-pull-request-event" event-type owner repo repo-id login pr-body pr-title)
|
||||||
(log/debug (extract-issue-number pr-body pr-title))
|
(if-let [issue (some->> (extract-issue-number pr-body pr-title)
|
||||||
(if-let [bounty-issue-number (->>
|
(first)
|
||||||
(extract-issue-number pr-body pr-title)
|
(issues/get-issue repo-id))]
|
||||||
(first)
|
(if-not (:commit_sha issue) ; no PR has been merged yet referencing this issue
|
||||||
(ensure-bounty-issue owner repo))]
|
(do
|
||||||
(do
|
(log/info "Referenced bounty issue found" owner repo (:issue_number issue))
|
||||||
(log/debug "Referenced bounty issue found" owner repo bounty-issue-number)
|
(handle-claim issue
|
||||||
(handle-claim user-id
|
user-id
|
||||||
login name
|
login name
|
||||||
avatar_url
|
avatar_url
|
||||||
owner repo
|
owner repo
|
||||||
repo-id
|
repo-id
|
||||||
bounty-issue-number
|
pr-id
|
||||||
pr-id
|
pr-number
|
||||||
pr-number
|
head-sha
|
||||||
head-sha
|
merged?
|
||||||
merged?
|
event-type))
|
||||||
event-type))
|
(log/info "PR for issue already merged"))
|
||||||
(when (= :edited event-type)
|
(when (= :edited event-type)
|
||||||
|
; Remove PR if it does not reference any issue
|
||||||
(pull-requests/remove pr-id))))
|
(pull-requests/remove pr-id))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,9 +199,15 @@
|
||||||
new-title (:title gh-issue)]
|
new-title (:title gh-issue)]
|
||||||
(issues/update-issue-title issue-id new-title)))
|
(issues/update-issue-title issue-id new-title)))
|
||||||
|
|
||||||
|
(defn update-repo-name [webhook-payload]
|
||||||
|
"Update repo name in DB if changed"
|
||||||
|
(let [{repo-id :id
|
||||||
|
repo-name :name} (:repository webhook-payload)]
|
||||||
|
(repositories/update-repo-name repo-id repo-name)))
|
||||||
|
|
||||||
(defn handle-issue
|
(defn handle-issue
|
||||||
[webhook-payload]
|
[webhook-payload]
|
||||||
|
(update-repo-name webhook-payload)
|
||||||
(when-let [action (:action webhook-payload)]
|
(when-let [action (:action webhook-payload)]
|
||||||
(log/debug "handle-issue" action)
|
(log/debug "handle-issue" action)
|
||||||
(when (labeled-as-bounty? action webhook-payload)
|
(when (labeled-as-bounty? action webhook-payload)
|
||||||
|
@ -224,17 +222,17 @@
|
||||||
(handle-issue-reopened webhook-payload)))
|
(handle-issue-reopened webhook-payload)))
|
||||||
(ok))
|
(ok))
|
||||||
|
|
||||||
(defn enable-repo-2 [repo-id full-repo]
|
(defn enable-repo [repo-id full-repo]
|
||||||
(log/debug "enable-repo-2" repo-id full-repo)
|
(log/debug "enable-repo" repo-id full-repo)
|
||||||
;; TODO(oskarth): Add granular permissions to enable creation of label
|
;; TODO(oskarth): Add granular permissions to enable creation of label
|
||||||
#_(github/create-label full-repo)
|
#_(github/create-label full-repo)
|
||||||
(repositories/update-repo repo-id {:state 2})
|
(repositories/update-repo-state repo-id 2)
|
||||||
(when (add-bounties-for-existing-issues?)
|
(when (add-bounties-for-existing-issues?)
|
||||||
(bounties/add-bounties-for-existing-issues full-repo)))
|
(bounties/add-bounties-for-existing-issues full-repo)))
|
||||||
|
|
||||||
(defn disable-repo-2 [repo-id full-repo]
|
(defn disable-repo [repo-id full-repo]
|
||||||
(log/debug "disable-repo-2" repo-id full-repo)
|
(log/debug "disable-repo" repo-id full-repo)
|
||||||
(repositories/update-repo repo-id {:state 0}))
|
(repositories/update-repo-state repo-id 0))
|
||||||
|
|
||||||
(defn full-repo->owner [full-repo]
|
(defn full-repo->owner [full-repo]
|
||||||
(try
|
(try
|
||||||
|
@ -244,8 +242,6 @@
|
||||||
(log/error "exception when parsing repo" e)
|
(log/error "exception when parsing repo" e)
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
;; NOTE(oskarth): Together with {enable,disable}-repo-2 above, this replaces
|
|
||||||
;; handle-toggle-repo for Github App.
|
|
||||||
(defn handle-add-repo [user-id username owner-avatar-url repo can-create?]
|
(defn handle-add-repo [user-id username owner-avatar-url repo can-create?]
|
||||||
(let [repo-id (:id repo)
|
(let [repo-id (:id repo)
|
||||||
repo-name (:name repo)
|
repo-name (:name repo)
|
||||||
|
@ -285,14 +281,14 @@
|
||||||
_ (log/info "handle-add-repo db-item" db-item)
|
_ (log/info "handle-add-repo db-item" db-item)
|
||||||
is-enabled (= 2 (:state db-item))]
|
is-enabled (= 2 (:state db-item))]
|
||||||
(if is-enabled
|
(if is-enabled
|
||||||
(disable-repo-2 repo-id full-repo)
|
(disable-repo repo-id full-repo)
|
||||||
(enable-repo-2 repo-id full-repo))
|
(enable-repo repo-id full-repo))
|
||||||
(ok {:enabled (not is-enabled)
|
(ok {:enabled (not is-enabled)
|
||||||
:id repo-id
|
:id repo-id
|
||||||
:full_name full-repo}))
|
:full_name full-repo}))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(log/error "exception when enabling repo" e)
|
(log/error "exception when enabling repo" e)
|
||||||
(repositories/update-repo repo-id {:state -1})
|
(repositories/update-repo-state repo-id -1)
|
||||||
(internal-server-error))))))
|
(internal-server-error))))))
|
||||||
|
|
||||||
(defn handle-installation [{:keys [action installation repositories sender]}]
|
(defn handle-installation [{:keys [action installation repositories sender]}]
|
||||||
|
@ -335,12 +331,13 @@
|
||||||
(ok))
|
(ok))
|
||||||
|
|
||||||
(defn handle-pull-request
|
(defn handle-pull-request
|
||||||
[pull-request]
|
[webhook-payload]
|
||||||
(let [action (keyword (:action pull-request))]
|
(update-repo-name webhook-payload)
|
||||||
|
(let [action (keyword (:action webhook-payload))]
|
||||||
(when (contains? #{:opened
|
(when (contains? #{:opened
|
||||||
:edited
|
:edited
|
||||||
:closed} action)
|
:closed} action)
|
||||||
(handle-pull-request-event action pull-request))
|
(handle-pull-request-event action webhook-payload))
|
||||||
(ok)))
|
(ok)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,14 +390,5 @@
|
||||||
"pull_request" (handle-pull-request payload)
|
"pull_request" (handle-pull-request payload)
|
||||||
"installation" (handle-installation payload)
|
"installation" (handle-installation payload)
|
||||||
"installation_repositories" (handle-installation-repositories payload)
|
"installation_repositories" (handle-installation-repositories payload)
|
||||||
|
|
||||||
;; NOTE(oskarth): These two webhooks are / will be deprecated on
|
|
||||||
;; November 22, 2017 but they keep being called. According to
|
|
||||||
;; documentation they should contain same format.
|
|
||||||
;; https://developer.github.com/webhooks/
|
|
||||||
"integration_installation" (handle-installation payload)
|
|
||||||
"integration_installation_repositories" (handle-installation-repositories payload)
|
|
||||||
(ok)))
|
(ok)))
|
||||||
(forbidden)))))
|
(forbidden)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -254,12 +254,6 @@
|
||||||
(neg? n) (- n)
|
(neg? n) (- n)
|
||||||
:else n))
|
:else n))
|
||||||
|
|
||||||
(defn float=
|
|
||||||
([x y] (float= x y 0.0000001))
|
|
||||||
([x y epsilon]
|
|
||||||
(log/debug x y epsilon)
|
|
||||||
(let [scale (if (or (zero? x) (zero? y)) 1 (abs x))]
|
|
||||||
(<= (abs (- x y)) (* scale epsilon)))))
|
|
||||||
|
|
||||||
(defn update-bounty-token-balances
|
(defn update-bounty-token-balances
|
||||||
"Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts."
|
"Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts."
|
||||||
|
@ -322,6 +316,17 @@
|
||||||
(db-bounties/open-bounty-contracts)]
|
(db-bounties/open-bounty-contracts)]
|
||||||
(update-issue-usd-value bounty-addr))))
|
(update-issue-usd-value bounty-addr))))
|
||||||
|
|
||||||
|
(defn float=
|
||||||
|
([x y] (float= x y 0.0000001))
|
||||||
|
([x y epsilon]
|
||||||
|
(log/debug x y epsilon)
|
||||||
|
(let [scale (if (or (zero? x) (zero? y)) 1 (abs x))]
|
||||||
|
(<= (abs (- x y)) (* scale epsilon)))))
|
||||||
|
|
||||||
|
(defn map-float= [m1 m2]
|
||||||
|
(and (= (set (keys m1)) (set (keys m2)))
|
||||||
|
(every? #(float= (get m1 %1) (get m2 %1)) (keys m1))))
|
||||||
|
|
||||||
(defn update-balances
|
(defn update-balances
|
||||||
[]
|
[]
|
||||||
(log/info "In update-balances")
|
(log/info "In update-balances")
|
||||||
|
@ -344,13 +349,13 @@
|
||||||
|
|
||||||
(when (or
|
(when (or
|
||||||
(not (float= db-balance-eth balance-eth))
|
(not (float= db-balance-eth balance-eth))
|
||||||
(not= db-tokens token-balances))
|
(not (map-float= db-tokens token-balances)))
|
||||||
(log/debug "balances differ")
|
(log/info "balances differ")
|
||||||
(log/debug "ETH (db):" db-balance-eth (type db-balance-eth) )
|
(log/info "ETH (db):" db-balance-eth (type db-balance-eth) )
|
||||||
(log/debug "ETH (chain):" balance-eth (type balance-eth) )
|
(log/info "ETH (chain):" balance-eth (type balance-eth) )
|
||||||
(log/debug "ETH cmp:" (float= db-balance-eth balance-eth))
|
(log/info "ETH cmp:" (float= db-balance-eth balance-eth))
|
||||||
(log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens)))
|
(log/info "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens)))
|
||||||
(log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances)))
|
(log/info "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances)))
|
||||||
(log/debug "tokens cmp:" (= db-tokens token-balances))
|
(log/debug "tokens cmp:" (= db-tokens token-balances))
|
||||||
|
|
||||||
(issues/update-eth-balance contract-address balance-eth)
|
(issues/update-eth-balance contract-address balance-eth)
|
||||||
|
|
|
@ -135,4 +135,10 @@
|
||||||
[:div.page-nav-text [:span (str "Page " page-number " of " page-count)]]
|
[:div.page-nav-text [:span (str "Page " page-number " of " page-count)]]
|
||||||
[draw-page-numbers page-number page-count container-element]]])))
|
[draw-page-numbers page-number page-count container-element]]])))
|
||||||
|
|
||||||
|
(defn usd-string
|
||||||
|
"Turn a given float into a USD currency string based on the browsers locale setting.
|
||||||
|
|
||||||
|
A more complex and customizable approach can be found in goog.i18n.NumberFormat:
|
||||||
|
https://google.github.io/closure-library/api/goog.i18n.NumberFormat.html"
|
||||||
|
[usd-float]
|
||||||
|
(.toLocaleString usd-float js/navigator.language #js {:style "currency" :currency "USD"}))
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
(ns commiteth.core
|
(ns commiteth.core
|
||||||
(:require [reagent.core :as r]
|
(:require [reagent.core :as r]
|
||||||
[re-frame.core :as rf]
|
[re-frame.core :as rf]
|
||||||
[secretary.core :as secretary]
|
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[goog.history.EventType :as HistoryEventType]
|
[goog.history.EventType :as HistoryEventType]
|
||||||
[commiteth.ajax :refer [load-interceptors!]]
|
[commiteth.ajax :refer [load-interceptors!]]
|
||||||
|
[commiteth.routes]
|
||||||
[commiteth.handlers]
|
[commiteth.handlers]
|
||||||
[commiteth.subscriptions]
|
[commiteth.subscriptions]
|
||||||
[commiteth.activity :refer [activity-page]]
|
[commiteth.activity :refer [activity-page]]
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
[:a
|
[:a
|
||||||
(merge props
|
(merge props
|
||||||
(if (keyword? target)
|
(if (keyword? target)
|
||||||
{:on-click #(rf/dispatch [target])}
|
{:on-click #(commiteth.routes/nav! target)}
|
||||||
{:href target}))
|
{:href target}))
|
||||||
caption]]))]]))
|
caption]]))]]))
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
[:div.ui.container.user-component
|
[:div.ui.container.user-component
|
||||||
[user-dropdown
|
[user-dropdown
|
||||||
@user
|
@user
|
||||||
[[:update-address "My Payment Details" {}]
|
[[:settings "My Payment Details" {}]
|
||||||
["/logout" "Sign Out" {:class "logout-link"}]]
|
["/logout" "Sign Out" {:class "logout-link"}]]
|
||||||
mobile?]]
|
mobile?]]
|
||||||
[:a.ui.button.small.login-button {:href js/authorizeUrl} (str "LOG IN"
|
[:a.ui.button.small.login-button {:href js/authorizeUrl} (str "LOG IN"
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
(for [[page caption] tabs]
|
(for [[page caption] tabs]
|
||||||
(let [props {:class (str "ui item"
|
(let [props {:class (str "ui item"
|
||||||
(when (= @current-page page) " active"))
|
(when (= @current-page page) " active"))
|
||||||
:on-click #(rf/dispatch [:set-active-page page])}]
|
:on-click #(commiteth.routes/nav! page)}]
|
||||||
^{:key page} [:div props caption])))))))
|
^{:key page} [:div props caption])))))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,15 +124,6 @@
|
||||||
[flash-message-pane])])))
|
[flash-message-pane])])))
|
||||||
|
|
||||||
|
|
||||||
(def pages
|
|
||||||
{:activity #'activity-page
|
|
||||||
:bounties #'bounties-page
|
|
||||||
:repos #'repos-page
|
|
||||||
:manage-payouts #'manage-payouts-page
|
|
||||||
:update-address #'update-address-page
|
|
||||||
:usage-metrics #'usage-metrics-page})
|
|
||||||
|
|
||||||
|
|
||||||
(defn top-hunters []
|
(defn top-hunters []
|
||||||
(let [top-hunters (rf/subscribe [:top-hunters])]
|
(let [top-hunters (rf/subscribe [:top-hunters])]
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -211,7 +202,13 @@
|
||||||
[:div {:class (str (if (show-top-hunters?) "eleven" "sixteen")
|
[:div {:class (str (if (show-top-hunters?) "eleven" "sixteen")
|
||||||
" wide computer sixteen wide tablet column")}
|
" wide computer sixteen wide tablet column")}
|
||||||
[:div.ui.container
|
[:div.ui.container
|
||||||
[(pages @current-page)]]]
|
(case @current-page
|
||||||
|
:activity [activity-page]
|
||||||
|
:bounties [bounties-page]
|
||||||
|
:repos [repos-page]
|
||||||
|
:manage-payouts [manage-payouts-page]
|
||||||
|
:settings [update-address-page]
|
||||||
|
:usage-metrics [usage-metrics-page])]]
|
||||||
(when (show-top-hunters?)
|
(when (show-top-hunters?)
|
||||||
[:div.five.wide.column.computer.only
|
[:div.five.wide.column.computer.only
|
||||||
[:div.ui.container.top-hunters
|
[:div.ui.container.top-hunters
|
||||||
|
@ -220,28 +217,6 @@
|
||||||
[top-hunters]]])]]]
|
[top-hunters]]])]]]
|
||||||
[footer]])))
|
[footer]])))
|
||||||
|
|
||||||
(secretary/set-config! :prefix "#")
|
|
||||||
|
|
||||||
(secretary/defroute "/" []
|
|
||||||
(rf/dispatch [:set-active-page :bounties]))
|
|
||||||
|
|
||||||
(secretary/defroute "/activity" []
|
|
||||||
(rf/dispatch [:set-active-page :activity]))
|
|
||||||
|
|
||||||
|
|
||||||
(secretary/defroute "/repos" []
|
|
||||||
(if js/user
|
|
||||||
(rf/dispatch [:set-active-page :repos])
|
|
||||||
(secretary/dispatch! "/")))
|
|
||||||
|
|
||||||
(defn hook-browser-navigation! []
|
|
||||||
(doto (History.)
|
|
||||||
(events/listen
|
|
||||||
HistoryEventType/NAVIGATE
|
|
||||||
(fn [event]
|
|
||||||
(secretary/dispatch! (.-token event))))
|
|
||||||
(.setEnabled true)))
|
|
||||||
|
|
||||||
(defn mount-components []
|
(defn mount-components []
|
||||||
(r/render [#'page] (.getElementById js/document "app")))
|
(r/render [#'page] (.getElementById js/document "app")))
|
||||||
|
|
||||||
|
@ -286,7 +261,7 @@
|
||||||
(when config/debug?
|
(when config/debug?
|
||||||
(enable-re-frisk!))
|
(enable-re-frisk!))
|
||||||
(load-interceptors!)
|
(load-interceptors!)
|
||||||
(hook-browser-navigation!)
|
(commiteth.routes/setup-nav!)
|
||||||
(load-data true)
|
(load-data true)
|
||||||
(.addEventListener js/window "click" #(rf/dispatch [:clear-flash-message]))
|
(.addEventListener js/window "click" #(rf/dispatch [:clear-flash-message]))
|
||||||
(on-js-load))
|
(on-js-load))
|
||||||
|
|
|
@ -312,12 +312,6 @@
|
||||||
(:status-text response)))]}))
|
(:status-text response)))]}))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-fx
|
|
||||||
:update-address
|
|
||||||
(fn [{:keys [db]} [_]]
|
|
||||||
{:db db
|
|
||||||
:dispatch [:set-active-page :update-address]}))
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:update-user
|
:update-user
|
||||||
(fn [db [_ fields]]
|
(fn [db [_ fields]]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns commiteth.manage-payouts
|
(ns commiteth.manage-payouts
|
||||||
(:require [re-frame.core :as rf]
|
(:require [re-frame.core :as rf]
|
||||||
[commiteth.common :refer [human-time]]))
|
[commiteth.common :as common :refer [human-time]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,9 +57,21 @@
|
||||||
(:claims bounty))]
|
(:claims bounty))]
|
||||||
[claim-card bounty claim]))))
|
[claim-card bounty claim]))))
|
||||||
|
|
||||||
|
(defn bounty-stats [{:keys [paid unpaid]}]
|
||||||
|
[:div.cf
|
||||||
|
[:div.fl-ns.w-50-ns.tc.pv4
|
||||||
|
[:div.ttu.tracked "Open"]
|
||||||
|
[:div.f2.pa2 (common/usd-string (:combined-usd-value unpaid))]
|
||||||
|
[:div (:count unpaid) " bounties"]]
|
||||||
|
|
||||||
|
[:div.fl-ns.w-50-ns.tc.pv4
|
||||||
|
[:div.ttu.tracked "Paid"]
|
||||||
|
[:div.f2.pa2 (common/usd-string (:combined-usd-value paid))]
|
||||||
|
[:div (:count paid) " bounties"]]])
|
||||||
|
|
||||||
(defn manage-payouts-page []
|
(defn manage-payouts-page []
|
||||||
(let [owner-bounties (rf/subscribe [:owner-bounties])
|
(let [owner-bounties (rf/subscribe [:owner-bounties])
|
||||||
|
bounty-stats-data (rf/subscribe [:owner-bounties-stats])
|
||||||
owner-bounties-loading? (rf/subscribe [:get-in [:owner-bounties-loading?]])]
|
owner-bounties-loading? (rf/subscribe [:get-in [:owner-bounties-loading?]])]
|
||||||
(fn []
|
(fn []
|
||||||
(if @owner-bounties-loading?
|
(if @owner-bounties-loading?
|
||||||
|
@ -67,17 +79,14 @@
|
||||||
[:div.ui.active.inverted.dimmer
|
[:div.ui.active.inverted.dimmer
|
||||||
[:div.ui.text.loader "Loading"]]]
|
[:div.ui.text.loader "Loading"]]]
|
||||||
(let [web3 (.-web3 js/window)
|
(let [web3 (.-web3 js/window)
|
||||||
bounties (vals @owner-bounties)
|
bounties (vals @owner-bounties)]
|
||||||
unpaid? #(empty? (:payout_hash %))
|
|
||||||
paid? #(not-empty (:payout_hash %))
|
|
||||||
unpaid-bounties (filter unpaid? bounties)
|
|
||||||
paid-bounties (filter paid? bounties)]
|
|
||||||
[:div.ui.container
|
[:div.ui.container
|
||||||
(when (nil? web3)
|
(when (nil? web3)
|
||||||
[:div.ui.warning.message
|
[:div.ui.warning.message
|
||||||
[:i.warning.icon]
|
[:i.warning.icon]
|
||||||
"To sign off claims, please view Status Open Bounty in Status, Mist or Metamask"])
|
"To sign off claims, please view Status Open Bounty in Status, Mist or Metamask"])
|
||||||
|
[bounty-stats @bounty-stats-data]
|
||||||
[:h3 "New claims"]
|
[:h3 "New claims"]
|
||||||
[claim-list unpaid-bounties]
|
[claim-list (filter (complement :paid?) bounties)]
|
||||||
[:h3 "Old claims"]
|
[:h3 "Old claims"]
|
||||||
[claim-list paid-bounties]])))))
|
[claim-list (filter :paid? bounties)]])))))
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
(ns commiteth.routes
|
||||||
|
(:require [bide.core :as bide]
|
||||||
|
[re-frame.core :as rf]))
|
||||||
|
|
||||||
|
(defonce router
|
||||||
|
(bide/router [["/" :bounties]
|
||||||
|
["/activity" :activity]
|
||||||
|
["/repos" :repos]
|
||||||
|
["/manage-payouts" :manage-payouts]
|
||||||
|
["/settings" :settings]
|
||||||
|
["/usage-metrics" :usage-metrics]]))
|
||||||
|
|
||||||
|
(defn on-navigate
|
||||||
|
"A function which will be called on each route change."
|
||||||
|
[name params query]
|
||||||
|
(println "Route change to: " name params query)
|
||||||
|
(rf/dispatch [:set-active-page name]))
|
||||||
|
|
||||||
|
(defn setup-nav! []
|
||||||
|
(bide/start! router {:default :bounties
|
||||||
|
:on-navigate on-navigate}))
|
||||||
|
|
||||||
|
(defn nav! [route-id]
|
||||||
|
(bide/navigate! router route-id {}))
|
||||||
|
|
|
@ -68,7 +68,26 @@
|
||||||
(reg-sub
|
(reg-sub
|
||||||
:owner-bounties
|
:owner-bounties
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:owner-bounties db)))
|
(->> (for [[id bounty] (:owner-bounties db)]
|
||||||
|
;; TODO(martinklepsch) we might want to consider using a
|
||||||
|
;; special prefix or namespace for derived properties that
|
||||||
|
;; are added to domain records like this
|
||||||
|
;; e.g. `derived/paid?`
|
||||||
|
[id (assoc bounty :paid? (boolean (:payout_hash bounty)))])
|
||||||
|
(into {}))))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:owner-bounties-stats
|
||||||
|
:<- [:owner-bounties]
|
||||||
|
(fn [owner-bounties _]
|
||||||
|
(let [sum-dollars (fn sum-dollars [bounties]
|
||||||
|
(reduce + (map #(js/parseFloat (:value_usd %)) bounties)))
|
||||||
|
{:keys [paid unpaid]} (group-by #(if (:paid? %) :paid :unpaid)
|
||||||
|
(vals owner-bounties))]
|
||||||
|
{:paid {:count (count paid)
|
||||||
|
:combined-usd-value (sum-dollars paid)}
|
||||||
|
:unpaid {:count (count unpaid)
|
||||||
|
:combined-usd-value (sum-dollars unpaid)}})))
|
||||||
|
|
||||||
(reg-sub
|
(reg-sub
|
||||||
:pagination
|
:pagination
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
node ('linux1') {sauce('1be1b688-e0e7-4314-92a0-db11f52d3c00') {
|
node ('linux1') {sauce('1be1b688-e0e7-4314-92a0-db11f52d3c00') {
|
||||||
checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanBeforeCheckout']], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/status-im/open-bounty.git']]])
|
checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanBeforeCheckout']], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/status-im/open-bounty.git']]])
|
||||||
configFileProvider([configFile(fileId: 'sob_automation_test_config', targetLocation: 'test/end-to-end/tests')]) {
|
configFileProvider([configFile(fileId: 'sob_automation_test_config', targetLocation: 'test/end-to-end/tests')]) {
|
||||||
try {sh 'cd test/end-to-end/tests && python3 -m pytest -m sanity --build=$BUILD_NAME -v -n 1'
|
try {withCredentials([string(credentialsId: 'SOB_SAUCE_ACCESS_KEY', variable: 'SAUCE_ACCESS_KEY'), string(credentialsId: 'SOB_SAUCE_USERNAME', variable: 'SAUCE_USERNAME')])
|
||||||
|
{sh 'cd test && docker build -t end2end . && docker run --rm -e "SAUCE_USERNAME="${SAUCE_USERNAME} -e "SAUCE_ACCESS_KEY="${SAUCE_ACCESS_KEY} --name end2end-container end2end -m pytest -m sanity --build=$BUILD_NAME -v -n 1'}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
saucePublisher()
|
saucePublisher()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import configparser
|
import configparser
|
||||||
|
import os
|
||||||
|
|
||||||
class TestData(object):
|
class TestData(object):
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ class TestData(object):
|
||||||
# define here path to your config.ini file
|
# define here path to your config.ini file
|
||||||
# example - config_example.ini
|
# example - config_example.ini
|
||||||
|
|
||||||
self.config.read("tests/config.ini")
|
self.config.read(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'config.ini'))
|
||||||
|
|
||||||
# self.issue['title'] is set in GithubPage::create_new_bounty
|
# self.issue['title'] is set in GithubPage::create_new_bounty
|
||||||
# self.issue['id'] is set in GithubPage::create_new_bounty
|
# self.issue['id'] is set in GithubPage::create_new_bounty
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BaseTestCase:
|
||||||
sauce_lab_cap = dict()
|
sauce_lab_cap = dict()
|
||||||
sauce_lab_cap['name'] = test_data.test_name
|
sauce_lab_cap['name'] = test_data.test_name
|
||||||
sauce_lab_cap['build'] = pytest.config.getoption('build')
|
sauce_lab_cap['build'] = pytest.config.getoption('build')
|
||||||
|
sauce_lab_cap['idleTimeout'] = 900
|
||||||
|
sauce_lab_cap['commandTimeout'] = 500
|
||||||
sauce_lab_cap['platform'] = "MAC"
|
sauce_lab_cap['platform'] = "MAC"
|
||||||
sauce_lab_cap['browserName'] = 'Chrome'
|
sauce_lab_cap['browserName'] = 'Chrome'
|
||||||
sauce_lab_cap['screenResolution'] = '2048x1536'
|
sauce_lab_cap['screenResolution'] = '2048x1536'
|
||||||
|
@ -67,8 +69,9 @@ class BaseTestCase:
|
||||||
|
|
||||||
if cls.environment == 'sauce':
|
if cls.environment == 'sauce':
|
||||||
for caps in cls.capabilities_dev, cls.capabilities_org:
|
for caps in cls.capabilities_dev, cls.capabilities_org:
|
||||||
cls.get_remote_caps(cls)
|
remote = cls.get_remote_caps(cls)
|
||||||
new_caps = caps.to_capabilities()
|
new_caps = caps.to_capabilities()
|
||||||
|
new_caps.update(remote)
|
||||||
driver = webdriver.Remote(cls.executor_sauce_lab,
|
driver = webdriver.Remote(cls.executor_sauce_lab,
|
||||||
desired_capabilities=new_caps)
|
desired_capabilities=new_caps)
|
||||||
drivers.append(driver)
|
drivers.append(driver)
|
||||||
|
@ -79,6 +82,7 @@ class BaseTestCase:
|
||||||
cls.driver_dev = drivers[0]
|
cls.driver_dev = drivers[0]
|
||||||
cls.driver_org = drivers[1]
|
cls.driver_org = drivers[1]
|
||||||
|
|
||||||
|
|
||||||
for driver in drivers:
|
for driver in drivers:
|
||||||
driver.implicitly_wait(10)
|
driver.implicitly_wait(10)
|
||||||
|
|
||||||
|
@ -132,9 +136,9 @@ class BaseTestCase:
|
||||||
remove_installation(cls.driver_org)
|
remove_installation(cls.driver_org)
|
||||||
|
|
||||||
######DEV
|
######DEV
|
||||||
|
|
||||||
cls.github_dev.delete_fork()
|
|
||||||
cls.github_dev.clean_repo_local_folder()
|
cls.github_dev.clean_repo_local_folder()
|
||||||
|
cls.github_dev.delete_fork()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cls.driver_dev.quit()
|
cls.driver_dev.quit()
|
||||||
cls.driver_org.quit()
|
cls.driver_org.quit()
|
||||||
|
|
Loading…
Reference in New Issue