Compare commits

..

2 Commits

Author SHA1 Message Date
Diogo Mendes
a403e51022 Lint 2022-04-04 12:29:08 -03:00
Diogo Mendes
3263ca1f66 Remove delay to not trigger autocomplete 2022-04-04 12:06:48 -03:00
7758 changed files with 452138 additions and 779509 deletions

31
.babelrc Normal file
View 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
}
]
]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
Update `clj-kondo` configs for libraries using
```sh
clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath -A:dev)"
```

View File

@@ -1 +0,0 @@
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}

View File

@@ -1 +0,0 @@
{:hooks {:macroexpand {sci.core/copy-ns sci.core/copy-ns}}}

View File

@@ -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)]))

View File

@@ -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}))

View File

@@ -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}}}

View File

@@ -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))}))

View File

@@ -1,4 +0,0 @@
{:hooks
{:analyze-call
{com.gfredericks.test.chuck.clojure-test/checking
clj-kondo.com.gfredericks.test.chuck.checking/checking}}}

View File

@@ -1,2 +0,0 @@
{:lint-as
{humane-are.core/are+ clojure.test/are}}

View File

@@ -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}}}

View File

@@ -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))

View File

@@ -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 <>)))))

View File

@@ -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*}))

View File

@@ -1,5 +0,0 @@
(ns macros.toucan.models)
(defmacro defmodel
[model _table-name]
`(def ~model "Docstring." ~(keyword (name model))))

View File

@@ -1,4 +0,0 @@
(ns macros.toucan2.common)
(defn ignore-unused [symb]
(vary-meta symb assoc :clj-kondo/ignore [:unused-binding]))

View File

@@ -1,6 +0,0 @@
(ns macros.toucan2.execute)
(defmacro with-call-count
[[call-count-fn-binding] & body]
`(let [~call-count-fn-binding (fn [])]
~@body))

View File

@@ -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)))

View File

@@ -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)))

View File

@@ -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)))

View File

@@ -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)))

View File

@@ -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))

View File

@@ -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)))

View File

@@ -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)))

View File

@@ -1,4 +0,0 @@
{:linters
{:unresolved-symbol
{:exclude
[(clojure.test/is [partial= re= schema= =?])]}}}

View File

@@ -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}}

View File

@@ -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})))

View File

@@ -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})))

View File

@@ -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}}}}

View File

@@ -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})

View File

@@ -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*}))

View File

@@ -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))])}))

View File

@@ -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*}))

View File

@@ -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*}))

View File

@@ -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}))

View File

@@ -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)))}))

View File

@@ -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*}))

View File

@@ -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))}))

View File

@@ -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*}))

View File

@@ -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))])}))

View File

@@ -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]))

View File

@@ -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))

View File

@@ -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))

View File

@@ -1,5 +1,5 @@
(ns macros.metabase.api.common)
(defmacro define-routes [& args]
`(do (def ~'routes "docstring" nil)
`(do (def ~'routes)
~@args))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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#)))))

View File

@@ -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)))))))

View File

@@ -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)))

View File

@@ -1,4 +0,0 @@
(ns macros.metabase.models.params.chain-filter-test)
(defmacro chain-filter [& _]
`(metabase.models.params.chain-filter/chain-filter nil nil))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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)))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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)]

View 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"))))

View File

@@ -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}}}

View File

@@ -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})))

View File

@@ -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})))

View File

@@ -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))

View File

@@ -1,2 +0,0 @@
{:lint-as {malli.experimental/defn schema.core/defn}
:linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}

View File

@@ -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}}}

View File

@@ -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))

View File

@@ -1 +0,0 @@
{:lint-as {schema.test/deftest clojure.test/deftest}}

View File

@@ -1,2 +0,0 @@
{metabase.api.collection/foo [[:inner 0]]
toucan.db/insert! [[:block 1]]}

View File

@@ -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

View File

@@ -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"
}

View File

@@ -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"))))

View File

@@ -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"
}
}
]

View File

@@ -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, …)

View File

@@ -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).

View File

@@ -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:

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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') }}

View File

@@ -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') }}

View File

@@ -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: |

View File

@@ -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

View File

@@ -1,7 +0,0 @@
name: "Metabase CodeQL config"
paths-ignore:
- "**/node_modules"
- "frontend/test/**"
- "frontend/**/*.unit.*"
- "e2e/**"

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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