Compare commits
2 Commits
csv/fix-te
...
fix-sql-st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a403e51022 | ||
|
|
3263ca1f66 |
31
.babelrc
Normal file
31
.babelrc
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"plugins": [
|
||||
"@emotion",
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }]
|
||||
],
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"env": {
|
||||
"development": {
|
||||
"presets": []
|
||||
},
|
||||
"extract": {
|
||||
"plugins": [
|
||||
[
|
||||
"ttag",
|
||||
{
|
||||
"extract": {
|
||||
"output": "locales/metabase-frontend.pot"
|
||||
},
|
||||
"discover": ["t", "jt"],
|
||||
"numberedExpressions": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
1299
.circleci/config.yml
1299
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
Update `clj-kondo` configs for libraries using
|
||||
|
||||
```sh
|
||||
clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath -A:dev)"
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}
|
||||
@@ -1 +0,0 @@
|
||||
{:hooks {:macroexpand {sci.core/copy-ns sci.core/copy-ns}}}
|
||||
@@ -1,9 +0,0 @@
|
||||
(ns sci.core)
|
||||
|
||||
(defmacro copy-ns
|
||||
([ns-sym sci-ns]
|
||||
`(copy-ns ~ns-sym ~sci-ns nil))
|
||||
([ns-sym sci-ns opts]
|
||||
`[(quote ~ns-sym)
|
||||
~sci-ns
|
||||
(quote ~opts)]))
|
||||
@@ -1,145 +0,0 @@
|
||||
(ns better-cond.core
|
||||
"A clj-kondo hook to allow linting of better-cond `cond` macro.
|
||||
This supports better-cond version 2.0.0+.
|
||||
|
||||
To use in a project, change the namespace to hooks.better-cond,
|
||||
put this code in file .clj-kondo/hooks/better_cond.clj, and include
|
||||
a config.edn entry in the :hooks key like:
|
||||
|
||||
:hooks {:analyze-call {better-cond.core/cond hooks.better-cond/cond}}
|
||||
|
||||
Note that the expansion of :when-let and :when-some forms currently
|
||||
takes a shortcut that *would* lead to incorrect values in some
|
||||
cases of restructuring during actual expansion/evaluation, e.g.,
|
||||
:when-let [[x y] nil] would not abort the cond, though :when-let
|
||||
[[x y] [nil nil]] would. However, for linting purposes, the current
|
||||
expansion approach works just fine. It seems unnecessary to do the
|
||||
full expansion in these cases for linting purposes, though that could
|
||||
be done if needed."
|
||||
(:refer-clojure :exclude [cond])
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as api]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(def better-cond-simple-keys
|
||||
"Special constructs in better cond, either as keywords or symbols.
|
||||
This includes those keys that are simply transformed. Note that
|
||||
:when-let and :when-some are *not* included as better-cond allows
|
||||
multiple bindings but clojure does not. These two must be handled
|
||||
separately."
|
||||
#{:let :when :do
|
||||
'let 'when 'do})
|
||||
|
||||
(def better-cond-complex-keys
|
||||
"Special constructs in better cond, either as keywords or symbols.
|
||||
This includes those keys that require a multi-step transformation.
|
||||
For example, :when-let and :when-some get converted to a let
|
||||
wrapping a when, wrapping the continuing cond. Note that clojure
|
||||
does not support multiple bindings in the standard when-let and
|
||||
when-some macros."
|
||||
{:when-let 'identity
|
||||
'when-let 'identity
|
||||
:when-some 'some?
|
||||
'when-some 'some?})
|
||||
|
||||
(defn extract-binding-forms
|
||||
[bindings]
|
||||
(keep-indexed #(when (even? %1) %2) bindings))
|
||||
|
||||
(defn process-pairs
|
||||
"Transforms a `cond` with the clauses given as a collection of explicit pairs.
|
||||
Handles all the special better-cond constructs as keywords or symbols.
|
||||
Returns a rewrite-clj list-node representing the transformed code."
|
||||
[node-pairs]
|
||||
(loop [[[lhs rhs :as pair] & pairs] node-pairs
|
||||
new-body [(api/token-node 'clojure.core/cond)]] ; Avoid reprocessing the cond with ns here
|
||||
(if pair
|
||||
(let [lhs-sexpr (api/sexpr lhs)]
|
||||
(clojure.core/cond
|
||||
(= 1 (count pair)) ;; better-cond allows single clause for default
|
||||
, (api/list-node (conj new-body (api/keyword-node :else) lhs))
|
||||
(better-cond-simple-keys lhs-sexpr) ;; Handle special better-cond constructs
|
||||
, (api/list-node
|
||||
(conj new-body
|
||||
(api/keyword-node :else)
|
||||
(api/list-node [(api/token-node (symbol #_"clojure.core" (name lhs-sexpr)))
|
||||
rhs
|
||||
(process-pairs pairs)])))
|
||||
(better-cond-complex-keys lhs-sexpr) ;; Multi stage constructs
|
||||
, (api/list-node
|
||||
(conj new-body
|
||||
(api/keyword-node :else)
|
||||
(api/list-node [(api/token-node 'let)
|
||||
rhs
|
||||
(api/list-node [(api/token-node 'when)
|
||||
(api/list-node ;; ATTN: shortcut here; fine for linting
|
||||
[(api/token-node 'every?)
|
||||
(api/token-node (better-cond-complex-keys lhs-sexpr))
|
||||
(api/vector-node (->> rhs
|
||||
api/sexpr
|
||||
extract-binding-forms
|
||||
(map api/token-node)))])
|
||||
(process-pairs pairs)])])))
|
||||
:else
|
||||
, (recur pairs (conj new-body lhs rhs))))
|
||||
(api/list-node new-body))))
|
||||
|
||||
(defn cond-hook
|
||||
[{:keys [node]}]
|
||||
(let [expr (let [args (rest (:children node))
|
||||
pairs (partition-all 2 args)]
|
||||
(process-pairs pairs))]
|
||||
{:node (with-meta expr
|
||||
(meta node))}))
|
||||
|
||||
(defn process-if-let-pairs [pairs then else]
|
||||
(if (seq pairs)
|
||||
(let [[lhs rhs] (first pairs)]
|
||||
(if (and (api/keyword-node? lhs)
|
||||
(= :let (api/sexpr lhs)))
|
||||
(api/list-node (conj [(api/token-node 'clojure.core/let) rhs
|
||||
(process-if-let-pairs (next pairs) then else)]))
|
||||
(let [test (api/token-node (gensym "test"))]
|
||||
(api/list-node
|
||||
(conj [(api/token-node 'clojure.core/let) (api/vector-node [test rhs])
|
||||
(api/list-node [(api/token-node 'if) test
|
||||
(api/list-node
|
||||
[(api/token-node 'clojure.core/let)
|
||||
(api/vector-node [lhs test])
|
||||
(process-if-let-pairs (next pairs) then else)])
|
||||
else])])))))
|
||||
then))
|
||||
|
||||
(defn if-let-hook
|
||||
[{:keys [node]}]
|
||||
(let [expr (let [[binding-vec then else] (rest (:children node))
|
||||
pairs (partition-all 2 (:children binding-vec))
|
||||
node (process-if-let-pairs pairs then else)]
|
||||
node)]
|
||||
{:node (with-meta expr
|
||||
(meta node))}))
|
||||
|
||||
(defn when-let-hook
|
||||
[{:keys [node]}]
|
||||
(let [expr (let [[binding-vec & body] (rest (:children node))]
|
||||
(api/list-node
|
||||
[(api/token-node 'better-cond.core/if-let)
|
||||
binding-vec
|
||||
(api/list-node (list* (api/token-node 'do)
|
||||
body))]))]
|
||||
{:node (with-meta expr
|
||||
(meta node))}))
|
||||
|
||||
(defn defnc-hook [{:keys [node]}]
|
||||
(let [[defnc-node name-node arg-node & body]
|
||||
(:children node)
|
||||
new-node (api/list-node [(api/token-node (if (str/ends-with? (str defnc-node)
|
||||
"defnc-")
|
||||
'clojure.core/defn-
|
||||
'clojure.core/defn))
|
||||
name-node
|
||||
arg-node
|
||||
(api/list-node
|
||||
(list* (api/token-node 'better-cond.core/cond)
|
||||
body))])]
|
||||
{:node new-node}))
|
||||
@@ -1,9 +0,0 @@
|
||||
{:hooks
|
||||
{:analyze-call
|
||||
{better-cond.core/cond better-cond.core/cond-hook
|
||||
better-cond.core/defnc better-cond.core/defnc-hook
|
||||
better-cond.core/defnc- better-cond.core/defnc-hook
|
||||
better-cond.core/if-let better-cond.core/if-let-hook
|
||||
better-cond.core/if-some better-cond.core/if-let-hook
|
||||
better-cond.core/when-let better-cond.core/when-let-hook
|
||||
better-cond.core/when-some better-cond.core/when-let-hook}}}
|
||||
@@ -1,19 +0,0 @@
|
||||
(ns clj-kondo.com.gfredericks.test.chuck.checking
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as api]))
|
||||
|
||||
(defn checking
|
||||
[{{:keys [children]} :node}]
|
||||
(let [[_checking desc & opt+bindings+body] children
|
||||
[opts binding-vec & body] (if (api/vector-node? (first opt+bindings+body))
|
||||
(into [(api/map-node {})] opt+bindings+body)
|
||||
opt+bindings+body)]
|
||||
(when-not (even? (count (:children binding-vec)))
|
||||
(throw (ex-info "checking requires an even number of bindings" {})))
|
||||
{:node (api/list-node
|
||||
(list*
|
||||
(api/token-node 'let)
|
||||
(api/vector-node (into [(api/token-node (symbol (gensym "_checking-desc"))) desc]
|
||||
(:children binding-vec)))
|
||||
opts
|
||||
body))}))
|
||||
@@ -1,4 +0,0 @@
|
||||
{:hooks
|
||||
{:analyze-call
|
||||
{com.gfredericks.test.chuck.clojure-test/checking
|
||||
clj-kondo.com.gfredericks.test.chuck.checking/checking}}}
|
||||
@@ -1,2 +0,0 @@
|
||||
{:lint-as
|
||||
{humane-are.core/are+ clojure.test/are}}
|
||||
@@ -1,39 +0,0 @@
|
||||
{:config-paths
|
||||
["macros"]
|
||||
|
||||
:lint-as
|
||||
{toucan2.core/build clojure.core/identity
|
||||
toucan2.core/compile clojure.core/identity
|
||||
toucan2.query/with-built-query clojure.core/let
|
||||
toucan2.tools.compile/build clojure.core/identity
|
||||
toucan2.tools.compile/compile clojure.core/identity}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
{toucan2.connection/with-connection hooks.toucan2.connection/with-connection
|
||||
toucan2.connection/with-transaction hooks.toucan2.connection/with-transaction
|
||||
toucan2.core/with-connection hooks.toucan2.connection/with-connection
|
||||
toucan2.core/with-transaction hooks.toucan2.connection/with-transaction
|
||||
toucan2.tools.simple-out-transform/define-out-transform hooks.toucan2.tools.simple-out-transform/define-out-transform
|
||||
toucan2.tools.with-temp/with-temp hooks.toucan2.tools.with-temp/with-temp}
|
||||
|
||||
:macroexpand
|
||||
{toucan.db/with-call-counting macros.toucan2.execute/with-call-count
|
||||
toucan.models/defmodel macros.toucan.models/defmodel
|
||||
toucan2.core/define-after-insert macros.toucan2.tools.after-insert/define-after-insert
|
||||
toucan2.core/define-after-select macros.toucan2.tools.helpers/define-after-select
|
||||
toucan2.core/define-after-update macros.toucan2.tools.after-update/define-after-update
|
||||
toucan2.core/define-before-delete macros.toucan2.tools.helpers/define-before-delete
|
||||
toucan2.core/define-before-insert macros.toucan2.tools.before-insert/define-before-insert
|
||||
toucan2.core/define-before-select macros.toucan2.tools.helpers/define-before-select
|
||||
toucan2.core/define-before-update macros.toucan2.tools.before-update/define-before-update
|
||||
toucan2.execute/with-call-count macros.toucan2.execute/with-call-count
|
||||
toucan2.tools.after-insert/define-after-insert macros.toucan2.tools.after-insert/define-after-insert
|
||||
toucan2.tools.after-select/define-after-select macros.toucan2.tools.helpers/define-after-select
|
||||
toucan2.tools.after-update/define-after-update macros.toucan2.tools.after-update/define-after-update
|
||||
toucan2.tools.before-delete/define-before-delete macros.toucan2.tools.helpers/define-before-delete
|
||||
toucan2.tools.before-insert/define-before-insert macros.toucan2.tools.before-insert/define-before-insert
|
||||
toucan2.tools.before-select/define-before-select macros.toucan2.tools.helpers/define-before-select
|
||||
toucan2.tools.before-update/define-before-update macros.toucan2.tools.before-update/define-before-update
|
||||
toucan2.tools.default-fields/define-default-fields macros.toucan2.tools.default-fields/define-default-fields
|
||||
toucan2.tools.named-query/define-named-query macros.toucan2.tools.named-query/define-named-query}}}
|
||||
@@ -1,14 +0,0 @@
|
||||
(ns hooks.toucan2.connection
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn with-connection [{{[_ bindings & body] :children} :node}]
|
||||
(let [[conn-binding connectable] (:children bindings)]
|
||||
{:node (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node [conn-binding (or connectable
|
||||
(hooks/token-node 'nil))])
|
||||
body))}))
|
||||
|
||||
(defn with-transaction [node]
|
||||
(with-connection node))
|
||||
@@ -1,37 +0,0 @@
|
||||
(ns hooks.toucan2.tools.simple-out-transform
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn- ignore-unused-binding [x]
|
||||
(vary-meta x assoc :clj-kondo/ignore [:unused-binding]))
|
||||
|
||||
(defn define-out-transform
|
||||
[{{[_define-out-transform dispatch-value {[instance-binding] :children, :as bindings} & body] :children, :as node} :node}]
|
||||
{:node (-> (hooks/list-node
|
||||
[(hooks/token-node 'do)
|
||||
dispatch-value
|
||||
(hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'fn)
|
||||
(-> (hooks/vector-node
|
||||
[(ignore-unused-binding (with-meta (hooks/token-node '&query-type) (meta bindings)))
|
||||
(ignore-unused-binding (with-meta (hooks/token-node '&model) (meta bindings)))
|
||||
instance-binding])
|
||||
(with-meta (meta bindings)))
|
||||
body))])
|
||||
(with-meta (meta node)))})
|
||||
|
||||
(comment
|
||||
(defn test-define-out-transform []
|
||||
(as-> '(tools.simple-out-transform/define-out-transform [:toucan.query-type/select.instances ::after-select]
|
||||
[instance]
|
||||
(let [wow 1000]
|
||||
;; don't do after-select if this select is a result of doing something like insert-returning instances
|
||||
(if (isa? &query-type :toucan2.pipeline/select.instances-from-pks)
|
||||
instance
|
||||
(after-select instance)))) <>
|
||||
(hooks/parse-string (pr-str <>))
|
||||
(define-out-transform {:node <>})
|
||||
(:node <>)
|
||||
(hooks/sexpr <>)
|
||||
(binding [*print-meta* false #_true]
|
||||
(clojure.pprint/pprint <>)))))
|
||||
@@ -1,22 +0,0 @@
|
||||
(ns hooks.toucan2.tools.with-temp
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn with-temp [{{[_with-temp {bindings :children} & body] :children} :node}]
|
||||
(let [bindings* (into
|
||||
[]
|
||||
(comp (partition-all 3)
|
||||
(mapcat (fn [[model binding attributes]]
|
||||
(let [binding (or binding (hooks/token-node '_))
|
||||
attributes (or attributes (hooks/token-node 'nil))]
|
||||
[binding (hooks/list-node
|
||||
(list
|
||||
(hooks/token-node 'do)
|
||||
model
|
||||
attributes))]))))
|
||||
bindings)
|
||||
node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node bindings*)
|
||||
body))]
|
||||
{:node node*}))
|
||||
@@ -1,5 +0,0 @@
|
||||
(ns macros.toucan.models)
|
||||
|
||||
(defmacro defmodel
|
||||
[model _table-name]
|
||||
`(def ~model "Docstring." ~(keyword (name model))))
|
||||
@@ -1,4 +0,0 @@
|
||||
(ns macros.toucan2.common)
|
||||
|
||||
(defn ignore-unused [symb]
|
||||
(vary-meta symb assoc :clj-kondo/ignore [:unused-binding]))
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns macros.toucan2.execute)
|
||||
|
||||
(defmacro with-call-count
|
||||
[[call-count-fn-binding] & body]
|
||||
`(let [~call-count-fn-binding (fn [])]
|
||||
~@body))
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns macros.toucan2.tools.after-insert
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-after-insert
|
||||
[model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&model)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns macros.toucan2.tools.after-update
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-after-update
|
||||
[model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&model)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns macros.toucan2.tools.before-insert
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-before-insert
|
||||
[model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&model)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns macros.toucan2.tools.before-update
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-before-update
|
||||
[model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&model)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns macros.toucan2.tools.default-fields
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-default-fields [model & body]
|
||||
`(let [~(common/ignore-unused '&model) ~model]
|
||||
~@body))
|
||||
@@ -1,27 +0,0 @@
|
||||
(ns macros.toucan2.tools.helpers
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
(defmacro define-before-select [dispatch-value [args-binding] & body]
|
||||
`(do
|
||||
~dispatch-value
|
||||
(fn [~(common/ignore-unused '&query-type)
|
||||
~(common/ignore-unused '&model)
|
||||
~args-binding]
|
||||
~@body)))
|
||||
|
||||
(defmacro define-after-select [model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&query-type)
|
||||
~(common/ignore-unused '&model)
|
||||
~(common/ignore-unused '&parsed-args)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
|
||||
(defmacro define-before-delete
|
||||
[model [instance-binding] & body]
|
||||
`(do
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&model)
|
||||
~instance-binding]
|
||||
~@body)))
|
||||
@@ -1,22 +0,0 @@
|
||||
(ns macros.toucan2.tools.named-query
|
||||
(:require [macros.toucan2.common :as common]))
|
||||
|
||||
;;; separate function because recursive macroexpansion doesn't seem to work.
|
||||
(defn- define-named-query*
|
||||
[query-name query-type model resolved-query]
|
||||
`(do
|
||||
~query-name
|
||||
~query-type
|
||||
~model
|
||||
(fn [~(common/ignore-unused '&query-type)
|
||||
~(common/ignore-unused '&model)
|
||||
~(common/ignore-unused '&parsed-args)
|
||||
~(common/ignore-unused '&unresolved-query)]
|
||||
~resolved-query)))
|
||||
|
||||
(defmacro define-named-query
|
||||
([query-name resolved-query]
|
||||
(define-named-query* query-name :default :default resolved-query))
|
||||
|
||||
([query-name query-type model resolved-query]
|
||||
(define-named-query* query-name query-type model resolved-query)))
|
||||
@@ -1,4 +0,0 @@
|
||||
{:linters
|
||||
{:unresolved-symbol
|
||||
{:exclude
|
||||
[(clojure.test/is [partial= re= schema= =?])]}}}
|
||||
@@ -1,5 +0,0 @@
|
||||
{:hooks
|
||||
{:analyze-call
|
||||
{next.jdbc/with-transaction
|
||||
hooks.com.github.seancorfield.next-jdbc/with-transaction}}
|
||||
:lint-as {next.jdbc/on-connection clojure.core/with-open}}
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns hooks.com.github.seancorfield.next-jdbc
|
||||
(:require [clj-kondo.hooks-api :as api]))
|
||||
|
||||
(defn with-transaction
|
||||
"Expands (with-transaction [tx expr opts] body)
|
||||
to (let [tx expr] opts body) pre clj-kondo examples."
|
||||
[{:keys [:node]}]
|
||||
(let [[binding-vec & body] (rest (:children node))
|
||||
[sym val opts] (:children binding-vec)]
|
||||
(when-not (and sym val)
|
||||
(throw (ex-info "No sym and val provided" {})))
|
||||
(let [new-node (api/list-node
|
||||
(list*
|
||||
(api/token-node 'let)
|
||||
(api/vector-node [sym val])
|
||||
opts
|
||||
body))]
|
||||
{:node new-node})))
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns hooks.com.github.seancorfield.next-jdbc
|
||||
(:require [clj-kondo.hooks-api :as api]))
|
||||
|
||||
(defn with-transaction
|
||||
"Expands (with-transaction [tx expr opts] body)
|
||||
to (let [tx expr] opts body) per clj-kondo examples."
|
||||
[{:keys [:node]}]
|
||||
(let [[binding-vec & body] (rest (:children node))
|
||||
[sym val opts] (:children binding-vec)]
|
||||
(when-not (and sym val)
|
||||
(throw (ex-info "No sym and val provided" {})))
|
||||
(let [new-node (api/list-node
|
||||
(list*
|
||||
(api/token-node 'let)
|
||||
(api/vector-node [sym val])
|
||||
opts
|
||||
body))]
|
||||
{:node new-node})))
|
||||
@@ -1,724 +1,136 @@
|
||||
{:config-paths ["macros"]
|
||||
:linters
|
||||
{:unresolved-symbol
|
||||
{:exclude
|
||||
[instaparse.core/transform
|
||||
(cljs.test/is [=?])
|
||||
(clojure.core.logic/fresh)
|
||||
(clojure.core.logic/matcha)
|
||||
(clojure.core.logic/run)
|
||||
(clojure.test/is [query= sql= =?])
|
||||
(clojure.tools.macro/macrolet)
|
||||
(metabase.async.streaming-response/streaming-response)
|
||||
(metabase.driver.druid.query-processor-test/druid-query-returning-rows)
|
||||
(metabase.mbql.util.match/match)
|
||||
(metabase.mbql.util.match/match-one)
|
||||
(metabase.mbql.util.match/replace)
|
||||
(metabase.mbql.util.match/replace-in)
|
||||
(metabase.mbql.util/match)
|
||||
(metabase.mbql.util/match-one)
|
||||
(metabase.mbql.util/replace)
|
||||
(metabase.mbql.util/replace-in)
|
||||
(metabase.query-processor.middleware.cache-backend.interface/with-cached-results)
|
||||
(metabase.util.regex/rx [opt])
|
||||
(metabase.util/prog1 [<>])
|
||||
(taoensso.nippy/extend-freeze)
|
||||
(taoensso.nippy/extend-thaw)]}
|
||||
:linters {:unresolved-symbol
|
||||
{:exclude [schema= re=
|
||||
(metabase.util/prog1 [<>])
|
||||
(metabase.mbql.util/match-one)
|
||||
(metabase.mbql.util/match)
|
||||
(metabase.mbql.util.match/match)
|
||||
(metabase.mbql.util.match/match-one)
|
||||
(metabase.mbql.util.match/replace)
|
||||
(metabase.mbql.util/replace)
|
||||
(metabase.mbql.util/replace-in)
|
||||
(metabase.query-processor.middleware.cache-backend.interface/with-cached-results)
|
||||
(metabase.util.regex/rx [opt])
|
||||
(metabase.async.streaming-response/streaming-response)
|
||||
(clojure.core.logic/fresh)
|
||||
(clojure.core.logic/matcha)
|
||||
(clojure.core.logic/run)
|
||||
(metabase.test/with-temporary-setting-values)
|
||||
(clojure.test/is [query= sql=])
|
||||
(toucan.util.test/with-temp*)
|
||||
(metabase.test/with-temp*)
|
||||
(taoensso.nippy/extend-freeze)
|
||||
(taoensso.nippy/extend-thaw)
|
||||
(metabase.driver.druid.query-processor-test/druid-query-returning-rows)
|
||||
(clojure.tools.macro/macrolet)]}
|
||||
:refer-all {:exclude [clojure.test
|
||||
monger.operators]}
|
||||
:unexpected-recur {:level :off}
|
||||
:unused-referred-var {:exclude {compojure.core [GET DELETE POST PUT]}}
|
||||
:deprecated-var {:exclude {metabase.query-processor.util/normalize-token
|
||||
{:namespaces ["metabase.*"]}
|
||||
metabase.driver/supports?
|
||||
{:namespaces ["metabase.*"]}
|
||||
metabase.driver/current-db-time
|
||||
{:namespaces ["metabase.*"]}
|
||||
metabase.driver.common/current-db-time-native-query
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/current-db-time-date-formatters
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute.old-impl/read-column
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/first-successful-parse
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/ThreadSafeSimpleDateFormat
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/create-db-time-formatters
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/current-db-time
|
||||
{:namespaces ["metabase.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/*field-options*
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/*source-query*
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/field->identifier
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/field->alias
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/prefix-field-alias
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.query-processor.middleware.resolve-joins/maybe-resolve-source-table
|
||||
{:namespaces ["metabase.*"]}
|
||||
metabase.driver.sql-jdbc.execute.old-impl/set-timezone-sq
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute.old-impl/set-timezone-sql
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/*table-alias*
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.public-settings.premium-features/enable-enhancements?
|
||||
{:namespaces ["metabase\\.models.*"]}
|
||||
metabase.driver.sql.query-processor.deprecated/escape-alias
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute/set-time-zone-if-supported!
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.sync.interface/syncable-schemas
|
||||
{:namespaces ["metabase\\.driver.*"]}
|
||||
schema.core/either
|
||||
{:namespaces ["metabase.*"]}
|
||||
schema.core/both
|
||||
{:namespaces ["metabase.*"]}}}
|
||||
:unresolved-var {:exclude [colorize.core]}}
|
||||
:lint-as {metabase.api.common/let-404 clojure.core/let
|
||||
metabase.db.data-migrations/defmigration clojure.core/def
|
||||
metabase.query-processor.error-type/deferror clojure.core/def
|
||||
metabase.models.setting/defsetting clj-kondo.lint-as/def-catch-all
|
||||
metabase.mbql.schema.macros/defclause clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/define-premium-feature clojure.core/def
|
||||
metabase.sync.util/sum-for clojure.core/for
|
||||
metabase.sync.util/with-emoji-progress-bar clojure.core/let
|
||||
metabase.driver.sql-jdbc.execute.diagnostic/capturing-diagnostic-info clojure.core/fn
|
||||
metabase.util.files/with-open-path-to-resource clojure.core/let
|
||||
metabase.util.ssh/with-ssh-tunnel clojure.core/let
|
||||
metabase.db.liquibase/with-liquibase clojure.core/let
|
||||
metabase.models.setting.multi-setting/define-multi-setting clojure.core/def
|
||||
metabase.integrations.ldap/with-ldap-connection clojure.core/fn
|
||||
metabase.test/defdataset clojure.core/def
|
||||
metabase.test/with-temp-file clojure.core/let
|
||||
metabase.test/with-open-channels clojure.core/let
|
||||
metabase.test.data.interface/defdataset clojure.core/def
|
||||
metabase.test.data.interface/defdataset-edn clojure.core/def
|
||||
metabase.driver.mongo.util/with-mongo-connection clojure.core/let
|
||||
metabase.driver.mongo.query-processor/mongo-let clojure.core/let
|
||||
toucan.db/with-call-counting clojure.core/fn
|
||||
|
||||
:refer-all {:level :warning
|
||||
:exclude [clojure.test]}
|
||||
;; TODO (cam): I think we just need to tell it how to handle MBQL match and we can enable this?
|
||||
:unexpected-recur {:level :off}
|
||||
;; TODO (cam): can we fix these?
|
||||
:unused-referred-var {:exclude {compojure.core [GET DELETE POST PUT]}}
|
||||
:missing-else-branch {:level :warning}
|
||||
:misplaced-docstring {:level :warning}
|
||||
:non-arg-vec-return-type-hint {:level :warning}
|
||||
:missing-body-in-when {:level :warning}
|
||||
:missing-docstring {:level :warning}
|
||||
;; TODO (braden): This is useful, but it doesn't grok eg. enterprise/backend/src
|
||||
:namespace-name-mismatch {:level :off}
|
||||
:use {:level :warning}
|
||||
:redundant-fn-wrapper {:level :warning}
|
||||
:invalid-arity {:skip-args [metabase.mbql.util.match/match]}
|
||||
:warn-on-reflection {:level :warning}
|
||||
;; TODO (cam): here are some more linters we should experiment with enabling -- some might be useful.
|
||||
;; :docstring-no-summary {:level :warning}
|
||||
;; :docstring-leading-trailing-whitespace {:level :warning}
|
||||
;; :reduce-without-init {:level :warning}
|
||||
;; :used-underscored-binding {:level :warning}
|
||||
;; :single-key-in {:level :warning}
|
||||
;; :keyword-binding {:level :warning}
|
||||
;; :main-without-gen-class {:level :warning}
|
||||
;; :shadowed-var {:level :warning}
|
||||
potemkin.types/defprotocol+ clojure.core/defprotocol
|
||||
potemkin/defprotocol+ clojure.core/defprotocol
|
||||
potemkin.types/defrecord+ clojure.core/defrecord
|
||||
potemkin/defrecord+ clojure.core/defrecord
|
||||
potemkin.types/deftype+ clojure.core/deftype
|
||||
potemkin/deftype+ clojure.core/deftype
|
||||
clojurewerkz.quartzite.jobs/defjob clojure.core/defn
|
||||
honeysql.util/defalias clojure.core/def
|
||||
honeysql.helpers/defhelper clj-kondo.lint-as/def-catch-all
|
||||
clojure.core.logic/defne clj-kondo.lint-as/def-catch-all
|
||||
monger.operators/defoperator clojure.core/def}
|
||||
:hooks {:analyze-call {metabase.test.data/dataset hooks.metabase.test.data/dataset
|
||||
metabase.test/dataset hooks.metabase.test.data/dataset
|
||||
metabase.test.data/$ids hooks.metabase.test.data/$ids
|
||||
metabase.test/$ids hooks.metabase.test.data/$ids
|
||||
metabase.test.data/mbql-query hooks.metabase.test.data/$ids
|
||||
metabase.test/mbql-query hooks.metabase.test.data/$ids
|
||||
metabase.test/data-query hooks.metabase.test.data/$ids
|
||||
metabase.test/query hooks.metabase.test.data/$ids
|
||||
metabase.test/run-mbql-query hooks.metabase.test.data/$ids
|
||||
metabase.test.data/run-mbql-query hooks.metabase.test.data/$ids
|
||||
metabase.api.common/defendpoint hooks.metabase.api.common/defendpoint
|
||||
metabase.api.common/defendpoint-async hooks.metabase.api.common/defendpoint
|
||||
|
||||
:deprecated-var
|
||||
{:exclude
|
||||
{metabase.cmd/dump {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
metabase.cmd/load {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
metabase.db.data-migrations/data-migrations {:namespaces ["metabase\\.db\\.data-migrations"]}
|
||||
metabase.db.data-migrations/defmigration {:namespaces ["metabase\\.db\\.data-migrations"]}
|
||||
metabase.db.data-migrations/run-migration-if-needed! {:namespaces ["metabase\\.db\\.data-migrations"]}
|
||||
metabase.driver.common/ThreadSafeSimpleDateFormat {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/create-db-time-formatters {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/current-db-time {:namespaces ["metabase.*"]}
|
||||
metabase.driver.common/current-db-time-date-formatters {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/current-db-time-native-query {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.common/first-successful-parse {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute.old-impl/set-timezone-sql {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute/set-time-zone-if-supported! {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver/current-db-time {:namespaces ["metabase.*"]}
|
||||
metabase.driver/supports? {:namespaces ["metabase.*"]}
|
||||
metabase.public-settings.premium-features/enable-enhancements? {:namespaces ["metabase\\.models.*"]}
|
||||
metabase.query-processor.middleware.resolve-joins/maybe-resolve-source-table {:namespaces ["metabase.*"]}
|
||||
metabase.query-processor.util/normalize-token {:namespaces ["metabase.*"]}
|
||||
metabase.util.honeysql-extensions/* {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/*honey-sql-version* {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/+ {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/- {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->boolean {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->date {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->datetime {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->integer {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->time {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->timestamp {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/->timestamp-with-time-zone {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions// {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/IdentifierType {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/abs {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/at-time-zone {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/call {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/cast {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/cast-unless-type-in {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/ceil {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/concat {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/database-type {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/day {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/dec {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/floor {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/format {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/hour {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/identifier {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/identifier? {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/inc {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/is-of-type? {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/literal {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/maybe-cast {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/minute {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/mod {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/month {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/quarter {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/quoted-cast {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/raw {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/round {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/second {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/type-info {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/type-info->db-type {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/unwrap-typed-honeysql-form {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/week {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/with-database-type-info {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/with-type-info {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
metabase.util.honeysql-extensions/year {:namespaces ["^metabase\\.driver\\..*$" "^metabase\\.test\\.data\\..*" "^metabase\\.query-processor-test\\..*$"]}
|
||||
schema.core/both {:namespaces ["metabase.*"]}
|
||||
schema.core/either {:namespaces ["metabase.*"]}}}
|
||||
|
||||
:discouraged-var
|
||||
{clojure.core/print {:message "Use clojure.tools.logging instead of clojure.core/print"}
|
||||
clojure.core/println {:message "Use clojure.tools.logging instead of clojure.core/println"}
|
||||
clojure.core/printf {:message "Use clojure.tools.logging instead of clojure.core/printf"}
|
||||
clojure.core/prn {:message "Use clojure.tools.logging instead of clojure.core/prn"}
|
||||
clojure.core/pr {:message "Use clojure.tools.logging instead of clojure.core/pr"}
|
||||
clojure.pprint/pprint {:message "Use clojure.tools.logging instead of clojure.pprint/pprint"}
|
||||
clojure.string/lower-case {:message "Use metabase.util/lower-case-en instead of clojure.string/lower-case"}
|
||||
clojure.string/upper-case {:message "Use metabase.util/upper-case-en instead of clojure.string/upper-case"}
|
||||
honeysql.core/call {:message "Use hx/call instead because it is Honey SQL 2 friendly"}
|
||||
honeysql.core/raw {:message "Use hx/raw instead because it is Honey SQL 2 friendly"}
|
||||
java-time/with-clock {:message "Use mt/with-clock"}
|
||||
toucan.db/select {:message "Use t2/select instead of toucan.db/select"}
|
||||
toucan.db/select-one {:message "Use t2/select-one instead of toucan.db/select-one"}
|
||||
toucan.db/select-one-id {:message "Use t2/select-one-pk instead of toucan.db/select-one-id"}
|
||||
toucan.db/select-one-field {:message "Use t2/select-one-fn instead of toucan.db/select-one-field"}
|
||||
toucan.db/select-ids {:message "Use t2/select-pks-set instead of toucan.db/select-ids"}
|
||||
toucan.db/select-field {:message "Use t2/select-fn instead of toucan.db/select-field"}
|
||||
toucan.db/select-field->field {:message "Use t2/select-fn->fn instead of toucan.db/select-field->field"}
|
||||
toucan.db/select-field->id {:message "Use t2/select-fn->pk instead of toucan.db/select-field->id"}
|
||||
toucan.db/select-id->field {:message "Use t2/select-pk->field instead of toucan.db/select-id->field"}
|
||||
toucan.db/simple-insert! {:message "Use t2/insert-returning-pks! with table name instead of toucan.db/simple-insert!"}
|
||||
toucan.db/simple-insert-many! {:message "Use t2/insert-returning-pks! with table name instead of toucan.db/simple-insert-many!"}
|
||||
toucan.db/simple-delete! {:message "Use t2/delete! with table name instead of toucan.db/simple-delete!"}
|
||||
toucan.db/delete! {:message "Use t2/delete! instead of toucan.db/delete!"}
|
||||
toucan.db/insert! {:message "Use t2/insert-returning-instances! instead of toucan.db/insert!"}
|
||||
toucan.db/update! {:message "Use t2/update! instead of toucan.db/update!"}
|
||||
toucan.db/update-where! {:message "Use t2/update! instead of toucan.db/update-where!"}
|
||||
toucan.db/query {:message "Use mdb.query/query instead of toucan.db/query"}
|
||||
toucan.db/count {:message "Use t2/count instead of toucan.db/count"}
|
||||
toucan.db/exists? {:message "Use t2/exists? instead of toucan.db/exists?"}
|
||||
toucan.db/transaction {:message "Use t2/with-transaction instead of toucan.db/transaction"}
|
||||
toucan.db/with-call-counting {:message "Use t2/with-call-count instead of toucan.db/with-call-counting"}
|
||||
toucan.db/execute! {:message "Use t2/query-one instead of toucan.db/execute!"}
|
||||
toucan.db/reducible-query {:message "Use mdb.query/reducible-query instead of toucan.db/reducible-query"}
|
||||
toucan.db/resolve-model {:message "Use metabase.db.util/resolve-model instead of toucan.db/resolve-model"}
|
||||
toucan.models/primary-key {:message "Use metabase.db.util/primary-key instead of toucan.models/primary-key"}}
|
||||
|
||||
:discouraged-namespace
|
||||
{clojure.tools.logging {:message "Use metabase.util.log instead of clojure.tools.logging directly"}
|
||||
metabase.util.jvm {:message "All of metabase.util.jvm is re-exported from metabase.util; prefer that"}}
|
||||
|
||||
:unresolved-var
|
||||
{:exclude
|
||||
[colorize.core]}
|
||||
|
||||
:unsorted-required-namespaces {:level :warning}
|
||||
|
||||
:consistent-alias
|
||||
{:aliases
|
||||
{buddy.core.hash buddy-hash
|
||||
cheshire.generate json.generate
|
||||
clojure.tools.logging log
|
||||
clj-http.client http
|
||||
clj-ldap.client ldap
|
||||
clj-time.coerce time.coerce
|
||||
clj-time.format time.format
|
||||
clojure.core.async a
|
||||
clojure.core.match clojure.core.match ; Prefer :refer [match]
|
||||
clojure.data data
|
||||
clojure.math.combinatorics math.combo
|
||||
clojure.pprint pprint
|
||||
clojure.spec.alpha s
|
||||
clojure.string str
|
||||
clojure.test t
|
||||
clojure.tools.build.api b
|
||||
clojure.tools.namespace.dependency ns.deps
|
||||
clojure.tools.namespace.find ns.find
|
||||
clojure.tools.namespace.parse ns.parse
|
||||
colorize.core colorize
|
||||
environ.core env
|
||||
hf.depstar.api depstar
|
||||
hiccup.core hiccup
|
||||
hiccup.util hiccup.util
|
||||
honey.sql sql
|
||||
honey.sql.helpers sql.helpers
|
||||
honeysql.core hsql
|
||||
honeysql.format hformat
|
||||
honeysql.helpers hh
|
||||
honeysql.types htypes
|
||||
java-time t
|
||||
malli.core mc
|
||||
malli.error me
|
||||
malli.experimental mx
|
||||
malli.generator mg
|
||||
malli.provider mp
|
||||
malli.transform mtx
|
||||
malli.util mut
|
||||
medley.core m
|
||||
metabase-enterprise.audit-app.pages.common common
|
||||
metabase-enterprise.sandbox.api.table table
|
||||
metabase-enterprise.test met
|
||||
metabase.analytics.stats stats
|
||||
metabase.api.activity api.activity
|
||||
metabase.api.alert api.alert
|
||||
metabase.api.automagic-dashboards api.magic
|
||||
metabase.api.bookmark api.bookmark
|
||||
metabase.api.card api.card
|
||||
metabase.api.card-test api.card-test
|
||||
metabase.api.collection api.collection
|
||||
metabase.api.common api
|
||||
metabase.api.dashboard api.dashboard
|
||||
metabase.api.dashboard-test api.dashboard-test
|
||||
metabase.api.database api.database
|
||||
metabase.api.dataset api.dataset
|
||||
metabase.api.email api.email
|
||||
metabase.api.embed api.embed
|
||||
metabase.api.field api.field
|
||||
metabase.api.geojson api.geojson
|
||||
metabase.api.ldap api.ldap
|
||||
metabase.api.logic-history api.login-history
|
||||
metabase.api.metric api.metric
|
||||
metabase.api.native-query-snippet api.native-query-snippet
|
||||
metabase.api.notify api.notify
|
||||
metabase.api.permission-graph api.permission-graph
|
||||
metabase.api.permissions api.permissions
|
||||
metabase.api.pivots api.pivots
|
||||
metabase.api.premium-features api.premium-features
|
||||
metabase.api.preview-embed api.preview-embed
|
||||
metabase.api.public api.public
|
||||
metabase.api.pulse api.pulse
|
||||
metabase.api.revision api.revision
|
||||
metabase.api.search api.search
|
||||
metabase.api.segment api.segment
|
||||
metabase.api.session api.session
|
||||
metabase.api.setting api.setting
|
||||
metabase.api.setup api.setup
|
||||
metabase.api.slack api.slack
|
||||
metabase.api.table api.table
|
||||
metabase.api.task api.task
|
||||
metabase.api.tiles api.tiles
|
||||
metabase.api.timeline api.timeline
|
||||
metabase.api.timeline-event api.timeline-event
|
||||
metabase.api.transform api.transform
|
||||
metabase.api.user api.user
|
||||
metabase.api.util api.util
|
||||
metabase.async.streaming-response.thread-pool thread-pool
|
||||
metabase.automagic-dashboards.core magic
|
||||
metabase.automagic-dashboards.populate populate
|
||||
metabase.cmd.copy.h2 copy.h2
|
||||
metabase.config config
|
||||
metabase.config.file config.file
|
||||
metabase.connection-pool connection-pool
|
||||
metabase.db.connection mdb.connection
|
||||
metabase.db.jdbc-protocols mdb.jdbc-protocols
|
||||
metabase.db.metadata-queries metadata-queries
|
||||
metabase.db.spec mdb.spec
|
||||
metabase.db.query mdb.query
|
||||
metabase.domain-entities.specs de.specs
|
||||
metabase.driver.common.parameters params
|
||||
metabase.driver.common.parameters.dates params.dates
|
||||
metabase.driver.common.parameters.operators params.ops
|
||||
metabase.driver.common.parameters.parse params.parse
|
||||
metabase.driver.common.parameters.values params.values
|
||||
metabase.driver.druid.client druid.client
|
||||
metabase.driver.druid.execute druid.execute
|
||||
metabase.driver.druid.js druid.js
|
||||
metabase.driver.druid.query-processor druid.qp
|
||||
metabase.driver.druid.sync druid.sync
|
||||
metabase.driver.googleanalytics.client ga.client
|
||||
metabase.driver.googleanalytics.execute ga.execute
|
||||
metabase.driver.googleanalytics.metadata ga.metadata
|
||||
metabase.driver.googleanalytics.query-processor ga.qp
|
||||
metabase.driver.impl driver.impl
|
||||
metabase.driver.mongo.execute mongo.execute
|
||||
metabase.driver.mongo.parameters mongo.params
|
||||
metabase.driver.mongo.query-processor mongo.qp
|
||||
metabase.driver.mongo.util mongo.util
|
||||
metabase.driver.sql driver.sql
|
||||
metabase.driver.sql-jdbc.common sql-jdbc.common
|
||||
metabase.driver.sql-jdbc.connection sql-jdbc.conn
|
||||
metabase.driver.sql-jdbc.execute sql-jdbc.execute
|
||||
metabase.driver.sql-jdbc.execute.diagnostic sql-jdbc.execute.diagnostic
|
||||
metabase.driver.sql-jdbc.execute.legacy-impl sql-jdbc.legacy
|
||||
metabase.driver.sql-jdbc.execute.old-impl sql-jdbc.execute.old
|
||||
metabase.driver.sql-jdbc.sync sql-jdbc.sync
|
||||
metabase.driver.sql-jdbc.sync.common sql-jdbc.sync.common
|
||||
metabase.driver.sql-jdbc.sync.describe-database sql-jdbc.describe-database
|
||||
metabase.driver.sql-jdbc.sync.describe-table sql-jdbc.describe-table
|
||||
metabase.driver.sql-jdbc.sync.interface sql-jdbc.sync.interface
|
||||
metabase.driver.sql-jdbc.test-util sql-jdbc.tu
|
||||
metabase.driver.sql.parameters.substitute sql.params.substitute
|
||||
metabase.driver.sql.parameters.substitution sql.params.substitution
|
||||
metabase.email-test et
|
||||
metabase.email.messages messages
|
||||
metabase.http-client client
|
||||
metabase.mbql.normalize mbql.normalize
|
||||
metabase.mbql.schema mbql.s
|
||||
metabase.mbql.util mbql.u
|
||||
metabase.models.activity activity
|
||||
metabase.models.application-permissions-revision a-perm-revision
|
||||
metabase.models.bookmark bookmark
|
||||
metabase.models.collection collection
|
||||
metabase.models.collection.graph graph
|
||||
metabase.models.collection-permission-graph-revision c-perm-revision
|
||||
metabase.models.dashboard-card dashboard-card
|
||||
metabase.models.database database
|
||||
metabase.models.dependency dependency
|
||||
metabase.models.field-values field-values
|
||||
metabase.models.interface mi
|
||||
metabase.models.moderation-review moderation-review
|
||||
metabase.models.native-query-snippet native-query-snippet
|
||||
metabase.models.permissions perms
|
||||
metabase.models.permissions-group perms-group
|
||||
metabase.models.permissions-group-membership perms-group-membership
|
||||
metabase.models.permissions-revision perms-revision
|
||||
metabase.models.permissions.parse perms-parse
|
||||
metabase.models.pulse pulse
|
||||
metabase.models.pulse-channel pulse-channel
|
||||
metabase.models.pulse-channel-recipient pulse-channel-recipient
|
||||
metabase.models.query.permissions query-perms
|
||||
metabase.models.setting.cache setting.cache
|
||||
metabase.models.timeline timeline
|
||||
metabase.models.timeline-event timeline-event
|
||||
metabase.plugins.initialize plugins.init
|
||||
metabase.public-settings public-settings
|
||||
metabase.public-settings.premium-features premium-features
|
||||
metabase.pulse pulse ; NB some conflicts with metabase.models.pulse
|
||||
metabase.pulse.markdown markdown
|
||||
metabase.pulse.render render
|
||||
metabase.pulse.render.body body
|
||||
metabase.pulse.render.common common
|
||||
metabase.pulse.render.style style
|
||||
metabase.query-processor-test qp.test
|
||||
metabase.query-processor.context qp.context
|
||||
metabase.query-processor.error-type qp.error-type
|
||||
metabase.query-processor.interface qp.i
|
||||
metabase.query-processor.middleware.add-dimension-projections qp.add-dimension-projections
|
||||
metabase.query-processor.middleware.add-implicit-clauses qp.add-implicit-clauses
|
||||
metabase.query-processor.middleware.add-implicit-joins qp.add-implicit-joins
|
||||
metabase.query-processor.middleware.auto-bucket-datetimes qp.auto-bucket-datetimes
|
||||
metabase.query-processor.middleware.constraints qp.constraints
|
||||
metabase.query-processor.middleware.cumulative-aggregations qp.cumulative-aggregations
|
||||
metabase.query-processor.middleware.parameters.mbql qp.mbql
|
||||
metabase.query-processor.middleware.parameters.native qp.native
|
||||
metabase.query-processor.middleware.permissions qp.perms
|
||||
metabase.query-processor.middleware.pre-alias-aggregations qp.pre-alias-aggregations
|
||||
metabase.query-processor.middleware.resolve-database-and-driver qp.resolve-database-and-driver
|
||||
metabase.query-processor.middleware.resolve-fields qp.resolve-fields
|
||||
metabase.query-processor.middleware.resolve-referenced qp.resolve-referenced
|
||||
metabase.query-processor.middleware.resolve-source-table qp.resolve-source-table
|
||||
metabase.query-processor.middleware.wrap-value-literals qp.wrap-value-literals
|
||||
metabase.query-processor.pivot qp.pivot
|
||||
metabase.query-processor.streaming qp.streaming
|
||||
metabase.query-processor.streaming.interface qp.si
|
||||
metabase.query-processor.streaming.xlsx qp.xlsx
|
||||
metabase.query-processor.timezone qp.timezone
|
||||
metabase.query-processor.util qp.util
|
||||
metabase.related related
|
||||
metabase.search.scoring scoring
|
||||
metabase.server.middleware.auth mw.auth
|
||||
metabase.server.middleware.browser-cookie mw.browser-cookie
|
||||
metabase.server.middleware.exceptions mw.exceptions
|
||||
metabase.server.middleware.json mw.json
|
||||
metabase.server.middleware.log mw.log
|
||||
metabase.server.middleware.misc mw.misc
|
||||
metabase.server.middleware.offset-paging mw.offset-paging
|
||||
metabase.server.middleware.security mw.security
|
||||
metabase.server.middleware.session mw.session
|
||||
metabase.server.middleware.ssl mw.ssl
|
||||
metabase.server.middleware.util mw.util
|
||||
metabase.server.protocols server.protocols
|
||||
metabase.shared.util shared.u
|
||||
metabase.shared.util.currency currency
|
||||
metabase.sync.analyze.classifiers.category classifiers.category
|
||||
metabase.sync.analyze.classifiers.name classifiers.name
|
||||
metabase.sync.analyze.classifiers.no-preview-display classifiers.no-preview-display
|
||||
metabase.sync.analyze.classifiers.text-fingerprint classifiers.text-fingerprint
|
||||
metabase.sync.analyze.fingerprint fingerprint
|
||||
metabase.sync.analyze.fingerprint.fingerprinters fingerprinters
|
||||
metabase.sync.analyze.fingerprint.insights insights
|
||||
metabase.sync.analyze.query-results qr
|
||||
metabase.sync.field-values field-values
|
||||
metabase.sync.interface i
|
||||
metabase.sync.schedules sync.schedules
|
||||
metabase.sync.sync-metadata.fields.fetch-metadata fetch-metadata
|
||||
metabase.sync.util sync-util
|
||||
metabase.sync.util-test sync.util-test
|
||||
metabase.task.sync-databases task.sync-databases
|
||||
metabase.test mt
|
||||
metabase.test.data.dataset-definitions defs
|
||||
metabase.test.data.env.impl tx.env.impl
|
||||
metabase.test.data.impl data.impl
|
||||
metabase.test.data.users test.users
|
||||
metabase.test.domain-entities test.de
|
||||
metabase.test.mock.util mock.util
|
||||
metabase.test.sync test.sync
|
||||
metabase.test.util.js test.js
|
||||
metabase.test.util.timezone test.tz
|
||||
metabase.timeseries-query-processor-test.util tqpt
|
||||
metabase.transforms.core tf
|
||||
metabase.transforms.materialize tf.materialize
|
||||
metabase.transforms.specs tf.specs
|
||||
metabase.util.cron u.cron
|
||||
metabase.util.date-2 u.date
|
||||
metabase.util.date-2.common u.date.common
|
||||
metabase.util.date-2.parse u.date.parse
|
||||
metabase.util.embed embed
|
||||
metabase.util.encryption encryption
|
||||
metabase.util.encryption-test encryption-test
|
||||
metabase.util.files u.files
|
||||
metabase.util.honey-sql-1 h1x
|
||||
metabase.util.honey-sql-2 h2x
|
||||
metabase.util.honeysql-extensions hx
|
||||
metabase.util.i18n i18n
|
||||
metabase.util.i18n.impl i18n.impl
|
||||
metabase.util.jvm u.jvm
|
||||
metabase.util.log log
|
||||
metabase.util.macros u.macros
|
||||
metabase.util.malli mu
|
||||
metabase.util.malli.schema ms
|
||||
metabase.util.password u.password
|
||||
metabase.util.schema su
|
||||
metabase.util.ui-logic ui-logic
|
||||
metabase.util.urls urls
|
||||
metabuild-common.core u
|
||||
metabuild-common.output out
|
||||
metabuild-common.shell shell
|
||||
monger.collection mcoll
|
||||
ring.mock.request ring.mock
|
||||
ring.util.codec codec
|
||||
ring.util.response response
|
||||
ring.adapter.jetty9.servlet servlet
|
||||
saml20-clj.core saml
|
||||
toucan.db db
|
||||
toucan.models models}}
|
||||
|
||||
:metabase/disallow-invoking-model {:level :warning}
|
||||
:metabase/disallow-class-or-type-on-model {:level :warning}}
|
||||
|
||||
:lint-as
|
||||
{clojure.core.logic/defne clj-kondo.lint-as/def-catch-all
|
||||
clojure.test.check.clojure-test/defspec clojure.test/deftest
|
||||
clojurewerkz.quartzite.jobs/defjob clojure.core/defn
|
||||
honeysql.helpers/defhelper clj-kondo.lint-as/def-catch-all
|
||||
honeysql.util/defalias clojure.core/def
|
||||
metabase-enterprise.serialization.test-util/with-random-dump-dir clojure.core/let
|
||||
metabase.actions.test-util/with-actions clojure.core/let
|
||||
metabase.api.common/let-404 clojure.core/let
|
||||
metabase.api.dashboard-test/let-url clojure.core/let
|
||||
metabase.api.search-test/do-test-users clojure.core/let
|
||||
metabase.async.api-response-test/with-response clojure.core/let
|
||||
metabase.dashboard-subscription-test/with-dashboard-sub-for-card clojure.core/let
|
||||
metabase.db.custom-migrations/define-migration clj-kondo.lint-as/def-catch-all
|
||||
metabase.db.custom-migrations/define-reversible-migration clj-kondo.lint-as/def-catch-all
|
||||
metabase.db.data-migrations/defmigration clojure.core/def
|
||||
metabase.db.liquibase/with-liquibase clojure.core/let
|
||||
metabase.db.schema-migrations-test.impl/with-temp-empty-app-db clojure.core/let
|
||||
metabase.domain-entities.malli/defn schema.core/defn
|
||||
metabase.driver.mongo.query-processor/mongo-let clojure.core/let
|
||||
metabase.driver.mongo.util/with-mongo-connection clojure.core/let
|
||||
metabase.driver.sql-jdbc.actions/with-jdbc-transaction clojure.core/let
|
||||
metabase.driver.sql-jdbc.connection/with-connection-spec-for-testing-connection clojure.core/let
|
||||
metabase.driver.sql-jdbc.execute.diagnostic/capturing-diagnostic-info clojure.core/fn
|
||||
metabase.integrations.ldap/with-ldap-connection clojure.core/fn
|
||||
metabase.mbql.schema.macros/defclause clj-kondo.lint-as/def-catch-all
|
||||
metabase.models.collection-test/with-collection-in-location clojure.core/let
|
||||
metabase.models.json-migration/def-json-migration clj-kondo.lint-as/def-catch-all
|
||||
metabase.models.setting.multi-setting/define-multi-setting clojure.core/def
|
||||
metabase.models.setting/defsetting clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/defenterprise clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/defenterprise-schema clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/define-premium-feature clojure.core/def
|
||||
metabase.pulse-test/with-pulse-for-card clojure.core/let
|
||||
metabase.query-processor.error-type/deferror clojure.core/def
|
||||
metabase.query-processor.middleware.cache.impl/with-reducible-deserialized-results clojure.core/let
|
||||
metabase.query-processor.middleware.process-userland-query-test/with-query-execution clojure.core/let
|
||||
metabase.query-processor-test.pipeline-queries-test/pmbql-query clojure.core/->
|
||||
metabase.query-processor-test.pipeline-queries-test/run-pmbql-query clojure.core/->
|
||||
metabase.shared.util.namespaces/import-fns potemkin/import-vars
|
||||
metabase.sync.util/sum-for clojure.core/for
|
||||
metabase.sync.util/with-emoji-progress-bar clojure.core/let
|
||||
metabase.test.data.interface/defdataset clojure.core/def
|
||||
metabase.test.data.interface/defdataset-edn clojure.core/def
|
||||
metabase.test/defdataset clojure.core/def
|
||||
metabase.test/with-actions clojure.core/let
|
||||
metabase.test/with-open-channels clojure.core/let
|
||||
metabase.test/with-single-admin-user clojure.core/fn
|
||||
metabase.test/with-temp-dir clojure.core/let
|
||||
metabase.test/with-temp-file clojure.core/let
|
||||
metabase.test/with-user-in-groups clojure.core/let
|
||||
metabase.util.files/with-open-path-to-resource clojure.core/let
|
||||
metabase.util.malli/defn schema.core/defn
|
||||
metabase.util.ssh/with-ssh-tunnel clojure.core/let
|
||||
monger.operators/defoperator clojure.core/def
|
||||
potemkin.types/defprotocol+ clojure.core/defprotocol
|
||||
potemkin.types/defrecord+ clojure.core/defrecord
|
||||
potemkin.types/deftype+ clojure.core/deftype
|
||||
potemkin/defprotocol+ clojure.core/defprotocol
|
||||
potemkin/defrecord+ clojure.core/defrecord
|
||||
potemkin/deftype+ clojure.core/deftype
|
||||
toucan.db/with-call-counting clojure.core/fn
|
||||
toucan2.core/with-call-count clojure.core/fn}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
{clojure.test/deftest hooks.clojure.test/deftest
|
||||
metabase-enterprise.advanced-permissions.models.permissions.application-permissions-test/with-new-group-and-current-graph hooks.common/with-two-top-level-bindings
|
||||
metabase-enterprise.audit-app.pages-test/with-temp-objects hooks.common/with-one-binding
|
||||
metabase-enterprise.serialization.test-util/with-temp-dpc hooks.toucan.util.test/with-temp*
|
||||
metabase.analytics.prometheus-test/with-prometheus-system hooks.common/with-two-bindings
|
||||
metabase.api.alert-test/with-alert-in-collection hooks.common/with-four-bindings
|
||||
metabase.api.card-test/with-persistence-setup hooks.common/with-one-top-level-binding
|
||||
metabase.api.card-test/with-temp-native-card hooks.common/with-two-bindings
|
||||
metabase.api.card-test/with-temp-native-card-with-params hooks.common/with-two-bindings
|
||||
metabase.api.collection-test/with-french-user-and-personal-collection hooks.common/with-two-top-level-bindings
|
||||
metabase.api.common/defendpoint hooks.metabase.api.common/defendpoint
|
||||
metabase.api.common/defendpoint-async hooks.metabase.api.common/defendpoint
|
||||
metabase.api.common/defendpoint-async-schema hooks.metabase.api.common/defendpoint
|
||||
metabase.api.common/defendpoint-schema hooks.metabase.api.common/defendpoint
|
||||
metabase.api.dashboard-test/with-chain-filter-fixtures hooks.common/let-one-with-optional-value
|
||||
metabase.api.card-test/with-card-param-values-fixtures hooks.common/let-one-with-optional-value
|
||||
metabase.api.embed-test/do-response-formats hooks.common/with-two-bindings
|
||||
metabase.api.embed-test/with-chain-filter-fixtures hooks.common/let-one-with-optional-value
|
||||
metabase.api.embed-test/with-temp-card hooks.common/let-one-with-optional-value
|
||||
metabase.api.embed-test/with-temp-dashcard hooks.common/let-one-with-optional-value
|
||||
metabase.api.persist-test/with-setup hooks.common/with-one-top-level-binding
|
||||
metabase.api.public-test/with-required-param-card hooks.common/with-one-binding
|
||||
metabase.api.public-test/with-temp-public-card hooks.common/let-one-with-optional-value
|
||||
metabase.api.public-test/with-temp-public-dashboard hooks.common/let-one-with-optional-value
|
||||
metabase.api.public-test/with-temp-public-dashboard-and-card hooks.common/with-three-bindings
|
||||
metabase.api.search-test/with-search-items-in-collection hooks.metabase.api.search-test/with-search-items-in-collection
|
||||
metabase.api.search-test/with-search-items-in-root-collection hooks.common/do*
|
||||
metabase.api.user-test/with-temp-user-email hooks.common/with-one-binding
|
||||
metabase.async.streaming-response-test/with-start-execution-chan hooks.common/with-one-binding
|
||||
metabase.db.schema-migrations-test.impl/test-migrations hooks.metabase.db.schema-migrations-test.impl/test-migrations
|
||||
metabase.dashboard-subscription-test/with-link-card-fixture-for-dashboard hooks.common/let-second
|
||||
metabase.models.collection-test/with-collection-hierarchy hooks.common/let-one-with-optional-value
|
||||
metabase.models.collection-test/with-personal-and-impersonal-collections hooks.common/with-two-bindings
|
||||
metabase.models.dashboard-test/with-dash-in-collection hooks.common/with-three-bindings
|
||||
metabase.models.interface/define-simple-hydration-method hooks.metabase.models.interface/define-hydration-method
|
||||
metabase.models.interface/define-batched-hydration-method hooks.metabase.models.interface/define-hydration-method
|
||||
metabase.models.pulse-test/with-dashboard-subscription-in-collection hooks.common/with-four-bindings
|
||||
metabase.models.pulse-test/with-pulse-in-collection hooks.common/with-four-bindings
|
||||
metabase.models.setting.multi-setting/define-multi-setting hooks.metabase.models.setting/defsetting
|
||||
metabase.models.setting/defsetting hooks.metabase.models.setting/defsetting
|
||||
metabase.pulse.test-util/checkins-query-card hooks.metabase.test.data/$ids
|
||||
metabase.query-processor-test.expressions-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
|
||||
metabase.query-processor-test.filter-test/count-with-filter-clause hooks.metabase.test.data/$ids
|
||||
metabase.query-processor.middleware.cache-test/with-mock-cache hooks.common/with-two-bindings
|
||||
metabase.sample-data-test/with-temp-sample-database-db hooks.common/with-one-binding
|
||||
metabase.test.data.users/with-group hooks.common/let-one-with-optional-value
|
||||
metabase.test.data/$ids hooks.metabase.test.data/$ids
|
||||
metabase.test.data/dataset hooks.metabase.test.data/dataset
|
||||
metabase.test.data/mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test.data/mbql-query-no-test hooks.metabase.test.data/mbql-query
|
||||
metabase.test.data/run-mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test.util.async/with-open-channels hooks.common/let-with-optional-value-for-last-binding
|
||||
metabase.test.util.log/with-log-level hooks.common/with-ignored-first-arg
|
||||
metabase.test.util.log/with-log-messages-for-level hooks.common/with-ignored-first-arg
|
||||
metabase.test.util/discard-setting-changes hooks.common/with-ignored-first-arg
|
||||
metabase.test.util/with-column-remappings hooks.common/with-ignored-first-arg
|
||||
metabase.test.util/with-non-admin-groups-no-root-collection-perms hooks.common/do*
|
||||
metabase.test.util/with-temp-file hooks.metabase.test.util/with-temp-file
|
||||
metabase.test.util/with-temporary-setting-values hooks.metabase.test.util/with-temporary-setting-values
|
||||
metabase.test/$ids hooks.metabase.test.data/$ids
|
||||
metabase.test/dataset hooks.metabase.test.data/dataset
|
||||
metabase.test/discard-setting-changes hooks.common/with-ignored-first-arg
|
||||
metabase.test/mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/mbql-query-no-test hooks.metabase.test.data/mbql-query
|
||||
metabase.test/query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/test-drivers hooks.common/do*
|
||||
metabase.test/run-mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/with-column-remappings hooks.common/with-ignored-first-arg
|
||||
metabase.test/with-group hooks.common/let-one-with-optional-value
|
||||
metabase.test/with-log-level hooks.common/with-ignored-first-arg
|
||||
metabase.test/with-log-messages-for-level hooks.common/with-ignored-first-arg
|
||||
metabase.test/with-non-admin-groups-no-root-collection-perms hooks.common/do*
|
||||
metabase.test/with-temp hooks.toucan.util.test/with-temp
|
||||
metabase.test/with-temp* hooks.toucan.util.test/with-temp*
|
||||
metabase.test/with-temp-file hooks.metabase.test.util/with-temp-file
|
||||
metabase.test/with-temporary-setting-values hooks.metabase.test.util/with-temporary-setting-values
|
||||
toucan.util.test/with-temp hooks.toucan.util.test/with-temp
|
||||
toucan.util.test/with-temp* hooks.toucan.util.test/with-temp*}
|
||||
|
||||
:macroexpand
|
||||
{clojurewerkz.quartzite.jobs/build macros.quartz/build-job
|
||||
clojurewerkz.quartzite.schedule.cron/schedule macros.quartz/schedule
|
||||
clojurewerkz.quartzite.schedule.simple/schedule macros.quartz/simple-schedule
|
||||
clojurewerkz.quartzite.triggers/build macros.quartz/build-trigger
|
||||
metabase-enterprise.sandbox.test-util/with-gtaps macros.metabase-enterprise.sandbox.test-util/with-gtaps
|
||||
metabase-enterprise.serialization.test-util/with-world macros.metabase-enterprise.serialization.test-util/with-world
|
||||
metabase-enterprise.test/with-gtaps macros.metabase-enterprise.sandbox.test-util/with-gtaps
|
||||
metabase.api.card-test/with-ordered-items macros.metabase.api.card-test/with-ordered-items
|
||||
metabase.api.collection-test/with-collection-hierarchy macros.metabase.api.collection-test/with-collection-hierarchy
|
||||
metabase.api.collection-test/with-some-children-of-collection macros.metabase.api.collection-test/with-some-children-of-collection
|
||||
metabase.api.common/define-routes macros.metabase.api.common/define-routes
|
||||
metabase.api.embed-test/with-embedding-enabled-and-temp-card-referencing macros.metabase.api.embed-test/with-embedding-enabled-and-temp-card-referencing
|
||||
metabase.api.embed-test/with-embedding-enabled-and-temp-dashcard-referencing macros.metabase.api.embed-test/with-embedding-enabled-and-temp-dashcard-referencing
|
||||
metabase.api.public-test/with-sharing-enabled-and-temp-card-referencing macros.metabase.api.public-test/with-sharing-enabled-and-temp-card-referencing
|
||||
metabase.api.public-test/with-sharing-enabled-and-temp-dashcard-referencing macros.metabase.api.public-test/with-sharing-enabled-and-temp-dashcard-referencing
|
||||
metabase.domain-entities.malli/define-getters-and-setters macros.metabase.domain-entities.malli/define-getters-and-setters
|
||||
metabase.lib.filter/deffilter macros.metabase.lib.filter/deffilter
|
||||
metabase.lib.common/defop macros.metabase.lib.common/defop
|
||||
metabase.models.params.chain-filter-test/chain-filter macros.metabase.models.params.chain-filter-test/chain-filter
|
||||
metabase.models.params.chain-filter-test/chain-filter-search macros.metabase.models.params.chain-filter-test/chain-filter
|
||||
metabase.models.user-test/with-groups macros.metabase.models.user-test/with-groups
|
||||
metabase.query-processor.streaming/streaming-response macros.metabase.query-processor.streaming/streaming-response
|
||||
metabase.related-test/with-world macros.metabase.related-test/with-world
|
||||
metabase.shared.util.namespaces/import-fn macros.metabase.shared.util.namespaces/import-fn
|
||||
metabase.test.data.users/with-group-for-user macros.metabase.test.data.users/with-group-for-user
|
||||
metabase.test.util/with-temp-env-var-value macros.metabase.test.util/with-temp-env-var-value
|
||||
metabase.test.util/with-temporary-raw-setting-values macros.metabase.test.util/with-temporary-raw-setting-values
|
||||
metabase.test/with-group-for-user macros.metabase.test.data.users/with-group-for-user
|
||||
metabase.test/with-persistence-enabled macros.metabase.test.persistence/with-persistence-enabled
|
||||
metabase.test/with-temp-env-var-value macros.metabase.test.util/with-temp-env-var-value
|
||||
metabase.test/with-temporary-raw-setting-values macros.metabase.test.util/with-temporary-raw-setting-values}}
|
||||
|
||||
:config-in-comment
|
||||
{:linters {:unresolved-symbol {:level :off}}}
|
||||
|
||||
;;
|
||||
;; TEST CONFIG
|
||||
;;
|
||||
:ns-groups
|
||||
;; the following patterns are considered to be test namespaces:
|
||||
;;
|
||||
;; - Any namespace ending in `-test` or `-test.whatever`
|
||||
;; - Any namespace ending in `test-util`
|
||||
;; - Any namespace that starts with `metabase.test`
|
||||
;;
|
||||
;; this list isn't exhaustive because it misses some stuff like the test runner and HTTP client but it's easier to go
|
||||
;; fix those namespaces than it is to make this regex super hairy.
|
||||
[{:pattern "(?:.*-test(?:\\..*)?$)|(?:.*test-util$)|(?:^metabase\\.test.*)"
|
||||
:name test-namespaces}
|
||||
{:pattern "^(?!.*-test(?:\\..*)?$)(?!.*test-util$)(?!^metabase\\.test.*).*$"
|
||||
:name source-namespaces}
|
||||
{:pattern "metabase\\.cmd.*"
|
||||
:name printable-namespaces}
|
||||
{:pattern "^metabase\\.lib\\.*"
|
||||
:name metabase-lib}
|
||||
;; Basically everything except `metabase.driver.` or `metabase.test-data.` except for the drivers explicitly called
|
||||
;; out below. Remove these drivers from the regex once we switch to Honey SQL 2.
|
||||
;;
|
||||
;; This regex is way too big to easily read or write by hand, so use the [[metabase.util.regex/rx]] macro to
|
||||
;; generate it. It was generated from the following form:
|
||||
;;
|
||||
;; (str
|
||||
;; (metabase.util.regex/rx
|
||||
;; #"^metabase\."
|
||||
;; [:not [:and #"util\." [:or "honeysql-extensions" "honey-sql-1"]]]
|
||||
;; [:not "query-processor-test"]
|
||||
;; [:not [:and
|
||||
;; [:or "driver" #"test\.data"]
|
||||
;; #"\."
|
||||
;; [:or
|
||||
;; [:and "sql" [:? "-jdbc"]]
|
||||
;; #"(?:sql(?:-jdbc)?)"
|
||||
;; "bigquery-cloud-sdk"
|
||||
;; [:and "presto" [:? [:or "-common" "-jdbc"]]]
|
||||
;; "sqlserver"]
|
||||
;; [:? "-test"]
|
||||
;; [:or #"\." #"$"]]]
|
||||
;; ".*"))
|
||||
;;
|
||||
;; Please keep this form updated when you change the generated regex! <3
|
||||
{:pattern "^metabase\\.(?!util\\.(?:(?:honeysql-extensions)|(?:honey-sql-1)))(?!query-processor-test)(?!(?:(?:driver)|(?:test\\.data))\\.(?:(?:sql(?:-jdbc)?)|(?:(?:sql(?:-jdbc)?))|(?:bigquery-cloud-sdk)|(?:presto(?:(?:(?:-common)|(?:-jdbc)))?)|(?:sqlserver))(?:-test)?(?:(?:\\.)|(?:$))).*"
|
||||
:name honey-sql-2-namespaces}]
|
||||
|
||||
:config-in-ns
|
||||
{test-namespaces
|
||||
{:linters
|
||||
{:inline-def {:level :off}
|
||||
:missing-docstring {:level :off}
|
||||
:private-call {:level :off}
|
||||
:hooks.metabase.test.data/mbql-query-first-arg {:level :error}}}
|
||||
|
||||
source-namespaces
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{clojure.core/with-redefs {:message "Don't use with-redefs"}
|
||||
clojure.core/eval {:message "Don't use eval"}}}}
|
||||
|
||||
printable-namespaces
|
||||
{:linters
|
||||
{:discouraged-var {:level :off}}}
|
||||
|
||||
honey-sql-2-namespaces
|
||||
{:linters
|
||||
{:discouraged-namespace
|
||||
{clj-yaml.core {:message "Use metabase.util.yaml"}
|
||||
honeysql.core {:message "Use Honey SQL 2"}
|
||||
honeysql.format {:message "Use Honey SQL 2"}
|
||||
honeysql.helpers {:message "Use Honey SQL 2"}
|
||||
honeysql.types {:message "Use Honey SQL 2"}
|
||||
honeysql.util {:message "Use Honey SQL 2"}
|
||||
metabase.util.honeysql-extensions {:message "Use h2x"}
|
||||
metabase.util.honey-sql-1 {:message "Use h2x"}}}}
|
||||
|
||||
;; enable all the extra linters we haven't enabled in the core app yet in MLv2. It's all new code so we can adhere
|
||||
;; to the new stricter rules from day 1
|
||||
metabase-lib
|
||||
{:linters
|
||||
{:docstring-leading-trailing-whitespace {:level :warning}
|
||||
:reduce-without-init {:level :warning}
|
||||
:used-underscored-binding {:level :warning}
|
||||
:single-key-in {:level :warning}
|
||||
:keyword-binding {:level :warning}
|
||||
:shadowed-var {:level :warning}
|
||||
:metabase/deftest-not-marked-parallel-or-synchronized {:level :warning}}}}}
|
||||
metabase.test/with-temp hooks.toucan.util.test/with-temp}
|
||||
:macroexpand {metabase.query-processor.streaming/streaming-response
|
||||
metabase.query-processor.streaming/streaming-response
|
||||
metabase.api.common/define-routes macros.metabase.api.common/define-routes
|
||||
toucan.models/defmodel toucan.models/defmodel
|
||||
clojurewerkz.quartzite.jobs/build macros.quartz/build-job
|
||||
clojurewerkz.quartzite.triggers/build macros.quartz/build-trigger
|
||||
clojurewerkz.quartzite.schedule.cron/schedule macros.quartz/schedule}}
|
||||
:config-in-comment {:linters {:unresolved-symbol {:level :off}}}}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
(ns hooks.clojure.test
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(def disallowed-parallel-forms
|
||||
'#{with-redefs
|
||||
clojure.core/with-redefs
|
||||
metabase.test/with-temporary-setting-values
|
||||
mt/with-temporary-setting-values})
|
||||
|
||||
(defn warn-about-disallowed-parallel-forms [form]
|
||||
(letfn [(f [form]
|
||||
(when-let [sexpr (and (hooks/token-node? form)
|
||||
(hooks/sexpr form))]
|
||||
(when (disallowed-parallel-forms sexpr)
|
||||
(hooks/reg-finding! (assoc (meta form)
|
||||
:message (format "%s is not allowed inside a ^:parallel test" sexpr)
|
||||
:type :metabase/validate-deftest)))))
|
||||
(walk [form]
|
||||
(f form)
|
||||
(doseq [child (:children form)]
|
||||
(walk child)))]
|
||||
(walk form)))
|
||||
|
||||
(defn deftest [{{[_ test-name & body] :children, :as node} :node}]
|
||||
(let [test-metadata (:meta test-name)
|
||||
metadata-sexprs (map hooks/sexpr test-metadata)
|
||||
combined-metadata (transduce
|
||||
(map (fn [x]
|
||||
(if (map? x)
|
||||
x
|
||||
{x true})))
|
||||
(completing merge)
|
||||
{}
|
||||
metadata-sexprs)
|
||||
parallel? (:parallel combined-metadata)
|
||||
synchronized? (:synchronized combined-metadata)]
|
||||
(when (and parallel? synchronized?)
|
||||
(hooks/reg-finding! (assoc (meta test-name)
|
||||
:message "Test should not be marked both ^:parallel and ^:synchronized"
|
||||
:type :metabase/validate-deftest)))
|
||||
;; only when the custom `:metabase/deftest-not-marked-parallel` is enabled: complain if tests are not explicitly
|
||||
;; marked `^:parallel` or `^:synchronized`. This is mostly to encourage people to mark everything `^:parallel` in
|
||||
;; places like `metabase.lib` tests unless there is a really good reason not to.
|
||||
(when-not (or parallel? synchronized?)
|
||||
(hooks/reg-finding!
|
||||
(assoc (meta test-name)
|
||||
:message "Test should be marked either ^:parallel or ^:synchronized"
|
||||
:type :metabase/deftest-not-marked-parallel-or-synchronized)))
|
||||
(when parallel?
|
||||
(doseq [form body]
|
||||
(warn-about-disallowed-parallel-forms form))))
|
||||
{:node node})
|
||||
@@ -1,293 +0,0 @@
|
||||
(ns hooks.common
|
||||
(:require [clj-kondo.hooks-api :as hooks]
|
||||
[clojure.pprint]))
|
||||
|
||||
(defn with-macro-meta
|
||||
"When introducing internal nodes (let, defn, etc) it is important to provide a meta of an existing token
|
||||
as the current version of kondo will use the whole form by default."
|
||||
[new-node hook-node]
|
||||
(with-meta new-node (meta (first (:children hook-node)))))
|
||||
|
||||
;;; This stuff is to help debug hooks. Trace a function and it will pretty-print the before & after sexprs.
|
||||
;;;
|
||||
;;; (hooks.common/trace #'calculate-bird-scarcity)
|
||||
|
||||
(defn- trace* [f]
|
||||
{:pre [(fn? f)]}
|
||||
(fn traced-fn [node]
|
||||
(println \newline)
|
||||
(clojure.pprint/pprint (hooks/sexpr (:node node)))
|
||||
(let [node* (f node)]
|
||||
(println '=>)
|
||||
(clojure.pprint/pprint (hooks/sexpr (:node node*)))
|
||||
node*)))
|
||||
|
||||
;;; this doesn't seem to work with SCI. Use [[defn-traced]] instead.
|
||||
|
||||
;; (defn trace [varr]
|
||||
;; {:pre [(var? varr)]}
|
||||
;; (when-not (::traced? (meta varr))
|
||||
;; (alter-var-root varr trace*)
|
||||
;; (alter-meta! varr assoc ::traced? true)
|
||||
;; (println "Traced" varr)))
|
||||
|
||||
(defmacro defn-traced
|
||||
"Replace a hook [[defn]] with this to trace the before and after sexprs."
|
||||
[fn-name & fn-tail]
|
||||
`(do
|
||||
(defn fn# ~@fn-tail)
|
||||
(def ~fn-name (trace* fn#))))
|
||||
|
||||
;;;; Common hook definitions
|
||||
|
||||
(defn do*
|
||||
"This is the same idea as [[clojure.core/do]] but doesn't cause Kondo to complain about redundant dos or unused values."
|
||||
[{{[_ & args] :children, :as node} :node}]
|
||||
(let [node* (-> (hooks/list-node
|
||||
(list*
|
||||
(with-meta (hooks/token-node 'do) {:clj-kondo/ignore [:redundant-do]})
|
||||
(for [arg args]
|
||||
(vary-meta arg update :clj-kondo/ignore #(conj (vec %) :unused-value)))))
|
||||
(with-meta (meta node)))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-one-binding
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro [x]
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [x nil]
|
||||
...)
|
||||
|
||||
Binding is optional and `_` will be substituted if not supplied."
|
||||
[{{[_ {[x] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[(or x (hooks/token-node '_)) (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-two-bindings
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro [x y]
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [x nil, y nil]
|
||||
...)
|
||||
|
||||
All bindings are optional and `_` will be substituted if not supplied."
|
||||
[{{[_ {[x y] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[(or x (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or y (hooks/token-node '_)) (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-three-bindings
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro [x y z]
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [x nil, y nil, z nil]
|
||||
...)
|
||||
|
||||
All bindings are optional and `_` will be substituted if not supplied."
|
||||
[{{[_ {[x y z] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[(or x (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or y (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or z (hooks/token-node '_)) (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-four-bindings
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro [a b c d]
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [a nil, b nil, c nil, d nil]
|
||||
...)
|
||||
|
||||
All bindings are optional and `_` will be substituted if not supplied."
|
||||
[{{[_ {[a b c d] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[(or a (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or b (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or c (hooks/token-node '_)) (hooks/token-node 'nil)
|
||||
(or d (hooks/token-node '_)) (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-one-top-level-binding
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro x
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [x nil]
|
||||
...)"
|
||||
[{{[_ x & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[x (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-two-top-level-bindings
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro x y
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [x nil, y nil]
|
||||
...)"
|
||||
[{{[_ x y & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[x (hooks/token-node 'nil)
|
||||
y (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn let-one-with-optional-value
|
||||
"This is exactly like [[clojure.core/let]] but the right-hand side of the binding, `value`, is optional, and only one
|
||||
binding can be established.
|
||||
|
||||
(some-macro [x] ...)
|
||||
=>
|
||||
(let [x nil] ...)
|
||||
|
||||
(some-macro [x 100] ...)
|
||||
=>
|
||||
(let [x 100] ...)"
|
||||
[{{[_ {[binding value] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[binding (or value (hooks/token-node 'nil))])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn- let-second-inner [body bindings]
|
||||
(let [binding-infos (for [[model {[binding value] :children}] (partition 2 bindings)]
|
||||
{:model model
|
||||
:binding binding
|
||||
:value (or value
|
||||
(hooks/token-node 'nil))})]
|
||||
(-> (hooks/vector-node
|
||||
[(hooks/vector-node (map :model binding-infos))
|
||||
(-> (hooks/list-node (list* (hooks/token-node `let)
|
||||
(hooks/vector-node (mapcat (juxt :binding :value) binding-infos))
|
||||
body))
|
||||
(with-meta (meta body)))])
|
||||
(with-meta (meta body)))))
|
||||
|
||||
(defn let-second
|
||||
"Helper for macros that have a shape like
|
||||
|
||||
(my-macro x [y]
|
||||
...)
|
||||
|
||||
where the let is for second arg.
|
||||
|
||||
=>
|
||||
|
||||
(let [y nil]
|
||||
...)"
|
||||
[{:keys [node]}]
|
||||
(let [[_ first-arg-ref binding+opts & body] (:children node)]
|
||||
{:node (let-second-inner body [first-arg-ref binding+opts])}))
|
||||
|
||||
(defn let-with-optional-value-for-last-binding
|
||||
"This is exactly like [[clojure.core/let]] but the right-hand side of the *last* binding, `value`, is optional.
|
||||
|
||||
(some-macro [x] ...)
|
||||
=>
|
||||
(let [x nil] ...)
|
||||
|
||||
(some-macro [x 100] ...)
|
||||
=>
|
||||
(let [x 100] ...)"
|
||||
[{{[_ {bindings :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
(into []
|
||||
(comp (partition-all 2)
|
||||
(mapcat (fn [[binding value]]
|
||||
[binding (or value (hooks/token-node 'nil))])))
|
||||
bindings))
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-ignored-first-arg
|
||||
"For macros like
|
||||
|
||||
(discard-setting-changes [setting-1 setting-2]
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(do ...)
|
||||
|
||||
where the first arg ought to be ignored for linting purposes."
|
||||
[{{[_ _x & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'do)
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-used-first-arg
|
||||
"For macros like
|
||||
|
||||
(with-drivers (filter pred? some-drivers)
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [_1234 (filter pred? some-drivers)]
|
||||
...)
|
||||
|
||||
where the first arg should be linted and appear to be used."
|
||||
[{{[_ arg & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node [(hooks/token-node (gensym "_"))
|
||||
arg])
|
||||
body))]
|
||||
{:node node*}))
|
||||
@@ -1,29 +1,23 @@
|
||||
(ns hooks.metabase.api.common
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[clojure.string :as str]
|
||||
[hooks.common :as common]))
|
||||
[clj-kondo.hooks-api :as api]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn route-fn-name
|
||||
"route fn hook"
|
||||
[method route]
|
||||
(let [route (if (vector? route) (first route) route)]
|
||||
(-> (str (name method) route)
|
||||
(str/replace #"/" "_")
|
||||
symbol)))
|
||||
|
||||
(defn defendpoint
|
||||
"defendpoint hook"
|
||||
[{:keys [node]}]
|
||||
(defn defendpoint [{:keys [node]}]
|
||||
(let [[method route & body] (rest (:children node))]
|
||||
{:node
|
||||
(hooks/vector-node [;; register usage of compojure core var
|
||||
(common/with-macro-meta (hooks/token-node (symbol (str "compojure.core")
|
||||
(str method)))
|
||||
node)
|
||||
;; define function with route-fn-name
|
||||
(hooks/list-node
|
||||
(list* (common/with-macro-meta (hooks/token-node 'clojure.core/defn)
|
||||
node)
|
||||
(route-fn-name (hooks/sexpr method) (hooks/sexpr route))
|
||||
body))])}))
|
||||
(api/list-node [(api/token-node 'do)
|
||||
;; register usage of compojure core var
|
||||
(api/token-node (symbol (str "compojure.core")
|
||||
(str method)))
|
||||
;; define function with route-fn-name
|
||||
(api/list-node (list* (api/token-node 'clojure.core/defn)
|
||||
(route-fn-name (api/sexpr method) (api/sexpr route))
|
||||
body))])}))
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
(ns hooks.metabase.api.search-test
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn with-search-items-in-collection [{{[_ & args] :children, :as node} :node}]
|
||||
;; (println \newline)
|
||||
;; (clojure.pprint/pprint (hooks/sexpr node))
|
||||
(let [[created-items-sym search-string & body] args
|
||||
node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[created-items-sym (hooks/token-node 'nil)])
|
||||
search-string
|
||||
body))]
|
||||
;; (println '=>)
|
||||
;; (clojure.pprint/pprint (hooks/sexpr node*))
|
||||
{:node node*}))
|
||||
@@ -1,14 +0,0 @@
|
||||
(ns hooks.metabase.db.schema-migrations-test.impl
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn test-migrations
|
||||
[{{[_ migration-range {[binding] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node `let)
|
||||
(hooks/vector-node
|
||||
[binding (hooks/list-node (list (hooks/token-node `fn)
|
||||
(hooks/vector-node [])))])
|
||||
migration-range
|
||||
body))]
|
||||
{:node node*}))
|
||||
@@ -1,17 +0,0 @@
|
||||
(ns hooks.metabase.models.interface
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn define-hydration-method
|
||||
"This is used for both [[metabase.models.interface/define-simple-hydration-method]] and
|
||||
for [[metabase.models.interface/define-batched-hydration-method]]."
|
||||
[{{[_define-simple-hydration-method fn-name hydration-key & fn-tail] :children} :node}]
|
||||
(let [node (hooks/list-node
|
||||
(list
|
||||
(hooks/token-node 'do)
|
||||
hydration-key
|
||||
(hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'defn)
|
||||
fn-name
|
||||
fn-tail))))]
|
||||
{:node node}))
|
||||
@@ -1,47 +0,0 @@
|
||||
(ns hooks.metabase.models.setting
|
||||
(:require [clj-kondo.hooks-api :as hooks]
|
||||
[hooks.common :as common]))
|
||||
|
||||
(defn defsetting
|
||||
"Rewrite a [[metabase.models.defsetting]] form like
|
||||
|
||||
(defsetting my-setting \"Description\" :type :boolean)
|
||||
|
||||
as
|
||||
|
||||
(let [_ \"Description\"
|
||||
_ :type
|
||||
_ :boolean]
|
||||
(defn my-setting \"Docstring.\" [])
|
||||
(defn my-setting! \"Docstring.\" [_value-or-nil]))
|
||||
|
||||
for linting purposes."
|
||||
[{:keys [node]}]
|
||||
(let [[setting-name & args] (rest (:children node))
|
||||
;; (defn my-setting [] ...)
|
||||
getter-node (-> (list
|
||||
(hooks/token-node 'defn)
|
||||
setting-name
|
||||
(hooks/string-node "Docstring.")
|
||||
(hooks/vector-node []))
|
||||
hooks/list-node
|
||||
(with-meta (meta setting-name)))
|
||||
;; (defn my-setting! [_x] ...)
|
||||
setter-node (-> (list
|
||||
(hooks/token-node 'defn)
|
||||
(with-meta
|
||||
(hooks/token-node (symbol (str (:string-value setting-name) \!)))
|
||||
(meta setting-name))
|
||||
(hooks/string-node "Docstring.")
|
||||
(hooks/vector-node [(hooks/token-node '_value-or-nil)]))
|
||||
hooks/list-node
|
||||
(with-meta (meta setting-name)))]
|
||||
{:node (-> (list
|
||||
(hooks/token-node 'let)
|
||||
;; include description and the options map so they can get validated as well.
|
||||
(hooks/vector-node (vec (interleave (repeat (common/with-macro-meta (hooks/token-node '_) node))
|
||||
args)))
|
||||
getter-node
|
||||
setter-node)
|
||||
hooks/list-node
|
||||
(with-meta (meta node)))}))
|
||||
@@ -1,16 +0,0 @@
|
||||
(ns hooks.metabase.query-processor-test.expressions-test
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[hooks.metabase.test.data :as data]))
|
||||
|
||||
(defn calculate-bird-scarcity
|
||||
[{{[_ formula filter-clause] :children} :node}]
|
||||
(let [formula* (data/replace-$id-special-tokens formula)
|
||||
filter-clause* (or (some-> filter-clause data/replace-$id-special-tokens)
|
||||
(hooks/token-node 'nil))
|
||||
node* (hooks/list-node
|
||||
(list
|
||||
(hooks/token-node 'do)
|
||||
formula*
|
||||
filter-clause*))]
|
||||
{:node node*}))
|
||||
@@ -1,152 +1,55 @@
|
||||
(ns hooks.metabase.test.data
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[clojure.string :as str]
|
||||
[clojure.string :as string]
|
||||
[clojure.walk :as walk]))
|
||||
|
||||
(defn- global-dataset-symbols
|
||||
"Dataset definitions defined in [[metabase.test.data.dataset-definitions]]. This is only populated if clj-kondo has
|
||||
cached analysis for that namespace -- so it may or may not be populated. If it is populated we can do a bit of extra
|
||||
linting with that information."
|
||||
[]
|
||||
(not-empty (set (keys (:clj (hooks/ns-analysis 'metabase.test.data.dataset-definitions))))))
|
||||
(defn dataset [{:keys [node]}]
|
||||
(let [[dataset & body] (rest (:children node))]
|
||||
{:node (with-meta
|
||||
(hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'clojure.test/testing)
|
||||
(hooks/string-node (str dataset))
|
||||
body))
|
||||
(meta dataset))}))
|
||||
|
||||
(defn- dataset-type
|
||||
"`dataset` can be one of:
|
||||
|
||||
- a qualified symbol
|
||||
- an unqualified symbol referring to a a var in [[metabase.test.data.dataset-definitions]]
|
||||
- an unqualified symbol (referring to a let-bound value or a var in the current namespace
|
||||
- some sort of non-symbol form like a function call
|
||||
|
||||
We can only determine if an unqualified symbol refers to something in the dataset definitions namespace if there are
|
||||
cached results available from [[global-dataset-symbols]]."
|
||||
[dataset]
|
||||
(let [sexpr (hooks/sexpr dataset)
|
||||
global-defs (global-dataset-symbols)]
|
||||
(cond
|
||||
(not (symbol? sexpr))
|
||||
:non-symbol
|
||||
|
||||
(namespace sexpr)
|
||||
:qualified
|
||||
|
||||
(empty? global-defs)
|
||||
:unqualified/unknown
|
||||
|
||||
(contains? global-defs sexpr)
|
||||
:unqualified/from-dataset-defs-namespace
|
||||
|
||||
;; either something defined in the current namespace or let-bound in the current scope.
|
||||
:else
|
||||
:unqualified/local-def)))
|
||||
|
||||
(defn dataset
|
||||
[{{[_ dataset & body] :children} :node}]
|
||||
(let [noop (constantly nil)
|
||||
body (case (dataset-type dataset)
|
||||
;; non-symbol, qualified symbols, and unqualified symbols from the current namespace/let-bound can all
|
||||
;; get converted from something like
|
||||
;;
|
||||
;; (dataset whatever
|
||||
;; ...)
|
||||
;;
|
||||
;; to
|
||||
;;
|
||||
;; (let [_ whatever]
|
||||
;; ...)
|
||||
(:non-symbol :qualified :unqualified/local-def)
|
||||
(list* (hooks/token-node 'let)
|
||||
(hooks/vector-node [(hooks/token-node '_) dataset])
|
||||
body)
|
||||
|
||||
;; for ones that came from the dataset defs namespace or ones whose origin is unknown, just ignore them
|
||||
;; and generate a `print` form:
|
||||
;;
|
||||
;; (print ...)
|
||||
;;
|
||||
;; (this used to be a `do` form (which makes a lot more semantic sense), but that resulted in warnings
|
||||
;; about unused values
|
||||
(:unqualified/from-dataset-defs-namespace :unqualified/unknown)
|
||||
(list* (hooks/token-node noop)
|
||||
body))]
|
||||
{:node (with-meta (hooks/list-node (with-meta body
|
||||
(meta dataset)))
|
||||
(meta dataset))}))
|
||||
|
||||
(defn- special-token-node?
|
||||
"Whether this node is one of the special symbols like `$field`."
|
||||
[node]
|
||||
(when (hooks/token-node? node)
|
||||
(let [symb (hooks/sexpr node)]
|
||||
(and (symbol? symb)
|
||||
(some (partial str/starts-with? symb)
|
||||
#{"$" "!" "&" "*" "%"})
|
||||
;; ignore args like `%` or `%1` inside function literals. $id forms have to be more than one character long,
|
||||
;; and the first character won't be a number (hopefully -- maybe some DBs allow this -- but we don't use it)
|
||||
(> (count (str symb)) 1)
|
||||
(not (re-find #"^%\d+" (str symb)))))))
|
||||
|
||||
(defn replace-$id-special-tokens
|
||||
"Impl for [[$ids]] and [[mbql-query]]. Walk `form` and look for special tokens like `$field` and replace them with
|
||||
strings so we don't get unresolved symbol errors. Preserves metadata."
|
||||
[form]
|
||||
;; [[walk/postwalk]] seems to preserve its meta so we don't need to do anything special
|
||||
(walk/postwalk
|
||||
(fn [node]
|
||||
(if (special-token-node? node)
|
||||
(-> (hooks/string-node (str (hooks/sexpr node)))
|
||||
(with-meta (meta node)))
|
||||
node))
|
||||
form))
|
||||
|
||||
(defn $ids
|
||||
[{{[_ & args] :children} :node}]
|
||||
;; `$ids` accepts either
|
||||
;;
|
||||
;; ($ids form)
|
||||
;;
|
||||
;; or
|
||||
;;
|
||||
;; ($ids table & body)
|
||||
;;
|
||||
;; table is only relevant for expanding the special tokens so we can ignore it.
|
||||
(let [body (if (= (count args) 1)
|
||||
(first args)
|
||||
(hooks/list-node
|
||||
(defn $ids [{:keys [node]}]
|
||||
(let [args (rest (:children node))
|
||||
[table-name & body] args
|
||||
unused-node (hooks/token-node '_)
|
||||
vars (atom #{})
|
||||
_ (walk/postwalk (fn [node]
|
||||
(when (hooks/token-node? node)
|
||||
(let [str-node (str (hooks/sexpr node))]
|
||||
(when (or (string/starts-with? str-node "$")
|
||||
(string/starts-with? str-node "!")
|
||||
(string/starts-with? str-node "&")
|
||||
(string/starts-with? str-node "*")
|
||||
(string/starts-with? str-node "%"))
|
||||
(swap! vars conj node))))
|
||||
node)
|
||||
body)
|
||||
nil-bindings (vec (interpose (hooks/token-node nil) @vars))
|
||||
unused-bindings (vec (interpose unused-node @vars))
|
||||
final-bindings (concat
|
||||
(when-not (= "nil" (str table-name))
|
||||
[table-name (hooks/token-node nil)])
|
||||
[unused-node table-name]
|
||||
(if (seq nil-bindings)
|
||||
(conj nil-bindings (hooks/token-node nil))
|
||||
[])
|
||||
(if (seq unused-bindings)
|
||||
(conj (next unused-bindings)
|
||||
(first unused-bindings)
|
||||
unused-node)
|
||||
[]))]
|
||||
{:node (with-meta
|
||||
(hooks/list-node
|
||||
(with-meta
|
||||
(list*
|
||||
(hooks/token-node `do)
|
||||
(rest args))))]
|
||||
{:node (replace-$id-special-tokens body)}))
|
||||
|
||||
(defn mbql-query
|
||||
[{{[_ & args] :children} :node}]
|
||||
;; `mbql-query` accepts either
|
||||
;;
|
||||
;; (mbql-query table)
|
||||
;;
|
||||
;; or
|
||||
;;
|
||||
;; (mbql-query table query)
|
||||
;;
|
||||
;; and table may be `nil`.
|
||||
;;
|
||||
;; table is only relevant for expanding the special tokens so we can ignore it either way.
|
||||
(let [[table query] (if (= (count args) 1)
|
||||
[(first args)
|
||||
(hooks/map-node [])]
|
||||
args)]
|
||||
(when-not ((some-fn symbol? nil?) (hooks/sexpr table))
|
||||
(hooks/reg-finding! (assoc (meta table)
|
||||
:message "First arg to mbql-query should be either a table name symbol or nil."
|
||||
:type ::mbql-query-first-arg)))
|
||||
(let [result (replace-$id-special-tokens query)
|
||||
;; HACK I'm not sure WHY it works but I ran into https://github.com/clj-kondo/clj-kondo/issues/1773 when
|
||||
;; trying to get this working -- for some magical reason wrapping the whole thing in a `do` form seems to fix
|
||||
;; it. Once that bug is resolved we can go ahead and remove this line
|
||||
result (with-meta (hooks/list-node (with-meta (list
|
||||
(hooks/token-node 'do)
|
||||
result)
|
||||
(meta query)))
|
||||
(meta query))]
|
||||
{:node result})))
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node (vec final-bindings))
|
||||
body)
|
||||
(meta body)))
|
||||
(meta body))}))
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
(ns hooks.metabase.test.util
|
||||
(:require [clj-kondo.hooks-api :as hooks]
|
||||
[hooks.common :as common]))
|
||||
|
||||
(defn- namespaced-symbol-node? [node]
|
||||
(when (hooks/token-node? node)
|
||||
(let [symb (hooks/sexpr node)]
|
||||
(and (symbol? symb)
|
||||
(namespace symb)))))
|
||||
|
||||
(defn with-temporary-setting-values
|
||||
"Rewrite a form like
|
||||
|
||||
(with-temporary-setting-values [x 1, some.ns/y 2]
|
||||
...)
|
||||
|
||||
as one like
|
||||
|
||||
(let [_ 1, _ some.ns/y, _ 2]
|
||||
...)
|
||||
|
||||
for analysis purposes. We only need to 'capture' namespaced Setting bindings with a `_` so Kondo considers their
|
||||
namespace to be 'used' and to catch undefined var usage."
|
||||
[{:keys [node]}]
|
||||
(let [{[_ bindings & body] :children} node
|
||||
bindings (if (hooks/vector-node? bindings)
|
||||
(hooks/vector-node (into []
|
||||
(mapcat (fn [[setting-name v]]
|
||||
(concat
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) v]
|
||||
;; if the setting name is namespace-qualified add a `_`
|
||||
;; entry for it too.
|
||||
(when (namespaced-symbol-node? setting-name)
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) setting-name]))))
|
||||
(partition 2 (:children bindings))))
|
||||
bindings)]
|
||||
{:node (-> (list*
|
||||
(hooks/token-node 'let)
|
||||
bindings
|
||||
body)
|
||||
(with-meta (meta body))
|
||||
hooks/list-node
|
||||
(with-meta (meta body)))}))
|
||||
|
||||
(defn with-temp-file
|
||||
[{{[_ {bindings :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
(into []
|
||||
(comp (partition-all 2)
|
||||
(mapcat (fn [[binding filename]]
|
||||
[binding (or (when (and filename
|
||||
(not (nil? (hooks/sexpr filename))))
|
||||
filename)
|
||||
(hooks/string-node "filename"))])))
|
||||
bindings))
|
||||
body))]
|
||||
{:node node*}))
|
||||
@@ -1,24 +1,11 @@
|
||||
(ns hooks.toucan.util.test
|
||||
(:require [clj-kondo.hooks-api :as api]))
|
||||
|
||||
(defn- with-temp-inner [body bindings]
|
||||
(let [binding-infos (for [[model {[binding value] :children}] (partition 2 bindings)]
|
||||
{:model model
|
||||
:binding binding
|
||||
:value (or value
|
||||
(api/token-node 'nil))})]
|
||||
(-> (api/vector-node
|
||||
[(api/vector-node (map :model binding-infos))
|
||||
(-> (api/list-node (list* (api/token-node `let)
|
||||
(api/vector-node (mapcat (juxt :binding :value) binding-infos))
|
||||
body))
|
||||
(with-meta (meta body)))])
|
||||
(with-meta (meta body)))))
|
||||
|
||||
(defn with-temp [{:keys [node]}]
|
||||
(let [[_ db-ref binding+opts & body] (:children node)]
|
||||
{:node (with-temp-inner body [db-ref binding+opts])}))
|
||||
|
||||
(defn with-temp* [{:keys [node]}]
|
||||
(let [[_ bindings & body] (:children node)]
|
||||
{:node (with-temp-inner body (:children bindings))}))
|
||||
(let [[_ db-ref binding+opts & body] (:children node)
|
||||
[args opts] (:children binding+opts)]
|
||||
{:node (api/vector-node [db-ref
|
||||
opts
|
||||
(api/list-node (list* (api/token-node 'fn)
|
||||
(api/vector-node [args])
|
||||
body))])}))
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
(ns macros.common
|
||||
"Helpers for common Metabase macro shapes so we don't have to define the same macroexpansions over and over.")
|
||||
|
||||
(defn ignore-unused [symb]
|
||||
(vary-meta symb assoc :clj-kondo/ignore [:unused-binding]))
|
||||
@@ -1,12 +0,0 @@
|
||||
(ns macros.metabase.api.card-test
|
||||
(:require [macros.common]))
|
||||
|
||||
(defmacro with-ordered-items
|
||||
[collection model-and-name-syms & body]
|
||||
`(let ~(into []
|
||||
(comp (partition-all 2)
|
||||
(mapcat (fn [[model binding]]
|
||||
[(macros.common/ignore-unused binding) model])))
|
||||
model-and-name-syms)
|
||||
~collection
|
||||
~@body))
|
||||
@@ -1,17 +0,0 @@
|
||||
(ns macros.metabase.api.collection-test
|
||||
(:require [macros.common]))
|
||||
|
||||
(defmacro with-collection-hierarchy [bindings & body]
|
||||
`(let [~(macros.common/ignore-unused 'a) nil
|
||||
~(macros.common/ignore-unused 'b) nil
|
||||
~(macros.common/ignore-unused 'c) nil
|
||||
~(macros.common/ignore-unused 'd) nil
|
||||
~(macros.common/ignore-unused 'e) nil
|
||||
~(macros.common/ignore-unused 'f) nil
|
||||
~(macros.common/ignore-unused 'g) nil]
|
||||
~bindings
|
||||
~@body))
|
||||
|
||||
(defmacro with-some-children-of-collection [collection-or-id-or-nil & body]
|
||||
`(let [~(macros.common/ignore-unused '&ids) ~collection-or-id-or-nil]
|
||||
~@body))
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns macros.metabase.api.common)
|
||||
|
||||
(defmacro define-routes [& args]
|
||||
`(do (def ~'routes "docstring" nil)
|
||||
`(do (def ~'routes)
|
||||
~@args))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns macros.metabase.api.embed-test)
|
||||
|
||||
(defmacro with-embedding-enabled-and-temp-card-referencing
|
||||
[table-kw field-kw [card-binding] & body]
|
||||
`(let [~card-binding [~table-kw ~field-kw]]
|
||||
~@body))
|
||||
|
||||
(defmacro with-embedding-enabled-and-temp-dashcard-referencing
|
||||
[table-kw field-kw [dash-binding card-binding dashcard-binding] & body]
|
||||
`(let [~dash-binding [~table-kw ~field-kw]
|
||||
~(or card-binding '_) nil
|
||||
~(or dashcard-binding '_) nil]
|
||||
~@body))
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns macros.metabase.api.public-test)
|
||||
|
||||
(defmacro with-sharing-enabled-and-temp-card-referencing
|
||||
[table-kw field-kw [card-binding] & body]
|
||||
`(let [~card-binding [~table-kw ~field-kw]]
|
||||
~@body))
|
||||
|
||||
(defmacro with-sharing-enabled-and-temp-dashcard-referencing
|
||||
[table-kw field-kw [dash-binding card-binding dashcard-binding] & body]
|
||||
`(let [~dash-binding [~table-kw ~field-kw]
|
||||
~(or card-binding '_) nil
|
||||
~(or dashcard-binding '_) nil]
|
||||
~@body))
|
||||
@@ -1,16 +0,0 @@
|
||||
(ns macros.metabase.domain-entities.malli)
|
||||
|
||||
(defmacro define-getters-and-setters [schema & defs]
|
||||
`(do
|
||||
(comment ~schema) ;; Reference the schema
|
||||
~@(for [[sym _path] (partition 2 defs)]
|
||||
`(do
|
||||
(defn ~(vary-meta sym
|
||||
assoc :export true)
|
||||
"docs" [_x#] nil)
|
||||
(defn ~(vary-meta (symbol (str "with-" (name sym)))
|
||||
assoc :export true)
|
||||
"docs" [x# _new#] x#)
|
||||
(defn ~(vary-meta (symbol (str (name sym) "-js"))
|
||||
assoc :export true)
|
||||
"docs" [x#] x#)))))
|
||||
@@ -1,24 +0,0 @@
|
||||
(ns macros.metabase.lib.common)
|
||||
|
||||
(defmacro defop
|
||||
[op-name & argvecs]
|
||||
`(do
|
||||
(defn ~(symbol (str (name op-name) "-clause"))
|
||||
~(format "Create a standalone clause of type `%s`." (name op-name))
|
||||
~@(for [argvec argvecs
|
||||
:let [arglist-expr (if (contains? (set argvec) '&)
|
||||
(cons 'list* (remove #{'&} argvec))
|
||||
argvec)]]
|
||||
`([~'query ~'stage-number ~@argvec]
|
||||
[~(keyword op-name) ~'query ~'stage-number ~@arglist-expr])))
|
||||
|
||||
(defn ~op-name
|
||||
~(format "Create a closure of clause of type `%s`." (name op-name))
|
||||
~@(for [argvec argvecs
|
||||
:let [arglist-expr (if (contains? (set argvec) '&)
|
||||
(cons 'list* (remove #{'&} argvec))
|
||||
argvec)]]
|
||||
`([~@argvec]
|
||||
(fn ~(symbol (str (name op-name) "-closure"))
|
||||
[~'query ~'stage-number]
|
||||
(apply ~(symbol (str (name op-name) "-clause")) ~'query ~'stage-number ~@arglist-expr)))))))
|
||||
@@ -1,7 +0,0 @@
|
||||
(ns macros.metabase.lib.filter)
|
||||
|
||||
(defmacro deffilter
|
||||
[filter-name argv]
|
||||
(let [argv (into ['query 'stage] (remove #{'&} argv))]
|
||||
`(defn ~filter-name "docstring" ~argv
|
||||
~argv)))
|
||||
@@ -1,4 +0,0 @@
|
||||
(ns macros.metabase.models.params.chain-filter-test)
|
||||
|
||||
(defmacro chain-filter [& _]
|
||||
`(metabase.models.params.chain-filter/chain-filter nil nil))
|
||||
@@ -1,9 +0,0 @@
|
||||
(ns macros.metabase.models.user-test)
|
||||
|
||||
(defmacro with-groups [bindings & body]
|
||||
`(let ~(into []
|
||||
(comp (partition-all 3)
|
||||
(mapcat (fn [[group-binding properties members]]
|
||||
[group-binding [properties members]])))
|
||||
bindings)
|
||||
~@body))
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns macros.metabase.query-processor.streaming)
|
||||
(ns metabase.query-processor.streaming)
|
||||
|
||||
(defmacro streaming-response [[x y z] & body]
|
||||
`(let [~x [~y ~z]]
|
||||
`(clojure.core/let [~x ~y]
|
||||
~z
|
||||
~@body))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns macros.metabase.related-test
|
||||
(:require [macros.common]))
|
||||
|
||||
(defmacro with-world [& body]
|
||||
`(let [~(macros.common/ignore-unused 'collection-id) nil
|
||||
~(macros.common/ignore-unused 'metric-id-a) nil
|
||||
~(macros.common/ignore-unused 'metric-id-b) nil
|
||||
~(macros.common/ignore-unused 'segment-id-a) nil
|
||||
~(macros.common/ignore-unused 'segment-id-b) nil
|
||||
~(macros.common/ignore-unused 'card-id-a) nil
|
||||
~(macros.common/ignore-unused 'card-id-b) nil
|
||||
~(macros.common/ignore-unused 'card-id-c) nil]
|
||||
~@body))
|
||||
@@ -1,8 +0,0 @@
|
||||
(ns macros.metabase.shared.util.namespaces)
|
||||
|
||||
(defmacro import-fn
|
||||
"Kondo macro replacement for [[metabase.shared.util.namespaces/import-fn]]."
|
||||
([sym]
|
||||
`(def ~(-> sym name symbol) "docstring" ~sym))
|
||||
([sym name]
|
||||
`(def ~name "docstring" ~sym)))
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns macros.metabase.test.data.users)
|
||||
|
||||
(defmacro with-group-for-user
|
||||
[[group-binding test-user-name-or-user-id group] & body]
|
||||
`(let [~group-binding [~test-user-name-or-user-id ~group]]
|
||||
~@body))
|
||||
@@ -1,5 +0,0 @@
|
||||
(ns macros.metabase.test.persistence)
|
||||
|
||||
(defmacro with-persistence-enabled [[persist-fn-sym] & body]
|
||||
`(clojure.core/let [~persist-fn-sym (fn [])]
|
||||
~@body))
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns macros.metabase.test.util)
|
||||
|
||||
(defmacro with-temp-env-var-value [bindings & body]
|
||||
`((constantly nil)
|
||||
~@(map second (partition-all 2 bindings))
|
||||
~@body))
|
||||
|
||||
(defmacro with-temporary-raw-setting-values [bindings & body]
|
||||
`((constantly nil)
|
||||
~@(map second (partition-all 2 bindings))
|
||||
~@body))
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns macros.metabase-enterprise.sandbox.test-util
|
||||
(:require [macros.common]))
|
||||
|
||||
(defmacro with-gtaps [gtaps-definition & body]
|
||||
`(let [~(macros.common/ignore-unused '&group) ~gtaps-definition]
|
||||
~@body))
|
||||
@@ -1,58 +0,0 @@
|
||||
(ns macros.metabase-enterprise.serialization.test-util
|
||||
(:require [macros.common]))
|
||||
|
||||
(defmacro with-world [& body]
|
||||
`(let [~(macros.common/ignore-unused 'db-id) nil
|
||||
~(macros.common/ignore-unused 'table-id) nil
|
||||
~(macros.common/ignore-unused 'table) nil
|
||||
~(macros.common/ignore-unused 'table-id-categories) nil
|
||||
~(macros.common/ignore-unused 'table-id-users) nil
|
||||
~(macros.common/ignore-unused 'table-id-checkins) nil
|
||||
~(macros.common/ignore-unused 'venues-pk-field-id) nil
|
||||
~(macros.common/ignore-unused 'numeric-field-id) nil
|
||||
~(macros.common/ignore-unused 'name-field-id) nil
|
||||
~(macros.common/ignore-unused 'latitude-field-id) nil
|
||||
~(macros.common/ignore-unused 'longitude-field-id) nil
|
||||
~(macros.common/ignore-unused 'category-field-id) nil
|
||||
~(macros.common/ignore-unused 'category-pk-field-id) nil
|
||||
~(macros.common/ignore-unused 'date-field-id) nil
|
||||
~(macros.common/ignore-unused 'users-pk-field-id) nil
|
||||
~(macros.common/ignore-unused 'user-id-field-id) nil
|
||||
~(macros.common/ignore-unused 'checkins->venues-field-id) nil
|
||||
~(macros.common/ignore-unused 'last-login-field-id) nil
|
||||
~(macros.common/ignore-unused 'collection-id) nil
|
||||
~(macros.common/ignore-unused 'collection-id-nested) nil
|
||||
~(macros.common/ignore-unused 'user-id-temp) nil
|
||||
~(macros.common/ignore-unused 'personal-collection-id) nil
|
||||
~(macros.common/ignore-unused 'pc-felicia-nested-id) nil
|
||||
~(macros.common/ignore-unused 'pc-nested-id) nil
|
||||
~(macros.common/ignore-unused 'pc-deeply-nested-id) nil
|
||||
~(macros.common/ignore-unused 'metric-id) nil
|
||||
~(macros.common/ignore-unused 'segment-id) nil
|
||||
~(macros.common/ignore-unused 'dashboard-id) nil
|
||||
~(macros.common/ignore-unused 'root-dashboard-id) nil
|
||||
~(macros.common/ignore-unused 'card-id) nil
|
||||
~(macros.common/ignore-unused 'card-arch-id) nil
|
||||
~(macros.common/ignore-unused 'card-id-root) nil
|
||||
~(macros.common/ignore-unused 'card-id-nested) nil
|
||||
~(macros.common/ignore-unused 'card-id-nested-query) nil
|
||||
~(macros.common/ignore-unused 'card-id-native-query) nil
|
||||
~(macros.common/ignore-unused 'dashcard-id) nil
|
||||
~(macros.common/ignore-unused 'dashcard-top-level-click-id) nil
|
||||
~(macros.common/ignore-unused 'dashcard-with-click-actions) nil
|
||||
~(macros.common/ignore-unused 'dashcard-with-textbox-id) nil
|
||||
~(macros.common/ignore-unused 'card-id-root-to-collection) nil
|
||||
~(macros.common/ignore-unused 'card-id-collection-to-root) nil
|
||||
~(macros.common/ignore-unused 'pulse-id) nil
|
||||
~(macros.common/ignore-unused 'pulsecard-root-id) nil
|
||||
~(macros.common/ignore-unused 'pulsecard-collection-id) nil
|
||||
~(macros.common/ignore-unused 'card-id-template-tags) nil
|
||||
~(macros.common/ignore-unused 'card-id-filter-agg) nil
|
||||
~(macros.common/ignore-unused 'card-id-temporal-unit) nil
|
||||
~(macros.common/ignore-unused 'snippet-id) nil
|
||||
~(macros.common/ignore-unused 'snippet-collection-id) nil
|
||||
~(macros.common/ignore-unused 'snippet-nested-collection-id) nil
|
||||
~(macros.common/ignore-unused 'nested-snippet-id) nil
|
||||
~(macros.common/ignore-unused 'card-id-with-native-snippet) nil
|
||||
~(macros.common/ignore-unused 'card-join-card-id) nil]
|
||||
~@body))
|
||||
@@ -10,10 +10,6 @@
|
||||
`(let [tb# (org.quartz.TriggerBuilder/newTrigger)]
|
||||
(clojurewerkz.quartzite.triggers/finalize (-> tb# ~@body))))
|
||||
|
||||
(defmacro simple-schedule
|
||||
[& body]
|
||||
`(-> {} ~@body))
|
||||
|
||||
(defmacro schedule
|
||||
[& body]
|
||||
`(let [s# ~(first body)]
|
||||
|
||||
8
.clj-kondo/macros/toucan/models.clj
Normal file
8
.clj-kondo/macros/toucan/models.clj
Normal file
@@ -0,0 +1,8 @@
|
||||
(ns toucan.models)
|
||||
|
||||
(defmacro defmodel [model-name & ks]
|
||||
`(do (clojure.core/defrecord ~model-name ~(vec (map (comp symbol name) ks)))
|
||||
(clojure.core/defrecord
|
||||
~(symbol (str model-name "Instance"))
|
||||
~(vec (map (comp symbol name) ks)))
|
||||
~(symbol (str model-name "Instance"))))
|
||||
@@ -1,14 +0,0 @@
|
||||
{:config-paths ["macros"]
|
||||
|
||||
:lint-as
|
||||
{}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
{methodical.core/defmethod hooks.methodical.macros/defmethod
|
||||
methodical.core/defmulti hooks.methodical.macros/defmulti
|
||||
methodical.macros/defmethod hooks.methodical.macros/defmethod
|
||||
methodical.macros/defmulti hooks.methodical.macros/defmulti}
|
||||
|
||||
:macroexpand
|
||||
{methodical.impl.combo.operator/defoperator macros.methodical.impl.combo.operator/defoperator}}}
|
||||
@@ -1,68 +0,0 @@
|
||||
(ns hooks.methodical.core
|
||||
(:require [clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
(defn add-next-method [fn-tail]
|
||||
(if (hooks/vector-node? (first fn-tail))
|
||||
(let [[args & body] fn-tail]
|
||||
(list*
|
||||
(-> (hooks/vector-node
|
||||
(cons (hooks/token-node 'next-method)
|
||||
(:children args)))
|
||||
(with-meta (meta args)))
|
||||
;; so Kondo stops complaining about it being unused.
|
||||
(hooks/token-node 'next-method)
|
||||
body))
|
||||
(for [list-node fn-tail]
|
||||
(hooks/list-node (add-next-method (:children list-node))))))
|
||||
|
||||
(defn defmethod
|
||||
[{{[_ multimethod & [first-arg :as args]] :children, :as node} :node}]
|
||||
#_(clojure.pprint/pprint (hooks/sexpr node))
|
||||
(let [[aux-qualifier dispatch-value & fn-tail] (if (#{:before :after :around} (hooks/sexpr first-arg))
|
||||
(cons (hooks/sexpr first-arg) (rest args))
|
||||
(cons nil args))
|
||||
fn-tail (if (contains? #{:around nil} aux-qualifier)
|
||||
(add-next-method fn-tail)
|
||||
fn-tail)
|
||||
result (hooks/list-node
|
||||
(list* (hooks/token-node 'clojure.core/defmethod)
|
||||
multimethod
|
||||
dispatch-value
|
||||
fn-tail))]
|
||||
#_(println "=>")
|
||||
#_(clojure.pprint/pprint (hooks/sexpr result))
|
||||
{:node result}))
|
||||
|
||||
(defn defmulti
|
||||
[{{[_ multimethod-name & args] :children, :as node} :node}]
|
||||
#_(clojure.pprint/pprint (hooks/sexpr node))
|
||||
(let [[docstring & args] (if (hooks/string-node? (first args))
|
||||
args
|
||||
(cons nil args))
|
||||
[attribute-map & args] (if (hooks/map-node? (first args))
|
||||
args
|
||||
(cons nil args))
|
||||
;; if there wasn't a positional dispatch function arg passed just use (constantly nil) so Kondo won't complain
|
||||
[dispatch-fn & kv-options] (if (odd? (count args))
|
||||
args
|
||||
(cons (hooks/list-node
|
||||
(list
|
||||
(hooks/token-node 'clojure.core/constantly)
|
||||
(hooks/token-node 'nil)))
|
||||
args))]
|
||||
(let [defmulti-form (hooks/list-node
|
||||
(filter
|
||||
some?
|
||||
[(hooks/token-node 'clojure.core/defmulti)
|
||||
multimethod-name
|
||||
docstring
|
||||
attribute-map
|
||||
dispatch-fn]))
|
||||
result (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'do)
|
||||
defmulti-form
|
||||
kv-options))]
|
||||
#_(println "=>")
|
||||
#_(clojure.pprint/pprint (hooks/sexpr result))
|
||||
{:node result})))
|
||||
@@ -1,185 +0,0 @@
|
||||
(ns hooks.methodical.macros
|
||||
(:refer-clojure :exclude [defmulti defmethod])
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]))
|
||||
|
||||
;;; The code below is basically simulating the spec for parsing defmethod args without using spec. It uses a basic
|
||||
;;; backtracking algorithm to achieve a similar result. Parsing defmethod args is kinda complicated.
|
||||
;;;
|
||||
;;; Unfortunately this is hardcoded to `:before`, `:after`, and `:around` as the only allowed qualifiers for now... at
|
||||
;;; some point in the future we'll have to figure out how to fix this and support other qualifiers too.
|
||||
|
||||
(defn- bindings-vector? [x]
|
||||
(and (hooks/vector-node? x)
|
||||
(every? (some-fn hooks/token-node?
|
||||
hooks/map-node?
|
||||
hooks/vector-node?)
|
||||
(:children x))))
|
||||
|
||||
(defn- single-arity-fn-tail? [args]
|
||||
(bindings-vector? (first args)))
|
||||
|
||||
(defn- n-arity-fn-tail? [args]
|
||||
(and (seq args)
|
||||
(every? (fn [x]
|
||||
(and (hooks/list-node? x)
|
||||
(single-arity-fn-tail? (:children x))))
|
||||
args)))
|
||||
|
||||
(defn- fn-tail? [args]
|
||||
(or (single-arity-fn-tail? args)
|
||||
(n-arity-fn-tail? args)))
|
||||
|
||||
(defn- qualifier? [x]
|
||||
(and (hooks/keyword-node? x)
|
||||
(#{:before :after :around} (hooks/sexpr x))))
|
||||
|
||||
(defn- dispatch-value?
|
||||
"A dispatch value can be anything except for qualifier keyword or a list that looks like part of a n-arity function tail
|
||||
e.g. `([x] x)`."
|
||||
[x]
|
||||
(and (not (qualifier? x))
|
||||
(or (not (hooks/list-node? x))
|
||||
(not (single-arity-fn-tail? (:children x))))))
|
||||
|
||||
(defonce ^:private backtrack (Exception.))
|
||||
|
||||
(defn- parse-defmethod-args
|
||||
([unparsed]
|
||||
(let [parses (atom [])]
|
||||
(try
|
||||
(parse-defmethod-args parses {} unparsed)
|
||||
(catch Exception _
|
||||
(when (zero? (count @parses))
|
||||
(throw (ex-info (format "Unable to parse defmethod args: %s" (pr-str (mapv hooks/sexpr unparsed)))
|
||||
{:args (mapv hooks/sexpr unparsed)})))
|
||||
(when (> (count @parses) 1)
|
||||
(throw (ex-info (format "Ambiguous defmethod args: %s" (pr-str (mapv hooks/sexpr unparsed)))
|
||||
{:args (mapv hooks/sexpr unparsed)
|
||||
:parses @parses})))
|
||||
(first @parses)))))
|
||||
|
||||
([parses parsed unparsed]
|
||||
(cond
|
||||
(and (not (contains? parsed :qualifier))
|
||||
(qualifier? (first unparsed)))
|
||||
(try
|
||||
(parse-defmethod-args parses (assoc parsed :qualifier (first unparsed)) (rest unparsed))
|
||||
(catch Exception _
|
||||
(parse-defmethod-args parses (assoc parsed :qualifier nil) unparsed)))
|
||||
|
||||
(and (not (contains? parsed :dispatch-value))
|
||||
(dispatch-value? (first unparsed)))
|
||||
(parse-defmethod-args parses (assoc parsed :dispatch-value (first unparsed)) (rest unparsed))
|
||||
|
||||
(not (contains? parsed :dispatch-value))
|
||||
(throw backtrack)
|
||||
|
||||
(and (not (contains? parsed :unique-key))
|
||||
(:qualifier parsed) ; can only have unique keys for aux methods
|
||||
(not (hooks/string-node? (first unparsed)))
|
||||
(not (hooks/list-node? (first unparsed)))
|
||||
(not (hooks/vector-node? (first unparsed))))
|
||||
(try
|
||||
(parse-defmethod-args parses (assoc parsed :unique-key (first unparsed)) (rest unparsed))
|
||||
(catch Exception _
|
||||
(parse-defmethod-args parses (assoc parsed :unique-key nil) unparsed)))
|
||||
|
||||
(and (not (contains? parsed :docstring))
|
||||
(hooks/string-node? (first unparsed)))
|
||||
(try
|
||||
(parse-defmethod-args parses (assoc parsed :docstring (first unparsed)) (rest unparsed))
|
||||
(catch Exception _
|
||||
(parse-defmethod-args parses (assoc parsed :docstring nil) unparsed)))
|
||||
|
||||
(fn-tail? unparsed)
|
||||
(do
|
||||
(swap! parses conj (assoc parsed :fn-tail unparsed))
|
||||
(throw backtrack))
|
||||
|
||||
:else
|
||||
(throw backtrack))))
|
||||
|
||||
(defn defmethod
|
||||
[{{[_ multimethod & args] :children, :as node} :node}]
|
||||
(#_println)
|
||||
#_(clojure.pprint/pprint (hooks/sexpr node))
|
||||
(let [parsed (parse-defmethod-args args)]
|
||||
#_(doseq [[k v] parsed]
|
||||
(println \newline k '=> (pr-str (some-> v hooks/sexpr))))
|
||||
(let [fn-tail (:fn-tail parsed)
|
||||
other-stuff (dissoc parsed :fn-tail)
|
||||
result (hooks/list-node
|
||||
(concat
|
||||
[(hooks/token-node 'do)
|
||||
multimethod]
|
||||
(filter some? (vals other-stuff))
|
||||
[(-> (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'fn)
|
||||
(hooks/token-node (if (contains? #{nil :around} (some-> (:qualifier parsed) hooks/sexpr))
|
||||
'next-method
|
||||
'__FN__NAME__THAT__YOU__CANNOT__REFER__TO__))
|
||||
fn-tail))
|
||||
(vary-meta update :clj-kondo/ignore conj :redundant-fn-wrapper))]))]
|
||||
#_(println "=>")
|
||||
#_(clojure.pprint/pprint (hooks/sexpr result))
|
||||
{:node result})))
|
||||
|
||||
;;; this stuff is for debugging things to make sure we didn't do something dumb
|
||||
(comment
|
||||
(defn defmethod* [form]
|
||||
(binding [*print-meta* true]
|
||||
(clojure.pprint/pprint
|
||||
(hooks/sexpr (:node (defmethod {:node (hooks/parse-string (str form))}))))))
|
||||
|
||||
(defmethod* '(defmethod mf :second [& _] 2))
|
||||
|
||||
(defmethod* '(m/defmethod multi-arity :k
|
||||
([x]
|
||||
{:x x})
|
||||
([x y]
|
||||
{:x x, :y y})))
|
||||
|
||||
(defmethod* '(m/defmethod mf1 :docstring
|
||||
"Docstring"
|
||||
[_x]))
|
||||
|
||||
(defmethod* '(m/defmethod mf1 :around :dispatch-value
|
||||
"Docstring"
|
||||
[x]
|
||||
(next-method x))))
|
||||
|
||||
(defn defmulti
|
||||
[{{[_ multimethod-name & args] :children, :as node} :node}]
|
||||
#_(clojure.pprint/pprint (hooks/sexpr node))
|
||||
(let [[docstring & args] (if (hooks/string-node? (first args))
|
||||
args
|
||||
(cons nil args))
|
||||
[attribute-map & args] (if (hooks/map-node? (first args))
|
||||
args
|
||||
(cons nil args))
|
||||
;; if there wasn't a positional dispatch function arg passed just use (constantly nil) so Kondo won't complain
|
||||
[dispatch-fn & kv-options] (if (odd? (count args))
|
||||
args
|
||||
(cons (hooks/list-node
|
||||
(list
|
||||
(hooks/token-node 'clojure.core/constantly)
|
||||
(hooks/token-node 'nil)))
|
||||
args))]
|
||||
(let [defmulti-form (hooks/list-node
|
||||
(filter
|
||||
some?
|
||||
[(hooks/token-node 'clojure.core/defmulti)
|
||||
multimethod-name
|
||||
docstring
|
||||
attribute-map
|
||||
dispatch-fn]))
|
||||
result (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'do)
|
||||
defmulti-form
|
||||
kv-options))]
|
||||
#_(println "=>")
|
||||
#_(clojure.pprint/pprint (hooks/sexpr result))
|
||||
{:node result})))
|
||||
@@ -1,7 +0,0 @@
|
||||
(ns macros.methodical.impl.combo.operator)
|
||||
|
||||
;; not exactly what actually happens but this is close enough to be able to lint it
|
||||
(defmacro defoperator [operator-name [methods-binding invoke-binding] & body]
|
||||
`(defmethod methodical.impl.combo.operator/operator ~(keyword operator-name)
|
||||
[~methods-binding ~invoke-binding]
|
||||
~@body))
|
||||
@@ -1,2 +0,0 @@
|
||||
{:lint-as {malli.experimental/defn schema.core/defn}
|
||||
:linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}
|
||||
@@ -1,62 +0,0 @@
|
||||
{:lint-as {potemkin.collections/compile-if clojure.core/if
|
||||
potemkin.collections/reify-map-type clojure.core/reify
|
||||
potemkin.collections/def-map-type clj-kondo.lint-as/def-catch-all
|
||||
potemkin.collections/def-derived-map clj-kondo.lint-as/def-catch-all
|
||||
|
||||
potemkin.types/reify+ clojure.core/reify
|
||||
potemkin.types/defprotocol+ clojure.core/defprotocol
|
||||
potemkin.types/deftype+ clojure.core/deftype
|
||||
potemkin.types/defrecord+ clojure.core/defrecord
|
||||
potemkin.types/definterface+ clojure.core/defprotocol
|
||||
potemkin.types/extend-protocol+ clojure.core/extend-protocol
|
||||
potemkin.types/def-abstract-type clj-kondo.lint-as/def-catch-all
|
||||
|
||||
potemkin.utils/doit clojure.core/doseq
|
||||
potemkin.utils/doary clojure.core/doseq
|
||||
potemkin.utils/condp-case clojure.core/condp
|
||||
potemkin.utils/fast-bound-fn clojure.core/bound-fn
|
||||
|
||||
potemkin.walk/prewalk clojure.walk/prewalk
|
||||
potemkin.walk/postwalk clojure.walk/postwalk
|
||||
potemkin.walk/walk clojure.walk/walk
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; top-level from import-vars
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Have hooks
|
||||
;;potemkin/import-fn potemkin.namespaces/import-fn
|
||||
;;potemkin/import-macro potemkin.namespaces/import-macro
|
||||
;;potemkin/import-def potemkin.namespaces/import-def
|
||||
|
||||
;; Internal, not transitive
|
||||
;;potemkin/unify-gensyms potemkin.macros/unify-gensyms
|
||||
;;potemkin/normalize-gensyms potemkin.macros/normalize-gensyms
|
||||
;;potemkin/equivalent? potemkin.macros/equivalent?
|
||||
|
||||
potemkin/condp-case clojure.core/condp
|
||||
potemkin/doit potemkin.utils/doit
|
||||
potemkin/doary potemkin.utils/doary
|
||||
|
||||
potemkin/def-abstract-type clj-kondo.lint-as/def-catch-all
|
||||
potemkin/reify+ clojure.core/reify
|
||||
potemkin/defprotocol+ clojure.core/defprotocol
|
||||
potemkin/deftype+ clojure.core/deftype
|
||||
potemkin/defrecord+ clojure.core/defrecord
|
||||
potemkin/definterface+ clojure.core/defprotocol
|
||||
potemkin/extend-protocol+ clojure.core/extend-protocol
|
||||
|
||||
potemkin/reify-map-type clojure.core/reify
|
||||
potemkin/def-derived-map clj-kondo.lint-as/def-catch-all
|
||||
potemkin/def-map-type clj-kondo.lint-as/def-catch-all}
|
||||
|
||||
;; leave import-vars alone, kondo special-cases it
|
||||
:hooks {:macroexpand {#_#_potemkin.namespaces/import-vars potemkin.namespaces/import-vars
|
||||
potemkin.namespaces/import-fn potemkin.namespaces/import-fn
|
||||
potemkin.namespaces/import-macro potemkin.namespaces/import-macro
|
||||
potemkin.namespaces/import-def potemkin.namespaces/import-def
|
||||
|
||||
#_#_potemkin/import-vars potemkin.namespaces/import-vars
|
||||
potemkin/import-fn potemkin.namespaces/import-fn
|
||||
potemkin/import-macro potemkin.namespaces/import-macro
|
||||
potemkin/import-def potemkin.namespaces/import-def}}}
|
||||
@@ -1,56 +0,0 @@
|
||||
(ns potemkin.namespaces
|
||||
(:require [clj-kondo.hooks-api :as api]))
|
||||
|
||||
(defn import-macro*
|
||||
([sym]
|
||||
`(def ~(-> sym name symbol) ~sym))
|
||||
([sym name]
|
||||
`(def ~name ~sym)))
|
||||
|
||||
(defmacro import-fn
|
||||
([sym]
|
||||
(import-macro* sym))
|
||||
([sym name]
|
||||
(import-macro* sym name)))
|
||||
|
||||
(defmacro import-macro
|
||||
([sym]
|
||||
(import-macro* sym))
|
||||
([sym name]
|
||||
(import-macro* sym name)))
|
||||
|
||||
(defmacro import-def
|
||||
([sym]
|
||||
(import-macro* sym))
|
||||
([sym name]
|
||||
(import-macro* sym name)))
|
||||
|
||||
#_
|
||||
(defmacro import-vars
|
||||
"Imports a list of vars from other namespaces."
|
||||
[& syms]
|
||||
(let [unravel (fn unravel [x]
|
||||
(if (sequential? x)
|
||||
(->> x
|
||||
rest
|
||||
(mapcat unravel)
|
||||
(map
|
||||
#(symbol
|
||||
(str (first x)
|
||||
(when-let [n (namespace %)]
|
||||
(str "." n)))
|
||||
(name %))))
|
||||
[x]))
|
||||
syms (mapcat unravel syms)
|
||||
result `(do
|
||||
~@(map
|
||||
(fn [sym]
|
||||
(let [vr (resolve sym)
|
||||
m (meta vr)]
|
||||
(cond
|
||||
(nil? vr) `(throw (ex-info (format "`%s` does not exist" '~sym) {}))
|
||||
(:macro m) `(def ~(-> sym name symbol) ~sym)
|
||||
(:arglists m) `(def ~(-> sym name symbol) ~sym)
|
||||
:else `(def ~(-> sym name symbol) ~sym))))
|
||||
syms))]
|
||||
result))
|
||||
@@ -1 +0,0 @@
|
||||
{:lint-as {schema.test/deftest clojure.test/deftest}}
|
||||
@@ -1,2 +0,0 @@
|
||||
{metabase.api.collection/foo [[:inner 0]]
|
||||
toucan.db/insert! [[:block 1]]}
|
||||
@@ -1,11 +1,11 @@
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/java:11
|
||||
|
||||
# Set up nodesource, install node, yarn, fontconfig for static viz, rlwrap for dev ergonomics
|
||||
RUN apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com\
|
||||
&& apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends yarn
|
||||
|
||||
RUN ( curl -fsSL https://deb.nodesource.com/setup_14.x | bash ) \
|
||||
&& export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com \
|
||||
&& apt-get update && apt-get -y install --no-install-recommends nodejs yarn rlwrap fontconfig
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash
|
||||
RUN apt-get update && apt-get -y install --no-install-recommends nodejs
|
||||
|
||||
# install Clojure
|
||||
RUN curl https://download.clojure.org/install/linux-install-1.11.0.1100.sh | bash
|
||||
RUN curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh \
|
||||
&& bash ./linux-install-1.10.3.933.sh
|
||||
@@ -13,9 +13,5 @@
|
||||
"forwardPorts": [3000],
|
||||
|
||||
// Comment out the next line to run as root instead.
|
||||
"remoteUser": "vscode",
|
||||
|
||||
"runArgs": ["--network=metabase-dev"],
|
||||
|
||||
"postStartCommand": "git config --global --add safe.directory /workspaces/metabase"
|
||||
"remoteUser": "vscode"
|
||||
}
|
||||
|
||||
@@ -19,29 +19,23 @@
|
||||
(clojure-mode
|
||||
;; Specify which arg is the docstring for certain macros
|
||||
;; (Add more as needed)
|
||||
(eval . (put 'defendpoint-schema 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'defendpoint 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'defendpoint-async 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'define-premium-feature 'clojure-doc-string-elt 2))
|
||||
(eval . (put 'api/defendpoint-schema 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'api/defendpoint 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'api/defendpoint-async 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'defsetting 'clojure-doc-string-elt 2))
|
||||
(eval . (put 'setting/defsetting 'clojure-doc-string-elt 2))
|
||||
(eval . (put 's/defn 'clojure-doc-string-elt 2))
|
||||
(eval . (put 'p.types/defprotocol+ 'clojure-doc-string-elt 2))
|
||||
(eval . (put 'methodical/defmethod 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'methodical/defmulti 'clojure-doc-string-elt 2))
|
||||
(eval . (put 'mi/define-simple-hydration-method 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'mi/define-batched-hydration-method 'clojure-doc-string-elt 3))
|
||||
(eval . (put 'mu/defn 'clojure-doc-string-elt 2))
|
||||
;; Define custom indentation for functions inside metabase.
|
||||
;; This list isn't complete; add more forms as we come across them.
|
||||
;;
|
||||
;; `put-clojure-indent' is a safe-local-eval-function, so use a bunch of calls to that
|
||||
;; instead of one call to `define-clojure-indent'
|
||||
(eval . (put-clojure-indent 'api/let-404 1))
|
||||
(eval . (put-clojure-indent 'c/step 1))
|
||||
(eval . (put-clojure-indent 'db/insert-many! 1))
|
||||
(eval . (put-clojure-indent 'db/update! 2))
|
||||
(eval . (put-clojure-indent 'impl/test-migrations 2))
|
||||
(eval . (put-clojure-indent 'let-404 0))
|
||||
(eval . (put-clojure-indent 'macros/case 0))
|
||||
@@ -50,46 +44,41 @@
|
||||
(eval . (put-clojure-indent 'mbql.match/match-one 1))
|
||||
(eval . (put-clojure-indent 'mbql.match/replace 1))
|
||||
(eval . (put-clojure-indent 'mbql.match/replace-in 2))
|
||||
(eval . (put-clojure-indent 'mbql.u/replace 1))
|
||||
(eval . (put-clojure-indent 'mi/define-methods '(:form)))
|
||||
(eval . (put-clojure-indent 'mt/dataset 1))
|
||||
(eval . (put-clojure-indent 'mt/format-rows-by 1))
|
||||
(eval . (put-clojure-indent 'mt/query 1))
|
||||
(eval . (put-clojure-indent 'mt/test-drivers 1))
|
||||
(eval . (put-clojure-indent 'mt/test-driver 1))
|
||||
(eval . (put-clojure-indent 'prop/for-all 1))
|
||||
(eval . (put-clojure-indent 'qp.streaming/streaming-response 1))
|
||||
(eval . (put-clojure-indent 'u/prog1 1))
|
||||
(eval . (put-clojure-indent 'u/select-keys-when 1))
|
||||
(eval . (put-clojure-indent 'with-meta '(:form)))
|
||||
(eval . (put-clojure-indent 'tc/quick-check 1))
|
||||
(eval . (put-clojure-indent 'u/strict-extend 1))
|
||||
;; these ones have to be done with `define-clojure-indent' for now because of upstream bug
|
||||
;; https://github.com/clojure-emacs/clojure-mode/issues/600 once that's resolved we should use `put-clojure-indent'
|
||||
;; instead. Please don't add new entries unless they don't work with `put-clojure-indent'
|
||||
(eval . (define-clojure-indent
|
||||
(l/matcha '(1 (:defn)))
|
||||
(l/matche '(1 (:defn)))
|
||||
(p.types/def-abstract-type '(1 (:defn)))
|
||||
(p.types/defprotocol+ '(1 (:defn)))
|
||||
(p.types/defrecord+ '(2 nil nil (:defn)))
|
||||
(p.types/deftype+ '(2 nil nil (:defn)))
|
||||
(p/def-map-type '(2 nil nil (:defn)))
|
||||
(p/defprotocol+ '(1 (:defn)))
|
||||
(p/defrecord+ '(2 nil nil (:defn)))
|
||||
(p/deftype+ '(2 nil nil (:defn)))
|
||||
(tools.macro/macrolet '(1 ((:defn)) :form))))
|
||||
(l/matcha '(1 (:defn)))
|
||||
(l/matche '(1 (:defn)))
|
||||
(p.types/def-abstract-type '(1 (:defn)))
|
||||
(p.types/defprotocol+ '(1 (:defn)))
|
||||
(p.types/defrecord+ '(2 nil nil (:defn)))
|
||||
(p.types/deftype+ '(2 nil nil (:defn)))
|
||||
(p/def-map-type '(2 nil nil (:defn)))
|
||||
(p/defprotocol+ '(1 (:defn)))
|
||||
(p/defrecord+ '(2 nil nil (:defn)))
|
||||
(p/deftype+ '(2 nil nil (:defn)))
|
||||
(tools.macro/macrolet '(1 ((:defn)) :form))))
|
||||
(cider-clojure-cli-aliases . "dev:drivers:drivers-dev:ee:ee-dev:user")
|
||||
(clojure-indent-style . always-align)
|
||||
(cljr-favor-prefix-notation . nil)
|
||||
(clojure-docstring-fill-column . 118)
|
||||
(cider-preferred-build-tool . clojure-cli)
|
||||
(cider-default-cljs-repl . shadow-select)
|
||||
(cider-shadow-default-options . "node-repl"))
|
||||
(cider-preferred-build-tool . clojure-cli))
|
||||
|
||||
("shared"
|
||||
(clojure-mode
|
||||
(cider-default-cljs-repl . shadow-select)
|
||||
(cider-shadow-default-options . "node-repl")
|
||||
(cider-preferred-build-tool . shadow-cljs)))
|
||||
|
||||
("bin"
|
||||
(clojure-mode
|
||||
(cider-clojure-cli-aliases . "dev:drivers:build:build-dev"))))
|
||||
(cider-clojure-cli-aliases . "dev"))))
|
||||
|
||||
87
.eslintrc
87
.eslintrc
@@ -4,58 +4,13 @@
|
||||
"no-undef": 2,
|
||||
"no-var": 1,
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "none",
|
||||
"varsIgnorePattern": "^_.+",
|
||||
"ignoreRestSiblings": true
|
||||
}
|
||||
1,
|
||||
{ "vars": "all", "args": "none", "varsIgnorePattern": "^_" }
|
||||
],
|
||||
"no-empty": [1, { "allowEmptyCatch": true }],
|
||||
"curly": [1, "all"],
|
||||
"eqeqeq": [1, "smart"],
|
||||
"import/no-commonjs": 1,
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "react",
|
||||
"group": "builtin",
|
||||
"position": "before"
|
||||
},
|
||||
{
|
||||
"pattern": "metabase/**",
|
||||
"group": "internal"
|
||||
},
|
||||
{
|
||||
"pattern": "metabase/**/components",
|
||||
"group": "internal",
|
||||
"position": "before"
|
||||
},
|
||||
{
|
||||
"pattern": "__**",
|
||||
"group": "internal",
|
||||
"position": "before"
|
||||
},
|
||||
{
|
||||
"pattern": "metabase-lib/**",
|
||||
"group": "internal",
|
||||
"position": "after"
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
"internal",
|
||||
"parent",
|
||||
"sibling",
|
||||
"index",
|
||||
"object"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-console": 0,
|
||||
"react/no-is-mounted": 2,
|
||||
"react/prefer-es6-class": 2,
|
||||
@@ -72,7 +27,7 @@
|
||||
"react/forbid-component-props": [2, { "forbid": ["w", "h"] }],
|
||||
"react-hooks/exhaustive-deps": [
|
||||
"warn",
|
||||
{ "additionalHooks": "(useSyncedQueryString|useSafeAsyncFunction)" }
|
||||
{ "additionalHooks": "(useSyncedQueryString|useAsyncFunction)" }
|
||||
],
|
||||
"prefer-const": [1, { "destructuring": "all" }],
|
||||
"no-useless-escape": 0,
|
||||
@@ -88,8 +43,7 @@
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"commonjs": true,
|
||||
"jest": true,
|
||||
"jest/globals": true
|
||||
"jest": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": ["react", "no-only-tests"],
|
||||
@@ -101,7 +55,6 @@
|
||||
"plugin:import/warnings"
|
||||
],
|
||||
"settings": {
|
||||
"import/internal-regex": "^metabase/|^metabase-lib/",
|
||||
"import/resolver": "webpack",
|
||||
"import/ignore": ["\\.css$"],
|
||||
"react": {
|
||||
@@ -118,6 +71,9 @@
|
||||
"extends": ["plugin:@typescript-eslint/recommended"],
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"prefer-rest-params": "off",
|
||||
@@ -125,34 +81,7 @@
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-this-alias": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "none",
|
||||
"varsIgnorePattern": "^_.+",
|
||||
"ignoreRestSiblings": true,
|
||||
"destructuredArrayIgnorePattern": "^_"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:jest/recommended",
|
||||
"plugin:jest-dom/recommended",
|
||||
"plugin:testing-library/react"
|
||||
],
|
||||
"plugins": ["jest", "jest-dom", "testing-library"],
|
||||
"files": [
|
||||
"*.unit.spec.ts",
|
||||
"*.unit.spec.tsx",
|
||||
"*.unit.spec.js",
|
||||
"*.unit.spec.jsx"
|
||||
],
|
||||
"rules": {
|
||||
"jest/valid-title": ["error", { "ignoreTypeOfDescribeName": true }]
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -6,19 +6,15 @@ labels: ".Needs Triage, Type:Bug"
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
**Read this before creating a bug report**
|
||||
- if any of the sections are incomplete, we might close the bug report since we won't be able to reproduce it
|
||||
- have you checked if the bug has already been reported? As we close duplicate reports, please search on the issue tracker if the problem has been reported before
|
||||
- use as many screenshots or videos as possible to describe what you're seeing, all visual representations speak for themselves
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Logs**
|
||||
Please include JavaScript console logs (open the browser dev tools and check the "console" tab) as well as the server logs (Metabase logs that you can get from Settings -> Admin -> Troubleshooting -> Logs) around the time this bug occurred. For information about how to get these, consult our [bug troubleshooting guide](https://metabase.com/docs/latest/troubleshooting-guide/bugs.html)
|
||||
Please include javascript console and server logs around the time this bug occurred. For information about how to get these, consult our [bug troubleshooting guide](https://metabase.com/docs/latest/troubleshooting-guide/bugs.html)
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior (if you can reproduce the bug using the Sample Database, we will find the issue faster):
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
@@ -27,12 +23,12 @@ Steps to reproduce the behavior (if you can reproduce the bug using the Sample D
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots/videos**
|
||||
If applicable, add screenshots/videos to help explain your problem.
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Information about your Metabase Installation:**
|
||||
|
||||
You can get this information by going to Admin -> Troubleshooting, or simply post the JSON you see in that page.
|
||||
You can get this information by going to Admin -> Troubleshooting.
|
||||
|
||||
- Your browser and the version: (e.g., Chrome 52.1, Firefox 48.0, Safari 11.1, …)
|
||||
- Your operating system: (e.g., OS X 10.10, Windows 10.1809, Ubuntu 16.04, …)
|
||||
|
||||
28
.github/PULL_REQUEST_TEMPLATE.md
vendored
28
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,24 +1,10 @@
|
||||
> **Warning**
|
||||
>
|
||||
> If that is your first contribution to Metabase, please sign the [Contributor License Agreement](https://docs.google.com/a/metabase.com/forms/d/1oV38o7b9ONFSwuzwmERRMi9SYrhYeOrkbmNaq9pOJ_E/viewform) (unless it's a tiny documentation change). Also, if you're attempting to fix a translation issue, please submit your changes to our [POEditor project](https://poeditor.com/join/project/ynjQmwSsGh) instead of opening a PR.
|
||||
###### Before submitting the PR, please make sure you do the following
|
||||
|
||||
Closes https://github.com/metabase/metabase/issues/[issue_number]
|
||||
- [ ] If you're attempting to fix a translation issue, please submit your changes to our [POEditor project](https://poeditor.com/join/project/ynjQmwSsGh) instead of opening a PR.
|
||||
|
||||
### Description
|
||||
### Tests
|
||||
|
||||
Describe the overall approach and the problem being solved.
|
||||
|
||||
### How to verify
|
||||
|
||||
Describe the steps to verify that the changes are working as expected.
|
||||
|
||||
1. New question -> Sample Dataset -> ...
|
||||
2. ...
|
||||
|
||||
### Demo
|
||||
|
||||
_Upload a demo video or before/after screenshots if sensible or remove the section_
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Tests have been added/updated to cover changes in this PR
|
||||
- [ ] Run the frontend and Cypress end-to-end tests with `yarn lint && yarn test`)
|
||||
- [ ] If there are changes to the backend codebase, run the backend tests with `clojure -X:dev:test`
|
||||
- [ ] Sign the [Contributor License Agreement](https://docs.google.com/a/metabase.com/forms/d/1oV38o7b9ONFSwuzwmERRMi9SYrhYeOrkbmNaq9pOJ_E/viewform)
|
||||
(unless it's a tiny documentation change).
|
||||
|
||||
@@ -22,7 +22,7 @@ runs:
|
||||
COMMIT=$(env -i git log $BASE_REF --grep="(#$PULL_REQUEST_NUMBER)" --format="%H")
|
||||
echo "commit SHA $COMMIT"
|
||||
|
||||
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
|
||||
echo "::set-output name=commit::$COMMIT"
|
||||
id: find-squashed-commit
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
@@ -7,19 +7,19 @@ outputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
- uses: actions/github-script@v4
|
||||
id: get-latest-release-branch
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
const releaseBranches = await github.rest.git.listMatchingRefs({
|
||||
const releaseBranches = await github.git.listMatchingRefs({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: "heads/release-x.",
|
||||
});
|
||||
|
||||
const getVersionFromBranch = branch => {
|
||||
const match = branch.match(/release-x\.(.*?)\.x$/);
|
||||
const match = branch.match(/release-x\.(.*?)\.x/);
|
||||
return match && parseInt(match[1]);
|
||||
};
|
||||
const latestReleaseBranch = releaseBranches.data
|
||||
|
||||
@@ -9,7 +9,7 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
- uses: actions/github-script@v4
|
||||
id: get-latest-release-branch
|
||||
with:
|
||||
result-encoding: string
|
||||
@@ -26,7 +26,7 @@ runs:
|
||||
body += ` [[Logs]](${runUrl})`;
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
github.issues.createComment({
|
||||
issue_number: context.payload.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
|
||||
9
.github/actions/prepare-backend/action.yml
vendored
9
.github/actions/prepare-backend/action.yml
vendored
@@ -5,7 +5,7 @@ inputs:
|
||||
default: '11'
|
||||
clojure-version:
|
||||
required: true
|
||||
default: '1.11.1.1262'
|
||||
default: '1.10.3.933'
|
||||
m2-cache-key:
|
||||
description: 'Key to cache M2 packages from Maven Central'
|
||||
required: true
|
||||
@@ -24,13 +24,8 @@ runs:
|
||||
run: |
|
||||
curl -O https://download.clojure.org/install/linux-install-${{ inputs.clojure-version }}.sh &&
|
||||
sudo bash ./linux-install-${{ inputs.clojure-version }}.sh
|
||||
- name: Check to see if dependencies should be cached
|
||||
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
run: echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
|
||||
shell: bash
|
||||
- name: Get M2 cache
|
||||
uses: actions/cache@v3
|
||||
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.m2
|
||||
|
||||
7
.github/actions/prepare-cypress/action.yml
vendored
7
.github/actions/prepare-cypress/action.yml
vendored
@@ -2,13 +2,8 @@ name: Prepare cypress environment
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Check to see if dependencies should be cached
|
||||
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
run: echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
|
||||
shell: bash
|
||||
- name: Get Cypress cache
|
||||
uses: actions/cache@v3
|
||||
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/Cypress
|
||||
key: ${{ runner.os }}-Cypress-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
17
.github/actions/prepare-frontend/action.yml
vendored
17
.github/actions/prepare-frontend/action.yml
vendored
@@ -5,26 +5,15 @@ runs:
|
||||
- name: Prepare Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
# Please don't bump this version to anything higher.
|
||||
# See https://github.com/facebook/jest/issues/11956 for more details,
|
||||
# as a lot of people couldn't complete a jest run with any other versions.
|
||||
node-version: 16.10.0
|
||||
node-version: 14.x
|
||||
cache: 'yarn'
|
||||
- name: Check to see if dependencies should be cached
|
||||
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
run: |
|
||||
echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
|
||||
yarn cache clean
|
||||
shell: bash
|
||||
- name: Get M2 cache
|
||||
uses: actions/cache@v3
|
||||
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-cljs-${{ hashFiles('**/shadow-cljs.edn') }}
|
||||
- name: Get node_modules cache
|
||||
uses: actions/cache@v3
|
||||
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
@@ -9,7 +9,7 @@ runs:
|
||||
run: sha256sum ./target/uberjar/metabase.jar > SHA256.sum
|
||||
shell: bash
|
||||
- name: Upload JARs as artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
path: |
|
||||
|
||||
35
.github/actions/test-driver/action.yml
vendored
35
.github/actions/test-driver/action.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: Test database driver
|
||||
inputs:
|
||||
junit-name:
|
||||
required: true
|
||||
default: 'driver'
|
||||
test-args:
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: driver-${{ inputs.junit-name }}
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
shell: bash
|
||||
- name: Setup upterm session
|
||||
uses: lhotari/action-upterm@v1
|
||||
- name: Test database driver
|
||||
run: clojure -X:dev:ci:ee:ee-dev:drivers:drivers-dev:test ${{ inputs.test-args }}
|
||||
shell: bash
|
||||
- name: Publish Test Report (JUnit)
|
||||
uses: dorny/test-reporter@v1
|
||||
if: failure()
|
||||
with:
|
||||
path: 'target/junit/**/*_test.xml'
|
||||
name: JUnit Test Report ${{ inputs.junit-name }}
|
||||
reporter: java-junit
|
||||
list-suites: failed
|
||||
list-tests: failed
|
||||
fail-on-error: false
|
||||
7
.github/codeql/codeql-config.yml
vendored
7
.github/codeql/codeql-config.yml
vendored
@@ -1,7 +0,0 @@
|
||||
name: "Metabase CodeQL config"
|
||||
|
||||
paths-ignore:
|
||||
- "**/node_modules"
|
||||
- "frontend/test/**"
|
||||
- "frontend/**/*.unit.*"
|
||||
- "e2e/**"
|
||||
103
.github/file-paths.yaml
vendored
103
.github/file-paths.yaml
vendored
@@ -1,103 +0,0 @@
|
||||
default: &default
|
||||
- "locales/**"
|
||||
- "bin/**"
|
||||
|
||||
ci: &ci
|
||||
- ".github/**/!(*.md)"
|
||||
|
||||
shared_sources: &shared_sources
|
||||
- "shared/src/**"
|
||||
|
||||
shared_specs: &shared_specs
|
||||
- "shared/test/**"
|
||||
|
||||
frontend_sources: &frontend_sources
|
||||
- *shared_sources
|
||||
- "enterprise/frontend/**"
|
||||
- "frontend/!(test)/**"
|
||||
- "yarn.lock"
|
||||
- "**/tsconfig*.json"
|
||||
- "package.json"
|
||||
- "babel.config.json"
|
||||
- "postcss.config.js"
|
||||
- "webpack.config.js"
|
||||
- "webpack.static-viz.config.js"
|
||||
|
||||
frontend_specs: &frontend_specs
|
||||
- *shared_specs
|
||||
- "frontend/test/**"
|
||||
- "frontend/**/*.unit.*"
|
||||
- "jest.unit.conf.json"
|
||||
- "jest.tz.unit.conf.json"
|
||||
|
||||
frontend_all: &frontend_all
|
||||
- *ci
|
||||
- *frontend_sources
|
||||
- *frontend_specs
|
||||
|
||||
backend_presto_kerberos:
|
||||
- "**/presto_jdbc/**"
|
||||
- "**/presto_jdbc.clj"
|
||||
|
||||
backend_sources: &backend_sources
|
||||
- *shared_sources
|
||||
- "**deps.edn"
|
||||
- "enterprise/backend/src/**"
|
||||
- "src/**"
|
||||
- "modules/drivers/{*,*/{*,!(test)/**}}"
|
||||
- "resources/**"
|
||||
- ".clj-kondo/**"
|
||||
|
||||
backend_specs: &backend_specs
|
||||
- *shared_specs
|
||||
- "test/**"
|
||||
- "enterprise/backend/test/**"
|
||||
- "test_modules/**"
|
||||
- "modules/drivers/*/test/**"
|
||||
- "test_config/**"
|
||||
- "dev/**"
|
||||
|
||||
backend_all: &backend_all
|
||||
- *default
|
||||
- *ci
|
||||
- *backend_sources
|
||||
- *backend_specs
|
||||
- *frontend_sources # keep it here until we detect static viz changes
|
||||
|
||||
sources: &sources
|
||||
- *shared_sources
|
||||
- *frontend_sources
|
||||
- *backend_sources
|
||||
|
||||
e2e_specs: &e2e_specs
|
||||
- "**/*.cy.*.js"
|
||||
- "e2e/runner/**"
|
||||
- "e2e/support/**"
|
||||
- "e2e/snapshot*/**"
|
||||
|
||||
e2e_all:
|
||||
- *default
|
||||
- *ci
|
||||
- *e2e_specs
|
||||
- *sources
|
||||
|
||||
snowplow:
|
||||
- *ci
|
||||
- "snowplow/**"
|
||||
|
||||
documentation:
|
||||
- "docs/**"
|
||||
- "**/*.md"
|
||||
|
||||
yaml:
|
||||
- "**/*.yml"
|
||||
- "**/*.yaml"
|
||||
|
||||
codeql:
|
||||
- "frontend/src/**"
|
||||
- "enterprise/frontend/src/**"
|
||||
|
||||
i18n:
|
||||
- *default
|
||||
- *ci
|
||||
- *sources
|
||||
@@ -3,16 +3,15 @@
|
||||
set -eo pipefail
|
||||
|
||||
# Need Java commands on $PATH, which apparently is not yet the case
|
||||
export JAVA_HOME="/usr/lib/jvm/msopenjdk-current"
|
||||
export PATH="$PATH:$JAVA_HOME/bin"
|
||||
|
||||
# ensure java commmand is available
|
||||
which java
|
||||
|
||||
# install clojure version needed for Metabase
|
||||
curl -O https://download.clojure.org/install/linux-install-1.11.0.1100.sh
|
||||
chmod +x linux-install-1.11.0.1100.sh
|
||||
./linux-install-1.11.0.1100.sh
|
||||
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh
|
||||
chmod +x linux-install-1.10.3.933.sh
|
||||
./linux-install-1.10.3.933.sh
|
||||
|
||||
RESOURCES_DIR=/app/source/resources
|
||||
|
||||
@@ -46,20 +45,20 @@ openssl x509 -outform der -in $RESOURCES_DIR/presto-ssl-root-ca.pem -out $RESOU
|
||||
keytool -noprompt -import -alias presto-kerberos -keystore $RESOURCES_DIR/cacerts-with-presto-ca.jks \
|
||||
-storepass changeit -file $RESOURCES_DIR/presto-ssl-root-ca.der -trustcacerts
|
||||
|
||||
ADDITIONAL_OPTS="SSLKeyStorePath=$RESOURCES_DIR/ssl_keystore.jks&SSLKeyStorePassword=presto\
|
||||
&SSLTrustStorePath=$RESOURCES_DIR/cacerts-with-presto-ca.jks&SSLTrustStorePassword=changeit"
|
||||
|
||||
# Set up the environment variables pointing to all of this, and run some tests
|
||||
DRIVERS=presto-jdbc \
|
||||
MB_ENABLE_PRESTO_JDBC_DRIVER=true \
|
||||
MB_PRESTO_JDBC_TEST_HOST=presto-kerberos \
|
||||
MB_PRESTO_JDBC_TEST_PORT=7778 \
|
||||
MB_PRESTO_JDBC_TEST_SSL=true \
|
||||
MB_PRESTO_JDBC_TEST_SSL_KEYSTORE_PATH=$RESOURCES_DIR/ssl_keystore.jks \
|
||||
MB_PRESTO_JDBC_TEST_SSL_KEYSTORE_PASSWORD=presto \
|
||||
MB_PRESTO_JDBC_TEST_SSL_TRUSTSTORE_PATH=$RESOURCES_DIR/cacerts-with-presto-ca.jks \
|
||||
MB_PRESTO_JDBC_TEST_SSL_TRUSTSTORE_PASSWORD=changeit \
|
||||
MB_PRESTO_JDBC_TEST_KERBEROS=true \
|
||||
MB_PRESTO_JDBC_TEST_USER=bob@EXAMPLE.COM \
|
||||
MB_PRESTO_JDBC_TEST_KERBEROS_PRINCIPAL=bob@EXAMPLE.COM \
|
||||
MB_PRESTO_JDBC_TEST_KERBEROS_REMOTE_SERVICE_NAME=HTTP \
|
||||
MB_PRESTO_JDBC_TEST_KERBEROS_KEYTAB_PATH=$RESOURCES_DIR/client.keytab \
|
||||
MB_PRESTO_JDBC_TEST_KERBEROS_CONFIG_PATH=$RESOURCES_DIR/krb5.conf \
|
||||
MB_PRESTO_JDBC_TEST_ADDITIONAL_OPTIONS=$ADDITIONAL_OPTS \
|
||||
clojure -X:dev:test:drivers:drivers-dev :only metabase.driver.presto-jdbc-test
|
||||
|
||||
22
.github/stale.yml
vendored
Normal file
22
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# For now we want to only check for stale pull requests
|
||||
only: pulls
|
||||
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Override the default Label of "wontfix"
|
||||
staleLabel: ""
|
||||
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue was automatically marked as stale due to a lack of recent activity.
|
||||
|
||||
This isn't a criticism of the PR, just an attempt to keep the PR queue in a happier state.
|
||||
If you'd like to bring this PR back to the attention of the folks on the Metabase team, just comment
|
||||
to prevent it from being closed.
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
46
.github/workflows/auto-backport.yml
vendored
46
.github/workflows/auto-backport.yml
vendored
@@ -5,17 +5,13 @@ on:
|
||||
|
||||
jobs:
|
||||
create-backport:
|
||||
if: github.event.pull_request.merged == true && (contains(github.event.pull_request.labels.*.name, 'backport') && github.event.action == 'closed' || github.event.label.name == 'backport')
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event.pull_request.merged == true && (contains(github.event.pull_request.labels.*.name, 'backport') || github.event.label.name == 'backport')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: tibdex/github-app-token@v1.6.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: ./.github/actions/find-squashed-commit
|
||||
name: Find commit
|
||||
id: find_commit
|
||||
@@ -28,10 +24,9 @@ jobs:
|
||||
id: get_latest_release_branch
|
||||
|
||||
- id: create_backport_pull_request
|
||||
name: Create backport pull request
|
||||
run: |
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
git config --global user.email "metabase-github-automation@metabase.com"
|
||||
git config --global user.name "$GITHUB_ACTOR"
|
||||
|
||||
BACKPORT_BRANCH="backport-$COMMIT"
|
||||
|
||||
@@ -43,46 +38,25 @@ jobs:
|
||||
CONFLICTS=$(git ls-files -u | wc -l)
|
||||
if [ "$CONFLICTS" -gt 0 ]; then
|
||||
echo "Could not cherry pick because of a conflict"
|
||||
echo "has-conflicts=true" >> $GITHUB_OUTPUT
|
||||
echo "::set-output name=has-conflicts::true"
|
||||
git cherry-pick --abort
|
||||
git checkout master
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "has-conflicts=false" >> $GITHUB_OUTPUT
|
||||
|
||||
git checkout master
|
||||
git push -u origin ${BACKPORT_BRANCH}
|
||||
|
||||
BACKPORT_PR_URL=$(hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "was-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
|
||||
hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "auto-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
|
||||
|
||||
#${ORIGINAL_PULL_REQUEST_NUMBER}")
|
||||
|
||||
BACKPORT_PR_NUMBER=${BACKPORT_PR_URL##*/}
|
||||
|
||||
echo "backport_pr_number=$BACKPORT_PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
#${ORIGINAL_PULL_REQUEST_NUMBER}"
|
||||
env:
|
||||
TARGET_BRANCH: ${{ steps.get_latest_release_branch.outputs.branch-name }}
|
||||
ORIGINAL_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
|
||||
ORIGINAL_TITLE: ${{ github.event.pull_request.title }}
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT: ${{ steps.find_commit.outputs.commit }}
|
||||
|
||||
- name: Auto approve backport PR
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'false' }}
|
||||
uses: juliangruber/approve-pull-request-action@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
|
||||
- name: Enable Pull Request Automerge
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'false' }}
|
||||
uses: peter-evans/enable-pull-request-automerge@v2
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
pull-request-number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
merge-method: squash
|
||||
|
||||
- uses: ./.github/actions/notify-pull-request
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'true' }}
|
||||
with:
|
||||
|
||||
217
.github/workflows/backend.yml
vendored
217
.github/workflows/backend.yml
vendored
@@ -6,102 +6,19 @@ on:
|
||||
- 'master'
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
backend_all: ${{ steps.changes.outputs.backend_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
be-linter-cloverage:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: 'cloverage'
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
- name: Collect the test coverage
|
||||
run: clojure -X:dev:ee:ee-dev:test:cloverage
|
||||
- name: Upload coverage to codecov.io
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./target/coverage/codecov.json
|
||||
flags: back-end
|
||||
|
||||
be-linter-clj-kondo:
|
||||
needs: files-changed
|
||||
if: needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run clj-kondo
|
||||
run: >-
|
||||
docker run
|
||||
--volume $PWD:/work
|
||||
--rm
|
||||
cljkondo/clj-kondo:2023.02.17
|
||||
clj-kondo
|
||||
--config /work/.clj-kondo/config.edn
|
||||
--config-dir /work/.clj-kondo
|
||||
--parallel
|
||||
--lint
|
||||
/work/src
|
||||
/work/test
|
||||
/work/enterprise/backend/src
|
||||
/work/enterprise/backend/test
|
||||
/work/shared/src
|
||||
/work/shared/test
|
||||
/work/modules/drivers/sparksql/src
|
||||
/work/modules/drivers/sparksql/test
|
||||
/work/modules/drivers/vertica/src
|
||||
/work/modules/drivers/vertica/test
|
||||
/work/modules/drivers/mongo/src
|
||||
/work/modules/drivers/mongo/test
|
||||
/work/modules/drivers/oracle/src
|
||||
/work/modules/drivers/oracle/test
|
||||
/work/modules/drivers/sqlite/src
|
||||
/work/modules/drivers/sqlite/test
|
||||
/work/modules/drivers/bigquery-cloud-sdk/src
|
||||
/work/modules/drivers/bigquery-cloud-sdk/test
|
||||
/work/modules/drivers/redshift/src
|
||||
/work/modules/drivers/redshift/test
|
||||
/work/modules/drivers/snowflake/src
|
||||
/work/modules/drivers/snowflake/test
|
||||
/work/modules/drivers/googleanalytics/src
|
||||
/work/modules/drivers/googleanalytics/test
|
||||
/work/modules/drivers/druid/src
|
||||
/work/modules/drivers/druid/test
|
||||
/work/modules/drivers/sqlserver/src
|
||||
/work/modules/drivers/sqlserver/test
|
||||
/work/modules/drivers/presto-jdbc/src
|
||||
/work/modules/drivers/presto-jdbc/test
|
||||
run: docker run -v $PWD:/work --rm cljkondo/clj-kondo clj-kondo --config /work/lint-config.edn --lint /work/src /work/enterprise/backend/src /work/backend/mbql/src /work/shared/src
|
||||
|
||||
be-linter-eastwood:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -112,130 +29,14 @@ jobs:
|
||||
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood
|
||||
name: Run Eastwood linter
|
||||
|
||||
# Because it's not possible to conditionally run only `java-11-ee` test in the draft mode,
|
||||
# we have to extract that job manually here. Backend developers have requested that this
|
||||
# test runs at all times to give them an early warning sign is something is broken.
|
||||
be-tests-java-11-ee-pre-check:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == true && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-tests-java-11-ee-pre-check
|
||||
timeout-minutes: 35
|
||||
be-linter-namespace-decls:
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: java-11-ee-pre-check
|
||||
|
||||
- run: yarn install --frozen-lockfile --prefer-offline
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
|
||||
- name: Run tests
|
||||
run: clojure -X:dev:ci:test:ee:ee-dev
|
||||
|
||||
- name: Publish Test Report (JUnit)
|
||||
uses: dorny/test-reporter@v1
|
||||
if: failure()
|
||||
with:
|
||||
path: 'target/junit/**/*_test.xml'
|
||||
name: JUnit Test Report be-tests-java-11-ee-pre-check
|
||||
reporter: java-junit
|
||||
list-suites: failed
|
||||
list-tests: failed
|
||||
fail-on-error: false
|
||||
|
||||
be-tests:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-tests-java-${{ matrix.java-version }}-${{ matrix.edition }}
|
||||
timeout-minutes: 35
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
java-version: [11, 17]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: be-tests
|
||||
|
||||
- run: yarn install --frozen-lockfile --prefer-offline
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
|
||||
- name: Run tests
|
||||
run: clojure -X:dev:ci:test:${{ matrix.edition }}:${{ matrix.edition }}-dev
|
||||
|
||||
- name: Publish Test Report (JUnit)
|
||||
uses: dorny/test-reporter@v1
|
||||
if: failure()
|
||||
with:
|
||||
path: 'target/junit/**/*_test.xml'
|
||||
name: JUnit Test Report be-tests-java-${{ matrix.java-version }}-${{ matrix.edition }}
|
||||
reporter: java-junit
|
||||
list-suites: failed
|
||||
list-tests: failed
|
||||
fail-on-error: false
|
||||
|
||||
be-tests-stub:
|
||||
needs: files-changed
|
||||
if: |
|
||||
always() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
needs.files-changed.outputs.backend_all == 'false'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-tests-java-${{ matrix.java-version }}-${{ matrix.edition }}
|
||||
timeout-minutes: 5
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
java-version: [11, 17]
|
||||
steps:
|
||||
- run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
|
||||
# checks that all the namespaces we actually ship can be compiled, without any dependencies that we don't ship (such
|
||||
# as `:dev` dependencies). See #27009 for more context.
|
||||
be-check:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-check-java-${{ matrix.java-version }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [11, 17, 19]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare backend
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: be-check
|
||||
- name: Check namespaces
|
||||
run: clojure -M:ee:drivers:check
|
||||
|
||||
be-check-stub:
|
||||
needs: files-changed
|
||||
if: |
|
||||
always() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
needs.files-changed.outputs.backend_all == 'false'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-check-java-${{ matrix.java-version }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [11, 17, 19]
|
||||
steps:
|
||||
- run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
m2-cache-key: 'namespace-decls'
|
||||
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:namespace-checker
|
||||
name: Check ns forms
|
||||
|
||||
54
.github/workflows/backport.yml
vendored
54
.github/workflows/backport.yml
vendored
@@ -9,26 +9,21 @@ jobs:
|
||||
create_pull_request:
|
||||
name: Creates a pull request
|
||||
if: contains(github.event.comment.body, '@metabase-bot backport')
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: tibdex/github-app-token@v1.6.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
- id: is_organization_member
|
||||
uses: JamesSingleton/is-organization-member@1.0.0
|
||||
with:
|
||||
organization: metabase
|
||||
username: ${{ github.event.issue.user.login }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: |
|
||||
result=${{ steps.is_organization_member.outputs.result }}
|
||||
if [ $result == false ]; then
|
||||
echo User ${{ github.event.comment.user.login }} is not a member of Metabase organization
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/github-script@v6
|
||||
- uses: actions/github-script@v4
|
||||
id: branch_info
|
||||
with:
|
||||
script: |
|
||||
@@ -36,19 +31,19 @@ jobs:
|
||||
const [_botName, _command, targetBranch] = context.payload.comment.body.split(" ");
|
||||
console.log(`Target branch is ${targetBranch}`);
|
||||
|
||||
const { data: originalPullRequest } = await github.rest.pulls.get({
|
||||
const { data: originalPullRequest } = await github.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.issue.number,
|
||||
});
|
||||
|
||||
const { data: commits } = await github.rest.pulls.listCommits({
|
||||
const { data: commits } = await github.pulls.listCommits({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.issue.number,
|
||||
});
|
||||
|
||||
const targetRef = await github.rest.git.getRef({
|
||||
const targetRef = await github.git.getRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `heads/${targetBranch}`,
|
||||
@@ -57,14 +52,14 @@ jobs:
|
||||
const backportBranch = `backport-${originalPullRequest.head.ref}`
|
||||
|
||||
try {
|
||||
await github.rest.git.getRef({
|
||||
await github.git.getRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `heads/${backportBranch}`,
|
||||
});
|
||||
} catch(e) {
|
||||
if (e.status === 404) {
|
||||
await github.rest.git.createRef({
|
||||
await github.git.createRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `refs/heads/${backportBranch}`,
|
||||
@@ -84,11 +79,9 @@ jobs:
|
||||
name: Cherry-pick commits and create PR
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: create_backport_pull_request
|
||||
name: Create backport pull request
|
||||
run: |
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
- run: |
|
||||
git config --global user.email "metabase-github-automation@metabase.com"
|
||||
git config --global user.name "$GITHUB_ACTOR"
|
||||
|
||||
git fetch --all
|
||||
|
||||
@@ -111,13 +104,9 @@ jobs:
|
||||
if [[ $(hub pr list -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -s "open") ]]; then
|
||||
echo "PR already exists"
|
||||
else
|
||||
BACKPORT_PR_URL=$(hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "was-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
|
||||
hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "auto-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
|
||||
|
||||
#${ORIGINAL_PULL_REQUEST_NUMBER}")
|
||||
|
||||
BACKPORT_PR_NUMBER=${BACKPORT_PR_URL##*/}
|
||||
|
||||
echo "backport_pr_number=$BACKPORT_PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
#${ORIGINAL_PULL_REQUEST_NUMBER}"
|
||||
echo "New PR has been created"
|
||||
fi
|
||||
env:
|
||||
@@ -131,26 +120,15 @@ jobs:
|
||||
BACKPORT_BRANCH: ${{ fromJson(steps.branch_info.outputs.result).backportBranch }}
|
||||
START_SHA: ${{ fromJson(steps.branch_info.outputs.result).startSha }}
|
||||
END_SHA: ${{ fromJson(steps.branch_info.outputs.result).endSha }}
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Auto approve backport PR
|
||||
uses: juliangruber/approve-pull-request-action@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
- name: Enable Pull Request Automerge
|
||||
uses: peter-evans/enable-pull-request-automerge@v2
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
pull-request-number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
merge-method: squash
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
notify_when_failed:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
name: Notify about failure
|
||||
needs: create_pull_request
|
||||
if: ${{ failure() }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/notify-pull-request
|
||||
with:
|
||||
include-log: true
|
||||
|
||||
24
.github/workflows/build-scripts.yml
vendored
24
.github/workflows/build-scripts.yml
vendored
@@ -10,17 +10,33 @@ on:
|
||||
jobs:
|
||||
|
||||
test-build-scripts:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare back-end environment
|
||||
timeout-minutes: 5
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: 'build-scripts'
|
||||
|
||||
- name: Run build and release script tests
|
||||
run: clojure -X:dev:drivers:build:build-dev:build-test:ci
|
||||
- name: Run metabuild-common build script tests
|
||||
run: clojure -M:test
|
||||
working-directory: bin/common
|
||||
timeout-minutes: 15
|
||||
- name: Run build-drivers build script tests
|
||||
run: clojure -M:test
|
||||
working-directory: bin/build-drivers
|
||||
timeout-minutes: 15
|
||||
- name: Run i18n script tests
|
||||
run: clojure -M:test
|
||||
working-directory: bin/i18n
|
||||
timeout-minutes: 15
|
||||
- name: Run build-mb build script tests
|
||||
run: clojure -M:test
|
||||
working-directory: bin/build-mb
|
||||
timeout-minutes: 15
|
||||
- name: Run release script tests
|
||||
run: clojure -M:test
|
||||
working-directory: bin/release
|
||||
timeout-minutes: 15
|
||||
- name: Run Liquibase migrations linter tests
|
||||
run: clojure -M:test
|
||||
|
||||
33
.github/workflows/clean-cache.yml
vendored
33
.github/workflows/clean-cache.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Cleanup caches by a branch
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
10
.github/workflows/cljs.yml
vendored
10
.github/workflows/cljs.yml
vendored
@@ -7,22 +7,14 @@ on:
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
||||
shared-tests-cljs:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: 'cljs'
|
||||
- name: Run Cljs tests for shared/ code
|
||||
run: yarn run test-cljs
|
||||
|
||||
9
.github/workflows/codenotify.yml
vendored
9
.github/workflows/codenotify.yml
vendored
@@ -3,20 +3,15 @@ name: Codenotify
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
# We're currently notifying developers only for frontend source changes.
|
||||
# Update this glob if that ever changes and we start including backend source code changes.
|
||||
paths:
|
||||
- 'frontend/src/metabase/**'
|
||||
- 'enterprise/frontend/src/metabase-enterprise/**'
|
||||
|
||||
jobs:
|
||||
codenotify:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
name: Codenotify
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: sourcegraph/codenotify@v0.6.4
|
||||
- uses: sourcegraph/codenotify@v0.4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
29
.github/workflows/codeql.yml
vendored
29
.github/workflows/codeql.yml
vendored
@@ -1,37 +1,16 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
codeql: ${{ steps.changes.outputs.codeql }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
analyze:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: javascript
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
18
.github/workflows/doc-md-links.yml
vendored
18
.github/workflows/doc-md-links.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Lint doc Markdown links
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- docs/**
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
jobs:
|
||||
markdown-link-check:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Lint doc links
|
||||
run: yarn run docs-lint-links
|
||||
20
.github/workflows/docs.yml
vendored
Normal file
20
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
fe-linter-docs-links:
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- run: yarn run lint-docs-links
|
||||
name: Run docs links checker
|
||||
695
.github/workflows/drivers.yml
vendored
695
.github/workflows/drivers.yml
vendored
@@ -1,695 +0,0 @@
|
||||
name: Driver Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
backend_all: ${{ steps.changes.outputs.backend_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
be-tests-athena-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: athena
|
||||
MB_ATHENA_TEST_REGION: us-east-1
|
||||
MB_ATHENA_TEST_ACCESS_KEY: ${{ secrets.MB_ATHENA_TEST_ACCESS_KEY }}
|
||||
MB_ATHENA_TEST_SECRET_KEY: ${{ secrets.MB_ATHENA_TEST_SECRET_KEY }}
|
||||
MB_ATHENA_TEST_S3_STAGING_DIR: ${{ secrets.MB_ATHENA_TEST_S3_STAGING_DIR }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Athena driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-athena-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-bigquery-cloud-sdk-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: bigquery-cloud-sdk
|
||||
MB_BIGQUERY_TEST_PROJECT_ID: ${{ secrets.BIGQUERY_TEST_PROJECT_ID }}
|
||||
MB_BIGQUERY_TEST_CLIENT_ID: ${{ secrets.MB_BIGQUERY_TEST_CLIENT_ID }}
|
||||
MB_BIGQUERY_TEST_CLIENT_SECRET: ${{ secrets.MB_BIGQUERY_TEST_CLIENT_SECRET }}
|
||||
MB_BIGQUERY_TEST_ACCESS_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_ACCESS_TOKEN }}
|
||||
MB_BIGQUERY_TEST_REFRESH_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_REFRESH_TOKEN }}
|
||||
MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON: ${{ secrets.MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test BigQuery Cloud SDK driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-bigquery-cloud-sdk-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-druid-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: druid
|
||||
services:
|
||||
druid:
|
||||
image: metabase/druid:0.20.2
|
||||
ports:
|
||||
- "8082:8082"
|
||||
env:
|
||||
CLUSTER_SIZE: nano-quickstart
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Druid driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-druid-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-googleanalytics-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: googleanalytics
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Google Analytics driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-googleanalytics-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-google-related-drivers-classpath-test:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: 'googleanalytics,bigquery-cloud-sdk'
|
||||
MB_BIGQUERY_TEST_PROJECT_ID: ${{ secrets.BIGQUERY_TEST_PROJECT_ID }}
|
||||
MB_BIGQUERY_TEST_CLIENT_ID: ${{ secrets.MB_BIGQUERY_TEST_CLIENT_ID }}
|
||||
MB_BIGQUERY_TEST_CLIENT_SECRET: ${{ secrets.MB_BIGQUERY_TEST_CLIENT_SECRET }}
|
||||
MB_BIGQUERY_TEST_ACCESS_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_ACCESS_TOKEN }}
|
||||
MB_BIGQUERY_TEST_REFRESH_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_REFRESH_TOKEN }}
|
||||
MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON: ${{ secrets.MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Google Related Drivers Classpath
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-google-related-drivers-classpath-test'
|
||||
test-args: ':only "[metabase.query-processor-test.expressions-test metabase.driver.google-test metabase.driver.googleanalytics-test]"'
|
||||
|
||||
be-tests-mariadb-10-2-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
services:
|
||||
mariadb:
|
||||
image: circleci/mariadb:10.2.23
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MariaDB driver (10.2)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mariadb-10-2-ee'
|
||||
|
||||
be-tests-mariadb-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
services:
|
||||
mariadb:
|
||||
image: circleci/mariadb:latest
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MariaDB driver (latest)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mariadb-latest-ee'
|
||||
|
||||
be-tests-mongo-4-2-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mongo
|
||||
MB_MONGO_TEST_USER: metabase
|
||||
MB_MONGO_TEST_PASSWORD: metasample123
|
||||
services:
|
||||
mongodb:
|
||||
image: metabase/qa-databases:mongo-sample-4.2
|
||||
ports:
|
||||
- "27017:27017"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MongoDB driver (4.2)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-4-2-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-mongo-4-2-ssl-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mongo
|
||||
MB_MONGO_TEST_USER: metabase
|
||||
MB_MONGO_TEST_PASSWORD: metasample123
|
||||
MB_TEST_MONGO_REQUIRES_SSL: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Spin up Mongo docker container
|
||||
run: docker run -d -p 27017:27017 --name metamongo metabase/qa-databases:mongo-sample-4.2 mongod --dbpath /data/db2/ --tlsMode requireTLS --tlsCertificateKeyFile /etc/mongo/metamongo.pem --tlsCAFile /etc/mongo/metaca.crt
|
||||
- name: Wait until the port 27017 is ready
|
||||
run: while ! nc -z localhost 27017; do sleep 1; done
|
||||
timeout-minutes: 5
|
||||
- name: Make SSL certificates for Mongo available
|
||||
run: |
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metabase.crt \
|
||||
-o ./test_resources/ssl/mongo/metabase.crt
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metabase.key \
|
||||
-o ./test_resources/ssl/mongo/metabase.key
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metaca.crt \
|
||||
-o ./test_resources/ssl/mongo/metaca.crt
|
||||
|
||||
- name: Test MongoDB SSL driver (4.2)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-4-2-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-mongo-5-0-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mongo
|
||||
MB_MONGO_TEST_USER: metabase
|
||||
MB_MONGO_TEST_PASSWORD: metasample123
|
||||
services:
|
||||
mongodb:
|
||||
image: metabase/qa-databases:mongo-sample-5.0
|
||||
ports:
|
||||
- "27017:27017"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MongoDB driver (5.0)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-5-0-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-mongo-5-0-ssl-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mongo
|
||||
MB_MONGO_TEST_USER: metabase
|
||||
MB_MONGO_TEST_PASSWORD: metasample123
|
||||
MB_TEST_MONGO_REQUIRES_SSL: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Spin up Mongo docker container
|
||||
run: docker run -d -p 27017:27017 --name metamongo metabase/qa-databases:mongo-sample-5.0 mongod --dbpath /data/db2/ --tlsMode requireTLS --tlsCertificateKeyFile /etc/mongo/metamongo.pem --tlsCAFile /etc/mongo/metaca.crt
|
||||
- name: Wait until the port 27017 is ready
|
||||
run: while ! nc -z localhost 27017; do sleep 1; done
|
||||
timeout-minutes: 5
|
||||
- name: Make SSL certificates for Mongo available
|
||||
run: |
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metabase.crt \
|
||||
-o ./test_resources/ssl/mongo/metabase.crt
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metabase.key \
|
||||
-o ./test_resources/ssl/mongo/metabase.key
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metaca.crt \
|
||||
-o ./test_resources/ssl/mongo/metaca.crt
|
||||
|
||||
- name: Test MongoDB SSL driver (5.0)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-5-0-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-mongo-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mongo
|
||||
MB_MONGO_TEST_USER: metabase
|
||||
MB_MONGO_TEST_PASSWORD: metasample123
|
||||
services:
|
||||
mongodb:
|
||||
image: circleci/mongo:latest
|
||||
ports:
|
||||
- "27017:27017"
|
||||
env:
|
||||
MONGO_INITDB_ROOT_USERNAME: metabase
|
||||
MONGO_INITDB_ROOT_PASSWORD: metasample123
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MongoDB driver (latest)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-latest-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-mysql-5-7-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
services:
|
||||
mysql:
|
||||
image: circleci/mysql:5.7.23
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MySQL driver (5.7)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mysql-5-7-ee'
|
||||
|
||||
be-tests-mysql-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
# set up env vars for something named "MYSQL_SSL" to run MySQL SSL tests verifying connectivity with PEM cert
|
||||
# they are deliberately given a different name to prevent them from affecting the regular test run against
|
||||
# the configured MySQL instance, but there is one particular test (mysql-connect-with-ssl-and-pem-cert-test)
|
||||
# that overrides the MB_MYSQL_TEST_* values with them
|
||||
# the MYSQL_RDS_SSL_INSTANCE vars are defined as secrets and can be altered
|
||||
MB_MYSQL_SSL_TEST_HOST: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_HOST }}
|
||||
MB_MYSQL_SSL_TEST_SSL: true
|
||||
MB_MYSQL_SSL_TEST_ADDITIONAL_OPTIONS: 'verifyServerCertificate=true'
|
||||
# the contents of the ./resources/certificates/rds-combined-ca-bundle.pem file
|
||||
MB_MYSQL_SSL_TEST_SSL_CERT: ${{ secrets.MB_MYSQL_SSL_TEST_SSL_CERT }}
|
||||
MB_MYSQL_SSL_TEST_USER: metabase
|
||||
MB_MYSQL_SSL_TEST_PASSWORD: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_PASSWORD }}
|
||||
services:
|
||||
mysql:
|
||||
image: circleci/mysql:latest
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MySQL driver (latest)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mysql-latest-ee'
|
||||
|
||||
be-tests-oracle-18-4-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: oracle
|
||||
MB_ORACLE_TEST_HOST: localhost
|
||||
MB_ORACLE_TEST_USER: system
|
||||
MB_ORACLE_TEST_PASSWORD: password
|
||||
MB_ORACLE_TEST_SERVICE_NAME: XEPDB1
|
||||
services:
|
||||
oracle:
|
||||
image: gvenzl/oracle-xe:18.4.0-slim
|
||||
env:
|
||||
ORACLE_PASSWORD: password
|
||||
ports:
|
||||
- "1521:1521"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Oracle driver (18.4)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-oracle-18-4-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-oracle-21-3-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: oracle
|
||||
MB_ORACLE_TEST_HOST: localhost
|
||||
MB_ORACLE_TEST_PORT: 2484
|
||||
MB_ORACLE_TEST_SERVICE_NAME: XEPDB1
|
||||
MB_ORACLE_TEST_SSL: true
|
||||
MB_ORACLE_TEST_SSL_USE_TRUSTSTORE: true
|
||||
MB_ORACLE_TEST_SSL_TRUSTSTORE_PATH: './test_resources/ssl/oracle/truststore.p12'
|
||||
MB_ORACLE_TEST_SSL_TRUSTSTORE_OPTIONS: local
|
||||
MB_ORACLE_TEST_SSL_TRUSTSTORE_PASSWORD_VALUE: 'PassworD_#1234'
|
||||
MB_ORACLE_TEST_SSL_USE_KEYSTORE: true
|
||||
MB_ORACLE_TEST_SSL_KEYSTORE_PATH: './test_resources/ssl/oracle/keystore.p12'
|
||||
MB_ORACLE_TEST_SSL_KEYSTORE_OPTIONS: local
|
||||
MB_ORACLE_TEST_SSL_KEYSTORE_PASSWORD_VALUE: 'PassworD_#1234'
|
||||
MB_ORACLE_SSL_TEST_SSL: true
|
||||
services:
|
||||
oracle:
|
||||
image: metabase/qa-databases:oracle-xe-21.3
|
||||
env:
|
||||
ORACLE_PASSWORD: password
|
||||
ports:
|
||||
- "2484:2484"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Oracle driver (21.3)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-oracle-21-3-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-postgres-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
MB_DB_TYPE: postgres
|
||||
MB_DB_PORT: 5432
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: circle_test
|
||||
MB_POSTGRESQL_TEST_USER: circle_test
|
||||
services:
|
||||
postgres:
|
||||
image: circleci/postgres:9.6-alpine
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_USER: circle_test
|
||||
POSTGRES_DB: circle_test
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Postgres driver (9.6)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-postgres-ee'
|
||||
|
||||
be-tests-postgres-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
MB_DB_TYPE: postgres
|
||||
MB_DB_PORT: 5432
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: circle_test
|
||||
MB_POSTGRESQL_TEST_USER: circle_test
|
||||
MB_POSTGRES_SSL_TEST_SSL: true
|
||||
MB_POSTGRES_SSL_TEST_SSL_MODE: verify-full
|
||||
MB_POSTGRES_SSL_TEST_SSL_ROOT_CERT_PATH: 'test-resources/certificates/us-east-2-bundle.pem'
|
||||
services:
|
||||
postgres:
|
||||
image: circleci/postgres:latest
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_USER: circle_test
|
||||
POSTGRES_DB: circle_test
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Postgres driver (latest)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-postgres-latest-ee'
|
||||
|
||||
be-tests-presto-jdbc-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: presto-jdbc
|
||||
MB_PRESTO_JDBC_TEST_CATALOG: test_data
|
||||
MB_PRESTO_JDBC_TEST_HOST: localhost
|
||||
MB_PRESTO_JDBC_TEST_PORT: 8443
|
||||
MB_PRESTO_JDBC_TEST_SSL: true
|
||||
MB_PRESTO_JDBC_TEST_USER: metabase
|
||||
MB_PRESTO_JDBC_TEST_PASSWORD: metabase
|
||||
MB_ENABLE_PRESTO_JDBC_DRIVER: true
|
||||
MB_PRESTO_JDBC_TEST_ADDITIONAL_OPTIONS: 'SSLTrustStorePath=/tmp/cacerts-with-presto-ssl.jks&SSLTrustStorePassword=changeit'
|
||||
services:
|
||||
presto:
|
||||
image: metabase/presto-mb-ci:latest # version 0.254
|
||||
ports:
|
||||
- "8443:8443"
|
||||
env:
|
||||
JAVA_TOOL_OPTIONS: "-Xmx2g"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Wait for port ${{ env.MB_PRESTO_JDBC_TEST_PORT }} to be ready
|
||||
run: while ! nc -z localhost ${{ env.MB_PRESTO_JDBC_TEST_PORT }}; do sleep 0.1; done
|
||||
timeout-minutes: 15
|
||||
- name: Create temp cacerts file based on bundled JDK one
|
||||
run: cp $JAVA_HOME/lib/security/cacerts /tmp/cacerts-with-presto-ssl.jks
|
||||
- name: Capture Presto server self signed CA
|
||||
run: |
|
||||
while [[ ! -s /tmp/presto-ssl-ca.pem ]];
|
||||
do echo "Waiting to capture SSL CA" \
|
||||
&& openssl s_client -connect localhost:8443 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/presto-ssl-ca.pem \
|
||||
&& sleep 1; done
|
||||
- name: Convert Presto CA from PEM to DER
|
||||
run: openssl x509 -outform der -in /tmp/presto-ssl-ca.pem -out /tmp/presto-ssl-ca.der
|
||||
- name: Add write permission on cacerts file
|
||||
run: chmod u+w /tmp/cacerts-with-presto-ssl.jks
|
||||
- name: Import Presto CA into temp cacerts file
|
||||
run: |
|
||||
keytool -noprompt -import -alias presto -keystore /tmp/cacerts-with-presto-ssl.jks \
|
||||
-storepass changeit -file /tmp/presto-ssl-ca.der -trustcacerts
|
||||
- name: Test Presto JDBC driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-presto-jdbc-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-redshift-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: redshift
|
||||
MB_REDSHIFT_TEST_USER: metabase_ci
|
||||
MB_REDSHIFT_TEST_DB: testdb
|
||||
MB_REDSHIFT_TEST_HOST: ${{ secrets.MB_REDSHIFT_TEST_HOST }}
|
||||
MB_REDSHIFT_TEST_PASSWORD: ${{ secrets.MB_REDSHIFT_TEST_PASSWORD }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Redshift driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-redshift-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-snowflake-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: snowflake
|
||||
MB_SNOWFLAKE_TEST_USER: METABASE CI
|
||||
MB_SNOWFLAKE_TEST_ACCOUNT: ${{ secrets.MB_SNOWFLAKE_TEST_ACCOUNT }}
|
||||
MB_SNOWFLAKE_TEST_PASSWORD: ${{ secrets.MB_SNOWFLAKE_TEST_PASSWORD }}
|
||||
MB_SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.MB_SNOWFLAKE_TEST_WAREHOUSE }}
|
||||
MB_SNOWFLAKE_TEST_PK_USER: METABASE PK
|
||||
MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Snowflake driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-snowflake-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-sparksql-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: sparksql
|
||||
services:
|
||||
sparksql:
|
||||
image: metabase/spark:3.2.1
|
||||
ports:
|
||||
- "10000:10000"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test Spark driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sparksql-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-sqlite-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: sqlite
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test SQLite driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sqlite-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-sqlserver-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: sqlserver
|
||||
MB_SQLSERVER_TEST_HOST: localhost
|
||||
MB_SQLSERVER_TEST_PASSWORD: 'P@ssw0rd'
|
||||
MB_SQLSERVER_TEST_USER: SA
|
||||
services:
|
||||
sqlserver:
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
ports:
|
||||
- "1433:1433"
|
||||
env:
|
||||
ACCEPT_EULA: Y
|
||||
SA_PASSWORD: 'P@ssw0rd'
|
||||
MSSQL_MEMORY_LIMIT_MB: 1024
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test MS SQL Server driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sqlserver-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
|
||||
be-tests-vertica-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: vertica
|
||||
services:
|
||||
vertica:
|
||||
image: vertica/vertica-ce:12.0.2-0
|
||||
ports:
|
||||
- "5433:5433"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Make plugins directory
|
||||
run: mkdir plugins
|
||||
- name: Test Vertica driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-vertica-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user