Compare commits
46 Commits
python-lib
...
ss/embeddi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e4e20090d | ||
|
|
89bdd982d1 | ||
|
|
a24b6daabd | ||
|
|
fd7059b2de | ||
|
|
15eed35a49 | ||
|
|
e05b159dbb | ||
|
|
92a080aa61 | ||
|
|
61c413fd8e | ||
|
|
9496e659f4 | ||
|
|
1f81d2f35d | ||
|
|
b307dc5c8f | ||
|
|
4fbefd6dcf | ||
|
|
29bf9a91ad | ||
|
|
c61c604145 | ||
|
|
a6d39b60de | ||
|
|
a45843559d | ||
|
|
a856712245 | ||
|
|
084d8b9ace | ||
|
|
7c647de9b0 | ||
|
|
8f70a19dca | ||
|
|
e21d011708 | ||
|
|
be980c252f | ||
|
|
68790b70ce | ||
|
|
855b60a016 | ||
|
|
be1c82dcb8 | ||
|
|
848192ccfb | ||
|
|
778e210968 | ||
|
|
6ed6ffadb7 | ||
|
|
0820d6af6e | ||
|
|
98d3cb58fa | ||
|
|
a7b719807f | ||
|
|
5a21df8919 | ||
|
|
5ffb202684 | ||
|
|
beaf957d2b | ||
|
|
3896229518 | ||
|
|
47387d8302 | ||
|
|
e351fd7d82 | ||
|
|
27dac611ea | ||
|
|
0635595e7c | ||
|
|
3a62376cff | ||
|
|
d730468b24 | ||
|
|
205b88f6bb | ||
|
|
75dd41a0d6 | ||
|
|
894f808c0d | ||
|
|
11b6380431 | ||
|
|
d309f2a7f9 |
@@ -49,7 +49,7 @@
|
||||
;; disabled linters
|
||||
;;
|
||||
|
||||
:redundant-ignore {:level :off} ; lots of false positives, see https://github.com/clj-kondo/clj-kondo/issues/2414
|
||||
:redundant-ignore {:level :off} ; lots of false positives, see https://github.com/clj-kondo/clj-kondo/issues/2414
|
||||
:unexpected-recur {:level :off} ; TODO (cam): I think we just need to tell it how to handle MBQL match and we can enable this?
|
||||
|
||||
;;
|
||||
@@ -173,6 +173,7 @@
|
||||
metabase.driver.sql-jdbc.execute/execute-prepared-statement!
|
||||
metabase.notification.models/create-notification!
|
||||
metabase.pulse.send/send-pulse!
|
||||
metabase.query-processor.store/store-database!
|
||||
;; Safe in tests, where we typically use a private, temporary index per thread.
|
||||
metabase.search.core/reindex!
|
||||
metabase.util/run-count!
|
||||
@@ -214,7 +215,7 @@
|
||||
;; misc config for built-in linters
|
||||
;;
|
||||
|
||||
:invalid-arity {:skip-args [metabase.lib.util.match/match]} ; TODO (cam): can we fix these?
|
||||
:invalid-arity {:skip-args [metabase.lib.util.match/match]} ; TODO (cam): can we fix these?
|
||||
:refer-all {:level :warning, :exclude [clojure.test]}
|
||||
:unused-referred-var {:exclude {compojure.core [GET DELETE POST PUT]}}
|
||||
|
||||
@@ -249,15 +250,16 @@
|
||||
(taoensso.nippy/extend-freeze)
|
||||
(taoensso.nippy/extend-thaw)]}
|
||||
|
||||
;; TODO (Cam 8/22/25) -- what's the point of marking stuff deprecated if we don't have Kondo enforce it? We should
|
||||
;; remove all of these and add individual ignores as needed.
|
||||
:deprecated-var
|
||||
{:exclude
|
||||
{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.query-processor.util/normalize-token {:namespaces ["metabase.*"]}}}
|
||||
{metabase.cmd.core/dump {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
metabase.cmd.core/load {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
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.query-processor.middleware.resolve-joins/maybe-resolve-source-table {:namespaces ["metabase.*"]}
|
||||
metabase.query-processor.util/normalize-token {:namespaces ["metabase.*"]}}}
|
||||
|
||||
:discouraged-var
|
||||
{clojure.core/print {:message "Use metabase.util.log instead of clojure.core/print"}
|
||||
@@ -290,8 +292,6 @@
|
||||
me.flowthing.pp/pprint {:message "Use metabase.util.log instead of me.flowthing.pp/pprint"}
|
||||
medley.core/random-uuid {:message "Use clojure.core/random-uuid instead of medley.core/random-uuid"}
|
||||
metabase.driver/database-supports? {:message "Use metabase.driver.util/supports? instead of metabase.driver/database-supports?"}
|
||||
metabase.lib.convert/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
|
||||
metabase.lib.core/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
|
||||
metabase.lib.equality/find-column-indexes-for-refs {:message "Use lib.equality/closest-matches-in-metadata or lib.equality/find-closest-matches-for-refs instead of lib.equality/find-column-indexes-for-refs"}
|
||||
next.jdbc/active-tx? {:message "Use metabase.app-db.core/in-transaction? to see if we are in a transaction"}
|
||||
toucan2.core/debug {:message "Don't commit code using t2/debug"}
|
||||
@@ -300,7 +300,6 @@
|
||||
:discouraged-namespace
|
||||
{camel-snake-kebab.core {:message "CSK is not Turkish-safe, use the versions in metabase.util instead."}
|
||||
cheshire.core {:message "Use metabase.util.json instead of cheshire.core directly."}
|
||||
clj-time.core {:message "Use java-time.api or metabase.util.date-2 instead of clj-time"}
|
||||
clojure.tools.logging {:message "Use metabase.util.log instead of clojure.tools.logging directly"}
|
||||
grouper.core {:message "Use metabase.util.grouper instead of grouper.core"}
|
||||
honeysql.core {:message "Use Honey SQL 2. Honey SQL 1 is removed as a dependency in Metabase 49+."}
|
||||
@@ -409,16 +408,10 @@
|
||||
clojure.test.check.clojure-test/defspec clojure.test/deftest
|
||||
clojure.test.check.properties/for-all clojure.core/let
|
||||
clojurewerkz.quartzite.jobs/defjob clojure.core/defn
|
||||
com.climate.claypoole/with-shutdown! clojure.core/let
|
||||
instaparse.core/defparser clojure.core/def
|
||||
metabase-enterprise.action-v2.test-util/with-test-tables! clojure.core/let
|
||||
metabase-enterprise.content-translation.routes-test/with-new-secret-key! clojure.core/fn
|
||||
metabase-enterprise.serialization.test-util/with-dbs clojure.core/fn
|
||||
metabase-enterprise.serialization.test-util/with-random-dump-dir clojure.core/let
|
||||
metabase-enterprise.transforms.api-test/with-transform-tags clojure.core/let
|
||||
metabase-enterprise.transforms.api-test/with-worker-runs clojure.core/let
|
||||
metabase-enterprise.transforms.test-util/with-transform-cleanup! clojure.core/let
|
||||
metabase-enterprise.transforms.execute/with-transform-lifecycle clojure.core/let
|
||||
metabase-enterprise.content-translation.routes-test/with-new-secret-key! clojure.core/fn
|
||||
metabase.actions.test-util/with-actions clojure.core/let
|
||||
metabase.api.common/let-404 clojure.core/let
|
||||
metabase.app-db.custom-migrations.util/with-temp-scheduler! clojure.core/fn
|
||||
@@ -477,7 +470,6 @@
|
||||
metabase.test/with-temp-file clojure.core/let
|
||||
metabase.test/with-user-in-groups clojure.core/let
|
||||
metabase.upload.impl-test/with-upload-table! clojure.core/let
|
||||
metabase.util/for-map clojure.core/for
|
||||
metabase.util.files/with-open-path-to-resource clojure.core/let
|
||||
metabase.util.malli.defn/defn schema.core/defn
|
||||
metabase.util.malli.defn/defn- schema.core/defn
|
||||
@@ -518,7 +510,6 @@
|
||||
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.cache.config-test/with-temp-persist-models hooks.common/with-seven-bindings
|
||||
metabase-enterprise.semantic-search.db.connection/with-migrate-tx hooks.common/let-one-with-optional-value
|
||||
metabase-enterprise.serialization.test-util/with-temp-dpc hooks.toucan2.tools.with-temp/with-temp
|
||||
metabase.api.common.internal-test/with-jetty-server hooks.common/with-one-binding
|
||||
metabase.api.macros/defendpoint hooks.metabase.api.macros/defendpoint
|
||||
@@ -550,7 +541,6 @@
|
||||
metabase.lib.schema.mbql-clause/define-tuple-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
|
||||
metabase.lib.test-util.macros/$ids hooks.metabase.test.data/$ids
|
||||
metabase.lib.test-util.macros/mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.lib.test-util.macros/mbql-5-query hooks.metabase.test.data/mbql-query
|
||||
metabase.lib.test-util.macros/with-testing-against-standard-queries hooks.metabase.lib.test-util.macros/with-testing-against-standard-queries
|
||||
metabase.model-persistence.api-test/with-persistence-setup! hooks.common/with-one-top-level-binding
|
||||
metabase.model-persistence.api-test/with-setup! hooks.common/with-one-top-level-binding
|
||||
@@ -650,7 +640,6 @@
|
||||
|
||||
:macroexpand
|
||||
{clojurewerkz.quartzite.jobs/build macros.quartz/build-job
|
||||
clojurewerkz.quartzite.schedule.calendar-interval/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
|
||||
@@ -725,19 +714,12 @@
|
||||
{:pattern "metabase\\.driver.*$"
|
||||
:name driver-namespaces}
|
||||
;;
|
||||
;; Perf-sensitive namespaces are currently the union of metabase.lib.*, driver namespaces, and QP (without tests).
|
||||
;;
|
||||
{:pattern "^(?!.*-test(?:\\..*)?$)(?!.*test-util)(?!^metabase\\.test.*)^metabase\\.(lib|driver|legacy-mbql|query-processor).*"
|
||||
:name performance-sensitive}
|
||||
;;
|
||||
;; general QP tests are ones that run across multiple drivers. Anything `metabase.query-processor*-test`,
|
||||
;; `metabase.driver.sql*-test` (excluding SQLServer and SQLite), or
|
||||
;; `metabase-enterprise.sandbox.query-processor*-test`
|
||||
;;
|
||||
{:pattern "^metabase(?:((?:-enterprise\\.sandbox)?\\.query-processor)|(?:\\.driver\\.sql(?!server)(?!ite))).*-test$"
|
||||
:name general-qp-and-driver-test-namespaces}
|
||||
{:pattern "^metabase\\.python-runner\\..*"
|
||||
:name python-runner-namespaces}]
|
||||
:name general-qp-and-driver-test-namespaces}]
|
||||
|
||||
:config-in-ns
|
||||
{test-namespaces
|
||||
@@ -745,13 +727,9 @@
|
||||
{:inline-def {:level :off}
|
||||
:missing-docstring {:level :off}
|
||||
:private-call {:level :off}
|
||||
:discouraged-var {metabase.driver/database-supports? {:level :off}}
|
||||
:metabase/defsetting-must-specify-export {:level :off}
|
||||
:metabase/defsetting-namespace {:level :off}
|
||||
|
||||
:discouraged-var
|
||||
{metabase.driver/database-supports? {:level :off}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}}}
|
||||
:metabase/defsetting-namespace {:level :off}}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
@@ -764,13 +742,9 @@
|
||||
{:metabase/validate-escaped-single-quotes-in-i18n {:level :warning}
|
||||
:metabase/validate-string-or-str-args-to-i18n {:level :warning}
|
||||
:metabase/discourage-millis-duration {:level :warning}
|
||||
|
||||
:discouraged-var
|
||||
{clojure.core/with-redefs {:message "Don't use with-redefs outside of tests"}
|
||||
clojure.core/eval {:message "Don't use eval outside of tests"}}
|
||||
|
||||
:discouraged-namespace
|
||||
{metabase.query-processor.store {:message "Please do not use the QP Store outside of legacy QP or driver code. Use MBQL 5/Lib or lib.metadata.jvm/applicaton-database-metadata-provider instead."}}}}
|
||||
clojure.core/eval {:message "Don't use eval outside of tests"}}}}
|
||||
|
||||
printable-namespaces
|
||||
{:linters
|
||||
@@ -795,11 +769,9 @@
|
||||
;; eventually we should do this for the whole codebase, but the args are in the opposite order so switching them
|
||||
;; all at once isn't trivial, at least we can stop using it in new code.
|
||||
:discouraged-var
|
||||
{medley.core/map-keys {:message "Use metabase.util.performance/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}
|
||||
metabase.test/with-temp {:message "Don't use application database inside Lib code"}}
|
||||
{medley.core/map-keys {:message "Use clojure.core/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.test/with-temp {:message "Don't use application database inside MLv2 code"}}
|
||||
|
||||
:discouraged-namespace
|
||||
{metabase.driver {:message "MLv2 code should be independent of driver code/methods"}
|
||||
@@ -821,36 +793,26 @@
|
||||
{:discouraged-var
|
||||
{metabase.driver/database-supports? {:level :off}}}}
|
||||
|
||||
performance-sensitive
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{clojure.core/update-keys {:message "Use metabase.util.performance/update-keys"}}}}
|
||||
|
||||
qp-and-driver-source-namespaces
|
||||
{:linters
|
||||
{:discouraged-namespace
|
||||
{metabase.query-processor.store {:level :off}
|
||||
metabase.util.malli.schema {:message "Prefer metabase.lib.schema or metabase.legacy-mbql.schema schemas in QP/driver code"}
|
||||
toucan.db {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.models {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.util.test {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan2.core {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}
|
||||
{metabase.util.malli.schema {:message "Prefer metabase.lib.schema or metabase.legacy-mbql.schema schemas in QP/driver code"}
|
||||
toucan.db {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.models {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.util.test {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan2.core {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}
|
||||
|
||||
:discouraged-var
|
||||
{medley.core/map-keys {:message "Use metabase.util.performance/update-keys"}
|
||||
{medley.core/map-keys {:message "Use clojure.core/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.app-db.core/query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
metabase.app-db.core/reducible-query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}}}}
|
||||
metabase.app-db.core/reducible-query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}}}
|
||||
|
||||
general-qp-and-driver-test-namespaces
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{metabase.test/with-column-remappings {:message "Use lib.tu/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test.util/with-column-remappings {:message "Use lib.tu/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test/with-temp {:message "Use lib.tu/mock-metadata-provider in QP tests. Exceptions: tests for code that doesn't use MPs or models not supported by MPs"}
|
||||
toucan2.tools.with-temp/with-temp {:message "Use lib.tu/mock-metadata-provider in QP tests. Exceptions: tests for code that doesn't use MPs or models not supported by MPs"}}
|
||||
{metabase.test/with-column-remappings {:message "Use metabase.lib.test-util/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test.util/with-column-remappings {:message "Use metabase.lib.test-util/remap-metadata-provider instead of with-column-remappings in QP tests"}}
|
||||
|
||||
:metabase/disallow-hardcoded-driver-names-in-tests
|
||||
{:level :warning}}}}}
|
||||
|
||||
@@ -52,13 +52,7 @@
|
||||
|
||||
(defn- lint-require* [node current-ns config]
|
||||
(let [[_require & args] (:children node)
|
||||
required-namespaces (->> (keep unwrap-require args)
|
||||
;; `require` runs through `cc/load-libs` which allows
|
||||
;; #{:as :reload :reload-all :require :use :verbose :refer :as-alias}
|
||||
;; as args. If you use a REPL tool that applies clj-kondo linting (e.g., Clojure MCP)
|
||||
;; you may wish to `:reload` or `:reload-all` a namespace. So we shouldn't assume all
|
||||
;; args are keywords:
|
||||
(remove keyword?))]
|
||||
required-namespaces (keep unwrap-require args)]
|
||||
(lint* node current-ns config required-namespaces)))
|
||||
|
||||
(defn- lint-requiring-resolve* [node current-ns config]
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
metabase.lib.join/with-join-alias [[:default]]
|
||||
metabase.lib.join/with-join-conditions [[:default]]
|
||||
metabase.lib.test-util.macros/$ids [[:inner 0]]
|
||||
metabase.lib.test-util.macros/mbql-5-query [[:inner 0]]
|
||||
metabase.lib.test-util.macros/mbql-query [[:inner 0]]
|
||||
metabase.lib.util.match/match [[:inner 0]]
|
||||
metabase.lib.util.match/match-one [[:inner 0]]
|
||||
@@ -285,7 +284,6 @@
|
||||
metabase.upload.impl-test/with-upload-table! [[:inner 0]]
|
||||
metabase.upload.types/with-currency [[:default]]
|
||||
metabase.upload.types/with-parens [[:default]]
|
||||
metabase.util/for-map [[:block 1]]
|
||||
metabase.util.async/cancelable-thread [[:block 0]]
|
||||
metabase.util.date-2/with-time-zone-same-instant [[:default]]
|
||||
metabase.util.encryption-test/with-secret-key [[:block 1]]
|
||||
|
||||
20
.eslintrc.js
@@ -1,8 +1,6 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
const path = require("path");
|
||||
|
||||
// `postcss-modules` lints css modules class names, but it currently crashes
|
||||
// eslint on vscode. If you use webstorm or want to run the lint for the cli, you
|
||||
// can use this flag to enable it. This is set to true in CI
|
||||
@@ -14,7 +12,6 @@ if (shouldLintCssModules) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ignorePatterns: ["!.storybook"],
|
||||
rules: {
|
||||
strict: [2, "never"],
|
||||
"no-undef": 2,
|
||||
@@ -49,7 +46,6 @@ module.exports = {
|
||||
],
|
||||
curly: [1, "all"],
|
||||
eqeqeq: [1, "smart"],
|
||||
"import/no-duplicates": ["warn", { considerQueryString: true }],
|
||||
"import/no-default-export": 2,
|
||||
"import/no-named-as-default": 0,
|
||||
"import/no-commonjs": 1,
|
||||
@@ -159,7 +155,6 @@ module.exports = {
|
||||
"import/internal-regex": "^metabase/|^metabase-lib/",
|
||||
"import/resolver": {
|
||||
webpack: {
|
||||
config: path.resolve(__dirname, "./rspack.main.config.js"),
|
||||
typescript: true,
|
||||
},
|
||||
},
|
||||
@@ -180,7 +175,6 @@ module.exports = {
|
||||
{
|
||||
files: ["*.js", "*.jsx", "*.ts", "*.tsx"],
|
||||
rules: {
|
||||
"jtag-missing-key": "error",
|
||||
"no-unconditional-metabase-links-render": "error",
|
||||
"no-color-literals": "error",
|
||||
"no-literal-metabase-strings": "error",
|
||||
@@ -205,15 +199,12 @@ module.exports = {
|
||||
"enterprise/frontend/src/metabase-enterprise/whitelabel/**/*",
|
||||
"frontend/lint/**/*",
|
||||
"*.stories.*",
|
||||
"**/.storybook/*",
|
||||
"stories-data.*",
|
||||
"e2e/**/*",
|
||||
"**/tests/*",
|
||||
"release/**/*",
|
||||
"webpack.config.js",
|
||||
"rspack.config.js",
|
||||
"rspack.main.config.js",
|
||||
"rspack.embedding-sdk-package.config.js",
|
||||
"rspack.embedding-sdk-bundle.config.js",
|
||||
],
|
||||
rules: {
|
||||
"no-color-literals": "off",
|
||||
@@ -230,7 +221,8 @@ module.exports = {
|
||||
"e2e/**/*",
|
||||
"**/tests/*",
|
||||
"release/**/*",
|
||||
"rspack.main.config.js",
|
||||
"webpack.config.js",
|
||||
"rspack.config.js",
|
||||
],
|
||||
rules: {
|
||||
"i18next/no-literal-string": "off",
|
||||
@@ -341,11 +333,5 @@ module.exports = {
|
||||
"no-color-literals": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["frontend/build/**/*.js"],
|
||||
rules: {
|
||||
"import/no-commonjs": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
50
.github/CODEOWNERS
vendored
@@ -1,13 +1,11 @@
|
||||
# Before changing this file, make sure you have read how we use it:
|
||||
# https://www.notion.so/metabase/Pull-Request-Code-Review-Guide-374f05df889748b69d67af753f9bc9b8?pvs=4#36550c04ceab40b5a8b8bee6264b090c
|
||||
|
||||
enterprise/frontend/src/embedding-sdk-package @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk-bundle @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk-shared @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk @metabase/embedding
|
||||
frontend/src/metabase/embedding-sdk @metabase/embedding
|
||||
frontend/src/metabase/public/containers/PublicOrEmbeddedQuestion @metabase/embedding
|
||||
frontend/src/metabase/public/containers/PublicOrEmbeddedDashboard @metabase/embedding
|
||||
frontend/src/metabase/ui @metabase/core-frontend-ux-west
|
||||
frontend/src/metabase/ui @metabase/core-frontend-admin-webapp
|
||||
# snowplow/* @metabase/data
|
||||
src/metabase/analytics/prometheus.clj @metabase/cloud-ops
|
||||
.github @metabase/devexp
|
||||
@@ -22,8 +20,8 @@ docs/developers-guide # exclude from tech-writer ownership
|
||||
#
|
||||
|
||||
# modules/drivers @metabase/drivers
|
||||
src/metabase/driver/sql_jdbc/actions.clj @metabase/core-ux-east
|
||||
test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-ux-east
|
||||
src/metabase/driver/sql_jdbc/actions.clj @metabase/core-workflows
|
||||
test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-workflows
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/advanced_config @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/advanced_config @metabase/core-backend-admin-webapp
|
||||
@@ -55,8 +53,8 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-ux-east
|
||||
# enterprise/backend/src/metabase_enterprise/core @metabase/devexp
|
||||
# enterprise/backend/test/metabase_enterprise/core @metabase/devexp
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/dashboard_subscription_filters @metabase/core-ux-east
|
||||
# enterprise/backend/test/metabase_enterprise/dashboard_subscription_filters @metabase/core-ux-east
|
||||
# enterprise/backend/src/metabase_enterprise/dashboard_subscription_filters @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/dashboard_subscription_filters @metabase/core-workflows
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/enhancements @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/enhancements @metabase/core-backend-admin-webapp
|
||||
@@ -73,11 +71,11 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-ux-east
|
||||
# enterprise/backend/src/metabase_enterprise/scim @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/scim @metabase/core-backend-admin-webapp
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/search ...
|
||||
# enterprise/backend/test/metabase_enterprise/search ...
|
||||
# enterprise/backend/src/metabase_enterprise/search @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/search @metabase/core-workflows
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/serialization @metabase/core-ux-east
|
||||
# enterprise/backend/test/metabase_enterprise/serialization @metabase/core-ux-east
|
||||
# enterprise/backend/src/metabase_enterprise/serialization @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/serialization @metabase/core-workflows
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/snippet_collections @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/snippet_collections @metabase/core-backend-admin-webapp
|
||||
@@ -97,8 +95,8 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-ux-east
|
||||
# enterprise/backend/src/metabase_enterprise/upload_management @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/upload_management @metabase/core-backend-admin-webapp
|
||||
|
||||
src/metabase/actions @metabase/core-ux-east
|
||||
test/metabase/actions @metabase/core-ux-east
|
||||
src/metabase/actions @metabase/core-backend-admin-webapp
|
||||
test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/activity_feed @metabase/core-backend-admin-webapp
|
||||
# test/metabase/activity_feed @metabase/core-backend-admin-webapp
|
||||
@@ -124,11 +122,11 @@ test/metabase/actions @metabase/core-ux-east
|
||||
# src/metabase/cmd @metabase/devexp
|
||||
# test/metabase/cmd @metabase/devexp
|
||||
|
||||
# src/metabase/channel @metabase/core-ux-east
|
||||
# test/metabase/channel @metabase/core-ux-east
|
||||
# src/metabase/channel @metabase/core-workflows
|
||||
# test/metabase/channel @metabase/core-workflows
|
||||
|
||||
# src/metabase/cloud_migration ...
|
||||
# test/metabase/cloud_migration ...
|
||||
# src/metabase/cloud_migration @metabase/core-workflows
|
||||
# test/metabase/cloud_migration @metabase/core-workflows
|
||||
|
||||
# src/metabase/cmd @metabase/devexp
|
||||
# test/metabase/cmd @metabase/devexp
|
||||
@@ -160,8 +158,8 @@ test/metabase/actions @metabase/core-ux-east
|
||||
# src/metabase/indexed_entities @metabase/core-backend-querying
|
||||
# test/metabase/indexed_entities @metabase/core-backend-querying
|
||||
|
||||
# src/metabase/integrations ...
|
||||
# test/metabase/integrations ...
|
||||
# src/metabase/integrations @metabase/core-workflows
|
||||
# test/metabase/integrations @metabase/core-workflows
|
||||
|
||||
# src/metabase/legacy_mbql @metabase/core-backend-querying
|
||||
# test/metabase/legacy_mbql @metabase/core-backend-querying
|
||||
@@ -184,8 +182,8 @@ test/metabase/actions @metabase/core-ux-east
|
||||
# src/metabase/moderation @metabase/core-backend-admin-webapp
|
||||
# test/metabase/moderation @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/notification @metabase/core-ux-east
|
||||
# test/metabase/notification @metabase/core-ux-east
|
||||
# src/metabase/notification @metabase/core-workflows
|
||||
# test/metabase/notification @metabase/core-workflows
|
||||
|
||||
# src/metabase/permissions @metabase/core-backend-admin-webapp
|
||||
# test/metabase/permissions @metabase/core-backend-admin-webapp
|
||||
@@ -202,8 +200,8 @@ test/metabase/actions @metabase/core-ux-east
|
||||
# src/metabase/public_sharing @metabase/core-backend-admin-webapp
|
||||
# test/metabase/public_sharing @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/pulse @metabase/core-ux-east
|
||||
# test/metabase/pulse @metabase/core-ux-east
|
||||
# src/metabase/pulse @metabase/core-workflows
|
||||
# test/metabase/pulse @metabase/core-workflows
|
||||
|
||||
# src/metabase/query_analysis @metabase/core-backend-querying
|
||||
# test/metabase/query_analysis @metabase/core-backend-querying
|
||||
@@ -220,8 +218,8 @@ test/metabase/actions @metabase/core-ux-east
|
||||
# src/metabase/sample_data @metabase/core-backend-admin-webapp
|
||||
# test/metabase/sample_data @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/search ...
|
||||
# test/metabase/search ...
|
||||
# src/metabase/search @metabase/core-workflows
|
||||
# test/metabase/search @metabase/core-workflows
|
||||
|
||||
# src/metabase/segments @metabase/core-backend-querying
|
||||
# test/metabase/segments @metabase/core-backend-querying
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -63,8 +63,7 @@ body:
|
||||
attributes:
|
||||
label: Information about your Metabase installation
|
||||
description: |
|
||||
For versions >= 56, copy and paste the Diagnostic info from `Admin -> Tools -> Help`.
|
||||
For versions < 56, copy and paste the Diagnostic info from `Admin -> Troubleshooting`.
|
||||
Copy and paste the JSON from `Admin -> Troubleshooting`.
|
||||
_This will be automatically formatted into code, so no need for backticks._
|
||||
placeholder: |
|
||||
{"browser-info": {
|
||||
|
||||
17
.github/actions/await-port/action.yml
vendored
@@ -1,5 +1,4 @@
|
||||
name: await-port
|
||||
description: Wait for localhost port to be ready
|
||||
name: Wait for localhost port to be ready
|
||||
|
||||
inputs:
|
||||
port:
|
||||
@@ -11,18 +10,6 @@ runs:
|
||||
- name: Wait for port ${{ inputs.port }} to be ready
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Waiting for port ${{ inputs.port }} to be ready..."
|
||||
timeout=300 # 5 minutes timeout
|
||||
elapsed=0
|
||||
while ! nc -z localhost ${{ inputs.port }}; do
|
||||
if [ $elapsed -ge $timeout ]; then
|
||||
echo "❌ Timeout waiting for port ${{ inputs.port }} after ${timeout} seconds"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
elapsed=$((elapsed + 1))
|
||||
if [ $((elapsed % 10)) -eq 0 ]; then
|
||||
echo " Still waiting for port ${{ inputs.port }}... ($elapsed seconds)"
|
||||
fi
|
||||
sleep 0.1;
|
||||
done
|
||||
echo "✅ Port ${{ inputs.port }} is ready!"
|
||||
|
||||
68
.github/actions/fetch-artifact/action.yml
vendored
@@ -5,14 +5,6 @@ inputs:
|
||||
name:
|
||||
description: The name of the artifact to fetch
|
||||
required: true
|
||||
output-name:
|
||||
description: Optional custom name for the output jar file (defaults to metabase.jar)
|
||||
required: false
|
||||
default: "metabase.jar"
|
||||
extract-path:
|
||||
description: Directory path where the jar should be extracted (defaults to current directory)
|
||||
required: false
|
||||
default: "."
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -33,7 +25,7 @@ runs:
|
||||
});
|
||||
|
||||
if (!artifacts.data?.artifacts?.[0]?.id) {
|
||||
throw new Error(`No artifacts found for ${{ inputs.name }}`);
|
||||
throw new Error(`No artifacts found for ${{ inputs.commit }}`);
|
||||
}
|
||||
|
||||
const artifact_id = artifacts.data.artifacts[0].id;
|
||||
@@ -47,59 +39,25 @@ runs:
|
||||
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/mb.zip`, Buffer.from(download.data));
|
||||
|
||||
- name: Extract and rename JAR
|
||||
- name: unzip uberjar artifact
|
||||
shell: bash
|
||||
run: unzip mb.zip
|
||||
- name: Move the Uberjar
|
||||
shell: bash
|
||||
run: | # bash
|
||||
OUTPUT_NAME="${{ inputs.output-name }}"
|
||||
EXTRACT_PATH="${{ inputs.extract-path }}"
|
||||
|
||||
# Create a temporary directory for extraction to avoid conflicts
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
# Extract to temporary directory
|
||||
unzip mb.zip -d "$TEMP_DIR"
|
||||
|
||||
# Create target directory
|
||||
mkdir -p "$EXTRACT_PATH"
|
||||
|
||||
# Find the jar and move all files from its directory
|
||||
if [ -e "$TEMP_DIR/metabase.jar" ]; then
|
||||
# Move all files to extract path
|
||||
mv "$TEMP_DIR"/* "$EXTRACT_PATH/" 2>/dev/null || true
|
||||
# Rename the jar to custom name if different
|
||||
if [ "$OUTPUT_NAME" != "metabase.jar" ]; then
|
||||
mv "$EXTRACT_PATH/metabase.jar" "$EXTRACT_PATH/$OUTPUT_NAME"
|
||||
fi
|
||||
elif [ -e "$TEMP_DIR/target/uberjar/metabase.jar" ]; then
|
||||
# Move all files from uberjar directory to extract path
|
||||
mv "$TEMP_DIR/target/uberjar"/* "$EXTRACT_PATH/" 2>/dev/null || true
|
||||
# Rename the jar to custom name if different
|
||||
if [ "$OUTPUT_NAME" != "metabase.jar" ]; then
|
||||
mv "$EXTRACT_PATH/metabase.jar" "$EXTRACT_PATH/$OUTPUT_NAME"
|
||||
fi
|
||||
if [ -e "metabase.jar" ]; then
|
||||
echo "metabase.jar is already in the right place"
|
||||
elif [ -e "target/uberjar/metabase.jar" ]; then
|
||||
echo "moving metabase.jar to current directory"
|
||||
mv target/uberjar/metabase.jar metabase.jar
|
||||
else
|
||||
echo "Could not find metabase.jar in extracted files"
|
||||
echo "Could not find the metabase.jar file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up temporary directory
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Set the JAR_PATH environment variable
|
||||
if [ "$EXTRACT_PATH" == "." ]; then
|
||||
echo "JAR_PATH=$OUTPUT_NAME" >> $GITHUB_ENV
|
||||
else
|
||||
echo "JAR_PATH=$EXTRACT_PATH/$OUTPUT_NAME" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Verify that this is a valid JAR file
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Verifying JAR at: $JAR_PATH"
|
||||
file --mime-type "$JAR_PATH"
|
||||
|
||||
run: file --mime-type ./metabase.jar
|
||||
- name: Reveal its version.properties
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Extracting version.properties from: $JAR_PATH"
|
||||
jar xf "$JAR_PATH" version.properties && cat version.properties
|
||||
run: jar xf metabase.jar version.properties && cat version.properties
|
||||
|
||||
74
.github/actions/get-docker-info/action.yml
vendored
@@ -1,74 +0,0 @@
|
||||
name: Get Docker Info
|
||||
description: Determines Docker repository and tag based on branch and edition
|
||||
|
||||
inputs:
|
||||
branch:
|
||||
description: Branch name (defaults to current branch)
|
||||
required: false
|
||||
default: ${{ github.head_ref || github.ref_name }}
|
||||
edition:
|
||||
description: Edition (ee or oss)
|
||||
required: false
|
||||
default: ee
|
||||
owner:
|
||||
description: Repository owner (defaults to current repo owner)
|
||||
required: false
|
||||
default: ${{ github.repository_owner }}
|
||||
|
||||
outputs:
|
||||
repo:
|
||||
description: Docker repository name
|
||||
value: ${{ steps.docker-info.outputs.repo }}
|
||||
tag:
|
||||
description: Docker tag
|
||||
value: ${{ steps.docker-info.outputs.tag }}
|
||||
full_image:
|
||||
description: Full Docker image name (repo:tag)
|
||||
value: ${{ steps.docker-info.outputs.full_image }}
|
||||
editions:
|
||||
description: JSON array of editions to build
|
||||
value: ${{ steps.docker-info.outputs.editions }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Determine Docker info
|
||||
id: docker-info
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const branch = '${{ inputs.branch }}';
|
||||
const edition = '${{ inputs.edition }}';
|
||||
const owner = '${{ inputs.owner }}';
|
||||
|
||||
console.log(`Determining Docker info for branch: ${branch}, edition: ${edition}`);
|
||||
|
||||
let repo, tag, editions;
|
||||
|
||||
if (branch === 'master') {
|
||||
// Master builds both editions with specific repos
|
||||
editions = ['ee', 'oss'];
|
||||
tag = 'latest';
|
||||
|
||||
if (edition === 'ee') {
|
||||
repo = `${owner}/metabase-enterprise-head`;
|
||||
} else {
|
||||
repo = `${owner}/metabase-head`;
|
||||
}
|
||||
} else {
|
||||
// All other branches only build EE to metabase-dev
|
||||
editions = ['ee'];
|
||||
tag = branch.replaceAll('/', '-'); // slashes make docker sad
|
||||
repo = `${owner}/metabase-dev`;
|
||||
}
|
||||
|
||||
const fullImage = `${repo}:${tag}`;
|
||||
|
||||
// Set outputs
|
||||
core.setOutput('repo', repo);
|
||||
core.setOutput('tag', tag);
|
||||
core.setOutput('full_image', fullImage);
|
||||
core.setOutput('editions', JSON.stringify(editions));
|
||||
|
||||
console.log(`Docker image: ${fullImage}`);
|
||||
console.log(`Editions: ${JSON.stringify(editions)}`);
|
||||
8
.github/actions/prepare-backend/action.yml
vendored
@@ -1,7 +1,4 @@
|
||||
name: Prepare back-end environment
|
||||
description: |
|
||||
Prepare the backend. Installs jdk, Clojure, and fetches the cache for m2. The CI config fetchs `ci-test-config.json`
|
||||
from master and lets us ignore tests at the var level if they are flaking.
|
||||
inputs:
|
||||
java-version:
|
||||
required: true
|
||||
@@ -24,14 +21,9 @@ runs:
|
||||
distribution: 'temurin'
|
||||
- name: Install Clojure CLI
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
run: |
|
||||
curl -O https://download.clojure.org/install/linux-install-${{ inputs.clojure-version }}.sh &&
|
||||
sudo bash ./linux-install-${{ inputs.clojure-version }}.sh
|
||||
- name: Fetch CI config
|
||||
shell: bash
|
||||
run: |
|
||||
curl -o ci-test-config.json https://raw.githubusercontent.com/metabase/metabase/refs/heads/master/ci-test-config.json
|
||||
- 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"
|
||||
|
||||
3
.github/actions/test-driver/action.yml
vendored
@@ -1,5 +1,4 @@
|
||||
name: Test database driver
|
||||
description: Test database driver
|
||||
inputs:
|
||||
junit-name:
|
||||
required: true
|
||||
@@ -40,7 +39,7 @@ runs:
|
||||
list-tests: failed
|
||||
fail-on-error: false
|
||||
- name: Upload Logs on Failure
|
||||
if: always() && !success()
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ github.job }}
|
||||
|
||||
24
.github/file-paths.yaml
vendored
@@ -29,10 +29,9 @@ frontend_configs: &frontend_configs
|
||||
- ".eslintrc.js"
|
||||
- "postcss.config.js"
|
||||
- "rspack.config.js"
|
||||
- "rspack.main.config.js"
|
||||
- "rspack.embedding-sdk-package.config.js"
|
||||
- "rspack.embedding-sdk-bundle.config.js"
|
||||
- "rspack.static-viz.config.js"
|
||||
- "webpack.config.js"
|
||||
- "webpack.embedding-sdk.config.js"
|
||||
- "webpack.static-viz.config.js"
|
||||
- ".nvmrc"
|
||||
|
||||
frontend_sources: &frontend_sources
|
||||
@@ -41,17 +40,10 @@ frontend_sources: &frontend_sources
|
||||
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
|
||||
- "frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
|
||||
|
||||
frontend_embedding_sources:
|
||||
- "enterprise/frontend/src/{embedding,embedding-*}/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
|
||||
- "enterprise/frontend/src/metabase-enterprise/{embedding,embedding-*}**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
|
||||
|
||||
frontend_embedding_sdk_sources:
|
||||
- *frontend_configs
|
||||
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
|
||||
|
||||
frontend_embedding_sdk_package_sources:
|
||||
- "enterprise/frontend/src/embedding-sdk-package/**/!(*.spec).{js,jsx,ts,tsx,css}"
|
||||
|
||||
frontend_specs: &frontend_specs
|
||||
- *shared_specs
|
||||
- "frontend/test/**"
|
||||
@@ -140,22 +132,20 @@ e2e_embedding_sdk_compatibility:
|
||||
- *default
|
||||
- *frontend_embedding_sdk_ci
|
||||
- *frontend_sources
|
||||
- *backend_sources
|
||||
- "e2e/embedding-sdk-host-apps/**"
|
||||
- "e2e/runner/embedding-sdk/**"
|
||||
- "e2e/test-host-app/**/*.cy.*.{js,ts}"
|
||||
|
||||
snowplow: &snowplow
|
||||
- ".github/workflows/snowplow.yml"
|
||||
- "snowplow/**"
|
||||
|
||||
e2e_all:
|
||||
- *default
|
||||
- *e2e_ci
|
||||
- *sources
|
||||
- *e2e_specs
|
||||
- "e2e/**"
|
||||
- *snowplow
|
||||
|
||||
snowplow:
|
||||
- ".github/workflows/snowplow.yml"
|
||||
- "snowplow/**"
|
||||
|
||||
documentation:
|
||||
- "docs/**"
|
||||
|
||||
@@ -1,66 +1,24 @@
|
||||
const TYPES = new Set([
|
||||
"feat",
|
||||
"fix",
|
||||
"perf",
|
||||
"docs",
|
||||
"style",
|
||||
"refactor",
|
||||
"test",
|
||||
"build",
|
||||
"ci",
|
||||
]);
|
||||
|
||||
/**
|
||||
* @param title {string}
|
||||
*/
|
||||
function isConventionalTitle(title) {
|
||||
const match = /^(?<type>\w+)\((?<rawScopes>[^)]+)\):/.exec(title);
|
||||
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [, type, rawScopes] = match;
|
||||
const scopes = rawScopes
|
||||
.split(",")
|
||||
.map((scope) => scope.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
return TYPES.has(type) && scopes.length > 0;
|
||||
}
|
||||
exports.updateComment = updateComment;
|
||||
|
||||
/** @param {import('@types/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
|
||||
async function updateCommentForEmbedding({ github, context }) {
|
||||
async function updateComment({ github, context }) {
|
||||
const githubUsername = context.payload.sender.login;
|
||||
|
||||
const comment = `${CONVENTIONAL_COMMENT_IDENTIFIER}
|
||||
@${githubUsername} You have modified embedding code. Please make sure the PR title follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) style.
|
||||
Here are all the supported types:
|
||||
const comment = `${CONVENTIONAL_COMMIT_REMINDER_COMMENT_IDENTIFIER}
|
||||
@${githubUsername} You have modified embedding SDK code. Please make sure the PR title follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) style.
|
||||
Here are all the supported types that will be shown in the changelog:
|
||||
- \`feat\`
|
||||
- \`fix\`
|
||||
- \`perf\`
|
||||
- \`docs\`
|
||||
- \`style\`
|
||||
- \`refactor\`
|
||||
- \`test\`
|
||||
- \`build\`
|
||||
- \`ci\`
|
||||
|
||||
Please also make sure to include a scope.
|
||||
These types \`docs\`, \`style\`, \`refactor\`, \`test\`, \`build\`, and \`ci\` are also encouraged for non-changelog related tasks.
|
||||
|
||||
Please also make sure to include \`sdk\` scope, otherwise, the changelog will not include this task.
|
||||
|
||||
For example, these are valid PR titles:
|
||||
- \`feat(sdk-bundle): Add interactive dashboard component\`
|
||||
- \`fix(sdk-package): Fixed MetabaseProviderPropsStore logic\`
|
||||
- \`fix(sdk-package, embed-js): Fix API\``;
|
||||
- \`feat(sdk): Add interactive dashboard component\`
|
||||
- \`feat(sdk): Support theming pie chart\`
|
||||
- \`fix(sdk): Fix static dashboard crash\``;
|
||||
|
||||
return updateComment(comment, { github, context });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comment {string}
|
||||
* @param {import('@types/github-script').AsyncFunctionArguments} AsyncFunctionArguments
|
||||
*/
|
||||
async function updateComment(comment, { github, context }) {
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const pullRequestNumber = context.issue.number;
|
||||
@@ -91,19 +49,20 @@ async function updateComment(comment, { github, context }) {
|
||||
}
|
||||
}
|
||||
|
||||
const CONVENTIONAL_COMMENT_IDENTIFIER =
|
||||
"<!---conventional comment identifier-->";
|
||||
|
||||
const CONVENTIONAL_COMMIT_REMINDER_COMMENT_IDENTIFIER =
|
||||
"<!---conventional commit reminder comment ID-->";
|
||||
/**
|
||||
* @param comments {{body: string}[]}
|
||||
* @typedef Comment
|
||||
* @property {string} body
|
||||
*
|
||||
* @param {Comment[]} comments
|
||||
*/
|
||||
function getExistingConventionalCommitReminderComment(comments) {
|
||||
for (const comment of comments) {
|
||||
if (comment.body.startsWith(CONVENTIONAL_COMMENT_IDENTIFIER)) {
|
||||
if (
|
||||
comment.body.startsWith(CONVENTIONAL_COMMIT_REMINDER_COMMENT_IDENTIFIER)
|
||||
) {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.isConventionalTitle = isConventionalTitle;
|
||||
exports.updateCommentForEmbedding = updateCommentForEmbedding;
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
const { isConventionalTitle } = require("./utils");
|
||||
|
||||
describe("isConventionalTitle", () => {
|
||||
it("returns true for a simple conventional commit", () => {
|
||||
expect(isConventionalTitle("feat: add new feature")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true for a commit with a scope", () => {
|
||||
expect(isConventionalTitle("fix(api): correct API bug")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true for a commit with multiple scopes, comma separated", () => {
|
||||
expect(isConventionalTitle("feat(build,deps): update dependencies")).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("returns true for a commit with multiple scopes, comma separated with space", () => {
|
||||
expect(isConventionalTitle("feat(build, deps): update dependencies")).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("returns false for a commit with round brackets in a message", () => {
|
||||
expect(isConventionalTitle("feat: (something) update dependencies")).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it("returns false for missing colon", () => {
|
||||
expect(isConventionalTitle("feat add feature")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false for invalid type", () => {
|
||||
expect(isConventionalTitle("invalidType: some message")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false for empty message", () => {
|
||||
expect(isConventionalTitle("feat:")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false for empty input", () => {
|
||||
expect(isConventionalTitle("")).toBe(false);
|
||||
});
|
||||
});
|
||||
84
.github/scripts/get-issue-data.js
vendored
@@ -1,84 +0,0 @@
|
||||
const githubSlackMap = require("../../release/github-slack-map.json");
|
||||
|
||||
async function getIssueData({ context, github, manualIssueNumber }) {
|
||||
let issueNumber;
|
||||
let issueData;
|
||||
let prReviews = [];
|
||||
const triggerType = context.eventName;
|
||||
|
||||
if (context.eventName === "issues") {
|
||||
issueNumber = context.payload.issue.number;
|
||||
issueData = context.payload.issue;
|
||||
} else if (context.eventName === "workflow_dispatch") {
|
||||
issueNumber = parseInt(manualIssueNumber);
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
issueData = data;
|
||||
} else if (context.eventName === "pull_request_review") {
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { data: prData } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
// Extract issue number from branch name (e.g., "claude-fix/issue-12345-some-title")
|
||||
const branchMatch = prData.head.ref.match(/claude-fix\/issue-(\d+)/);
|
||||
if (!branchMatch) {
|
||||
throw new Error(
|
||||
`Could not extract issue number from branch name: ${prData.head.ref}`,
|
||||
);
|
||||
}
|
||||
|
||||
issueNumber = parseInt(branchMatch[1]);
|
||||
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
issueData = data;
|
||||
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
prReviews = reviews.filter(
|
||||
(review) =>
|
||||
review.state === "CHANGES_REQUESTED" &&
|
||||
isMetabaseMember(review.user.login),
|
||||
);
|
||||
}
|
||||
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const employeeComments = comments.filter((comment) =>
|
||||
isMetabaseMember(comment.user.login),
|
||||
);
|
||||
|
||||
return {
|
||||
issueNumber,
|
||||
issueData,
|
||||
employeeComments,
|
||||
prReviews,
|
||||
triggerType,
|
||||
isIssueAuthorEmployee: isMetabaseMember(issueData.user.login),
|
||||
};
|
||||
}
|
||||
|
||||
function isMetabaseMember(username) {
|
||||
return username in githubSlackMap;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getIssueData,
|
||||
};
|
||||
66
.github/team.json
vendored
@@ -8,11 +8,21 @@
|
||||
"romeovs",
|
||||
"bshepherdson",
|
||||
"metamben",
|
||||
"uladzimirdev",
|
||||
"wzimrin",
|
||||
"ericnormand",
|
||||
"galdre"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Semantic Layer",
|
||||
"label": ".Team/SemanticLayer",
|
||||
"members": [
|
||||
"kamilmielnik",
|
||||
"lbrdnk",
|
||||
"bronsa"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Drivers",
|
||||
"label": ".Team/Drivers",
|
||||
@@ -26,6 +36,7 @@
|
||||
"label": ".Team/Embedding",
|
||||
"members": [
|
||||
"WiNloSt",
|
||||
"oisincoveney",
|
||||
"npretto",
|
||||
"heypoom",
|
||||
"sanex3339",
|
||||
@@ -39,18 +50,31 @@
|
||||
"qnkhuat",
|
||||
"piranha",
|
||||
"crisptrutski",
|
||||
"deniskaber",
|
||||
"spalt08",
|
||||
"stasgavrylov",
|
||||
"uladzimirdev",
|
||||
"kulyk",
|
||||
"kamilmielnik"
|
||||
"stasgavrylov"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Admin Webapp",
|
||||
"label": ".Team/AdminWebapp",
|
||||
"members": [
|
||||
"eliotmetabase"
|
||||
"npfitz",
|
||||
"johnswanson",
|
||||
"rafpaf",
|
||||
"iethree",
|
||||
"nvoxland",
|
||||
"fraserdrops",
|
||||
"edpaget"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DashViz",
|
||||
"label": ".Team/DashViz",
|
||||
"members": [
|
||||
"alxnddr",
|
||||
"kulyk",
|
||||
"bpander"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -71,19 +95,13 @@
|
||||
"sloansparger",
|
||||
"somtom",
|
||||
"wotbrew",
|
||||
"tsplude",
|
||||
"lbrdnk",
|
||||
"bronsa"
|
||||
"tsplude"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Product Growth",
|
||||
"label": ".Team/ProductGrowth",
|
||||
"members": [
|
||||
"nemanjaglumac",
|
||||
"chodorowicz",
|
||||
"andsalves"
|
||||
]
|
||||
"members": ["nemanjaglumac", "chodorowicz"]
|
||||
},
|
||||
{
|
||||
"name": "Cloud",
|
||||
@@ -91,28 +109,6 @@
|
||||
"members": [
|
||||
"filipesilva"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DashViz",
|
||||
"label": ".Team/DashViz",
|
||||
"members": [
|
||||
"eliotmetabase"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UX West",
|
||||
"label": ".Team/UXWest",
|
||||
"members": [
|
||||
"eliotmetabase",
|
||||
"npfitz",
|
||||
"johnswanson",
|
||||
"iethree",
|
||||
"nvoxland",
|
||||
"edpaget",
|
||||
"deniskaber",
|
||||
"alxnddr",
|
||||
"bpander"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
3
.github/workflows/backend.yml
vendored
@@ -154,7 +154,7 @@ jobs:
|
||||
fail-on-error: false
|
||||
|
||||
- name: Upload Logs on Failure
|
||||
if: always() && !success()
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ matrix.java-version }}-${{ matrix.job.edition }}-${{ github.job }}
|
||||
@@ -195,7 +195,6 @@ jobs:
|
||||
- name: Run cljfmt
|
||||
run: ./bin/mage cljfmt-all --force-check
|
||||
|
||||
|
||||
be-tests-result:
|
||||
needs:
|
||||
- be-linter-eastwood
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
name: Block Master Branch PRs
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
check-source-branch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Block master branch PRs
|
||||
if: github.head_ref == 'master'
|
||||
run: |
|
||||
echo "PRs from `master` branches are not allowed, please use a new branch name for your PR."
|
||||
exit 1
|
||||
327
.github/workflows/claude-code-bug-fix.yml
vendored
@@ -1,327 +0,0 @@
|
||||
name: "Claude Code Bug Fix"
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
pull_request_review:
|
||||
types:
|
||||
- submitted
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: "Issue number to fix"
|
||||
required: true
|
||||
type: string
|
||||
override_employee_check:
|
||||
description: "Override employee check for issue creator"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
auto-fix-bug:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
if: |
|
||||
(github.event_name == 'issues' && github.event.label.name == 'Claude Bug Fix' && github.event.issue.state == 'open') ||
|
||||
(github.event_name == 'workflow_dispatch') ||
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' && startsWith(github.event.pull_request.head.ref, 'claude-fix/'))
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get issue data and check employee status
|
||||
id: get_issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { getIssueData } = require('${{ github.workspace }}/.github/scripts/get-issue-data.js');
|
||||
|
||||
try {
|
||||
const result = await getIssueData({
|
||||
context,
|
||||
github,
|
||||
manualIssueNumber: '${{ github.event.inputs.issue_number }}'
|
||||
});
|
||||
|
||||
const { issueNumber, issueData, employeeComments, prReviews, triggerType, isIssueAuthorEmployee } = result;
|
||||
|
||||
// Check employee status and fail if not authorized
|
||||
if (!result.isIssueAuthorEmployee && '${{ github.event.inputs.override_employee_check }}' !== 'true') {
|
||||
core.setFailed(`User ${result.issueData.user.login} is not a Metabase employee. Skipping bug fix automation.`);
|
||||
}
|
||||
|
||||
core.setOutput('issue_number', issueNumber);
|
||||
core.setOutput('issue_data', JSON.stringify(issueData));
|
||||
core.setOutput('issue_comments', JSON.stringify(employeeComments));
|
||||
core.setOutput('pr_reviews', JSON.stringify(prReviews));
|
||||
core.setOutput('trigger_type', triggerType);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
|
||||
- name: Set up git configuration
|
||||
run: |
|
||||
git config --global user.name "Claude Code[bot]"
|
||||
git config --global user.email "noreply@anthropic.com"
|
||||
|
||||
- name: Prepare issue context and bug fix prompt
|
||||
id: prepare_prompt
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
ISSUE_DATA: ${{ steps.get_issue.outputs.issue_data }}
|
||||
ISSUE_COMMENTS: ${{ steps.get_issue.outputs.issue_comments }}
|
||||
PR_REVIEWS: ${{ steps.get_issue.outputs.pr_reviews }}
|
||||
TRIGGER_TYPE: ${{ steps.get_issue.outputs.trigger_type }}
|
||||
with:
|
||||
script: |
|
||||
const issueData = JSON.parse(process.env.ISSUE_DATA);
|
||||
const issueComments = JSON.parse(process.env.ISSUE_COMMENTS);
|
||||
const prReviews = JSON.parse(process.env.PR_REVIEWS);
|
||||
const triggerType = process.env.TRIGGER_TYPE;
|
||||
const issueNumber = '${{ steps.get_issue.outputs.issue_number }}';
|
||||
|
||||
// Convert issue title to kebab case and create branch name
|
||||
const issueTitle = issueData.title || 'untitled';
|
||||
const kebabTitle = issueTitle
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '')
|
||||
.replace(/-+/g, '-')
|
||||
.substring(0, 50);
|
||||
const branchName = `claude-fix/issue-${issueNumber}-${kebabTitle}`;
|
||||
|
||||
// Format data for bash environment
|
||||
const formattedComments = issueComments.length > 0
|
||||
? issueComments.map(comment =>
|
||||
`**Comment by @${comment.user.login} on ${comment.created_at}:**\n${comment.body}`
|
||||
).join('\n\n---\n\n')
|
||||
: '';
|
||||
const formattedReviews = prReviews.length > 0
|
||||
? prReviews.map(review =>
|
||||
`**Review by @${review.user.login} on ${review.submitted_at} (Changes Requested):**\n${review.body || 'No review comment provided'}`
|
||||
).join('\n\n---\n\n')
|
||||
: '';
|
||||
|
||||
core.exportVariable('BRANCH_NAME', branchName);
|
||||
core.exportVariable('ISSUE_NUMBER', issueNumber);
|
||||
core.exportVariable('ISSUE_TITLE', issueData.title);
|
||||
core.exportVariable('ISSUE_AUTHOR', issueData.user.login);
|
||||
core.exportVariable('ISSUE_CREATED', issueData.created_at);
|
||||
core.exportVariable('ISSUE_BODY', issueData.body || 'No description provided');
|
||||
core.exportVariable('ISSUE_COMMENTS_FORMATTED', formattedComments);
|
||||
core.exportVariable('PR_REVIEWS_FORMATTED', formattedReviews);
|
||||
core.exportVariable('TRIGGER_TYPE', triggerType);
|
||||
|
||||
- name: Generate bug fix prompt
|
||||
run: |
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
BUG_FIX_PROMPT<<PROMPT_END
|
||||
You are helping to fix a bug reported in GitHub issue #${{ env.ISSUE_NUMBER }}.
|
||||
|
||||
## Bug Report Details
|
||||
**Title:** ${{ env.ISSUE_TITLE }}
|
||||
**Reporter:** ${{ env.ISSUE_AUTHOR }}
|
||||
**Created:** ${{ env.ISSUE_CREATED }}
|
||||
|
||||
**Description:**
|
||||
${{ env.ISSUE_BODY }}
|
||||
|
||||
**Comments:**
|
||||
${{ env.ISSUE_COMMENTS_FORMATTED }}
|
||||
EOF
|
||||
|
||||
# Add review feedback section only if this is a review trigger
|
||||
if [ "${{ env.TRIGGER_TYPE }}" = "pull_request_review" ]; then
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
|
||||
## Previous Fix Attempt - Review Feedback (MUST ADDRESS)
|
||||
Your previous automated fix attempt received the following feedback that needs to be addressed:
|
||||
|
||||
${{ env.PR_REVIEWS_FORMATTED }}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Add the rest of the prompt (always the same)
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
|
||||
## Instructions
|
||||
1. **Analyze the issue description and comments** - Understand what the issue is describing
|
||||
a. Pay particular attention to reproduction steps and if there's an agreed upon fix.
|
||||
2. **Search the codebase** - Use Grep and Glob tools to find relevant files
|
||||
3. **Implement a fix** - Follow existing code patterns and conventions
|
||||
4. **Test the fix** - Run appropriate tests using the commands in CLAUDE.md:
|
||||
- JavaScript/TypeScript: `yarn test-unit path/to/file.unit.spec.js`
|
||||
- Clojure: `clojure -X:dev:test :only namespace/test-name`
|
||||
- Lint: `yarn lint-eslint-pure` for JS/TS, `./bin/mage kondo <file>` for Clojure
|
||||
5. **Verify the fix** - Ensure tests pass and code follows conventions
|
||||
|
||||
## Important Guidelines
|
||||
- Follow the development patterns in CLAUDE.md
|
||||
- Write failing tests first, then fix them
|
||||
- Work in small, testable increments
|
||||
- Don't commit changes - leave that for the workflow
|
||||
- IMPORTANT: Focus only on fixing the reported bug, don't make unrelated changes
|
||||
|
||||
## Scratchpad Directory
|
||||
A `.claude-scratchpad/` directory has been created for your temporary files:
|
||||
- Use this directory for ALL temporary verification files. However, prefer using production test files rather than adhoc ones.
|
||||
- Only modify actual production code in the main repository directories
|
||||
- The scratchpad will be cleaned up automatically - nothing from it will be committed
|
||||
|
||||
Start by understanding the bug and then systematically work toward a solution.
|
||||
PROMPT_END
|
||||
EOF
|
||||
|
||||
- name: Determine branch strategy
|
||||
run: |
|
||||
BRANCH_NAME="${{ env.BRANCH_NAME }}"
|
||||
if git branch -r --list "origin/${BRANCH_NAME}" | grep -q .; then
|
||||
echo "Branch already exists: $BRANCH_NAME"
|
||||
echo "Will push to existing branch and skip PR creation"
|
||||
echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Creating new branch: $BRANCH_NAME"
|
||||
echo "Will create new PR"
|
||||
echo "BRANCH_EXISTS=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
# Export the branch name
|
||||
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Create scratchpad directory for Claude
|
||||
run: |
|
||||
# Create a scratchpad directory for Claude to use for temporary files
|
||||
mkdir -p .claude-scratchpad
|
||||
echo "Scratchpad directory created for Claude's temporary verification files"
|
||||
|
||||
- name: Generate GitHub App Token for Claude
|
||||
uses: actions/create-github-app-token@v1
|
||||
id: claude-app-token
|
||||
with:
|
||||
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Generate Bug Fix with Claude Code
|
||||
uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
mode: agent
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ steps.claude-app-token.outputs.token }}
|
||||
direct_prompt: ${{ env.BUG_FIX_PROMPT }}
|
||||
timeout_minutes: "25"
|
||||
allowed_tools: "Bash(yarn test-unit*),Bash(yarn lint-eslint-pure),Bash(./bin/mage*),Bash(clojure*),Bash(find*),Bash(ls*),Bash(grep*),Write,Read,Glob,Grep,Edit,MultiEdit"
|
||||
disallowed_tools: "Bash(git commit*),Bash(git push*),Bash(gh*)"
|
||||
|
||||
- name: Clean up scratchpad directory
|
||||
run: |
|
||||
# Remove the scratchpad directory so its contents don't get committed
|
||||
rm -rf .claude-scratchpad/
|
||||
# Remove output file generated by Claude Code action
|
||||
rm -f output.txt
|
||||
echo "Scratchpad directory and action output files cleaned up"
|
||||
|
||||
- name: Check for changes and analysis
|
||||
id: check_changes
|
||||
run: |
|
||||
# Now check for actual code changes (excluding analysis file)
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected:"
|
||||
git status --short
|
||||
else
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes made by Claude."
|
||||
fi
|
||||
|
||||
- name: Get issue team labels and prepare reviewers
|
||||
if: steps.check_changes.outputs.has_changes == 'true'
|
||||
id: prepare_reviewers
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
ISSUE_DATA: ${{ steps.get_issue.outputs.issue_data }}
|
||||
with:
|
||||
script: |
|
||||
const issueData = JSON.parse(process.env.ISSUE_DATA);
|
||||
const issueLabels = issueData.labels.map(label => label.name);
|
||||
const teamLabels = issueLabels.filter(label => label.startsWith('.Team/'));
|
||||
const issueCreator = issueData.user.login;
|
||||
core.setOutput('team_labels', teamLabels.join(','));
|
||||
core.setOutput('reviewers', issueCreator);
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.check_changes.outputs.has_changes == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ env.BRANCH_NAME }}
|
||||
base: master
|
||||
commit-message: |
|
||||
Fix: ${{ env.ISSUE_TITLE }}
|
||||
|
||||
Fixes #${{ env.ISSUE_NUMBER }}
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
committer: "Claude Code[bot] <noreply@anthropic.com>"
|
||||
author: "Claude Code[bot] <noreply@anthropic.com>"
|
||||
title: "Fix: ${{ env.ISSUE_TITLE }}"
|
||||
body: |
|
||||
This PR automatically fixes the bug reported in #${{ env.ISSUE_NUMBER }}.
|
||||
|
||||
## Bug Report
|
||||
**Original Issue:** #${{ env.ISSUE_NUMBER }}
|
||||
**Reporter:** @${{ env.ISSUE_AUTHOR }}
|
||||
**Issue Title:** ${{ env.ISSUE_TITLE }}
|
||||
|
||||
## Automated Fix
|
||||
🤖 This fix was generated automatically by Claude Code based on the issue description.
|
||||
|
||||
**Please review carefully:**
|
||||
- [ ] The fix addresses the reported issue
|
||||
- [ ] Tests pass and code follows conventions
|
||||
- [ ] No unrelated changes were introduced
|
||||
- [ ] The solution is appropriate and maintainable
|
||||
|
||||
## Next Steps
|
||||
- Review the changes and test thoroughly
|
||||
- If the fix looks good, approve and merge
|
||||
- If issues are found, either fix them or close this PR
|
||||
|
||||
---
|
||||
Closes #${{ env.ISSUE_NUMBER }}
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
labels: |
|
||||
${{ steps.prepare_reviewers.outputs.team_labels }}
|
||||
automated-fix
|
||||
ci skip
|
||||
reviewers: ${{ steps.prepare_reviewers.outputs.reviewers }}
|
||||
|
||||
- name: Log existing branch update
|
||||
if: steps.check_changes.outputs.has_changes == 'true' && env.BRANCH_EXISTS == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
console.log('🔄 Updated existing branch: ${{ env.BRANCH_NAME }}');
|
||||
console.log('The changes have been pushed to the existing PR for this issue.');
|
||||
|
||||
- name: Log analysis for no changes
|
||||
if: steps.check_changes.outputs.has_changes == 'false'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
console.log('🤖 No code changes were made by Claude.');
|
||||
21
.github/workflows/claude.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Claude Assistant
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned, labeled]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude-response:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: git config --global --add safe.directory /__w/metabase/metabase
|
||||
- uses: actions/checkout@v4
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
126
.github/workflows/containerize-uberjar.yml
vendored
@@ -1,126 +0,0 @@
|
||||
name: Containerize Uberjar
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
get-container-info:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: Get container info
|
||||
outputs:
|
||||
editions: ${{ steps.ee-info.outputs.editions }}
|
||||
ee: ${{ toJson(fromJson(steps.build-matrix.outputs.result).ee) }}
|
||||
oss: ${{ toJson(fromJson(steps.build-matrix.outputs.result).oss) }}
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Get EE Docker info
|
||||
id: ee-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
edition: ee
|
||||
- name: Get OSS Docker info
|
||||
id: oss-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
edition: oss
|
||||
- name: Build matrix info
|
||||
id: build-matrix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const editions = JSON.parse('${{ steps.ee-info.outputs.editions }}');
|
||||
const result = {
|
||||
editions: editions,
|
||||
ee: {
|
||||
repo: '${{ steps.ee-info.outputs.repo }}',
|
||||
tag: '${{ steps.ee-info.outputs.tag }}'
|
||||
},
|
||||
oss: {
|
||||
repo: '${{ steps.oss-info.outputs.repo }}',
|
||||
tag: '${{ steps.oss-info.outputs.tag }}'
|
||||
}
|
||||
};
|
||||
console.log('Build matrix:', result);
|
||||
return result;
|
||||
|
||||
containerize:
|
||||
needs: [get-container-info]
|
||||
if: needs.get-container-info.result == 'success'
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
uses: ./.github/workflows/containerize-jar.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
artifact-name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
commit: ${{ github.event.inputs.commit || github.sha }}
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
release: "false"
|
||||
build-args: |
|
||||
GIT_COMMIT_SHA=${{ github.event.inputs.commit || github.sha }}
|
||||
|
||||
run-trivy:
|
||||
needs: [get-container-info, containerize]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Trivy vulnerability scanner
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit || github.sha }}
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.29.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
with:
|
||||
image-ref: docker.io/${{ env.repo }}:${{ env.tag }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: "trivy-results.sarif"
|
||||
|
||||
post-comment:
|
||||
needs: [get-container-info, containerize]
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-22.04
|
||||
name: Post PR comment
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Get Docker info for comment
|
||||
id: docker-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
branch: ${{ github.head_ref || github.ref_name }}
|
||||
edition: ee
|
||||
|
||||
- name: Post PR comment
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
header: docker-build-status
|
||||
message: |
|
||||
✅ Docker build completed for commit ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
The uberjar has been built and containerized successfully.
|
||||
|
||||
**Branch:** `${{ github.head_ref || github.ref_name }}`
|
||||
**Docker Image:** `${{ steps.docker-info.outputs.full_image }}`
|
||||
**Docker Hub:** [View on Docker Hub](https://hub.docker.com/r/${{ steps.docker-info.outputs.repo }}/tags?name=${{ steps.docker-info.outputs.tag }})
|
||||
**Triggered by:** @${{ github.actor }}
|
||||
|
||||
Pull the image:
|
||||
```bash
|
||||
docker pull ${{ steps.docker-info.outputs.full_image }}
|
||||
```
|
||||
@@ -4,53 +4,39 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- enterprise/frontend/src/embedding-sdk/**
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
frontend_embedding_sources: ${{ steps.changes.outputs.frontend_embedding_sources }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v3.0.0
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
pr-title-reminder:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
pull-requests: write
|
||||
needs: [ files-changed ]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.files-changed.outputs.frontend_embedding_sources == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Check if the PR title is already following Conventional Commits style
|
||||
uses: actions/github-script@v7
|
||||
id: is-conventional-commit
|
||||
with:
|
||||
result-encoding: string
|
||||
script: | # js
|
||||
const { isConventionalTitle } = require(".github/scripts/conventional-commit-pr-title-reminder/utils.js")
|
||||
const pullRequestTitle = context.payload.pull_request.title
|
||||
const conventionalCommitRegex = /^(?<type>\w+)\((?<scope>\w+)\):/
|
||||
const match = pullRequestTitle.match(conventionalCommitRegex)
|
||||
if (match) {
|
||||
const { type, scope } = match.groups
|
||||
return ['feat', 'fix', 'perf', 'docs', 'style', 'refactor', 'test', 'build', 'ci'].includes(type) && scope === 'sdk'
|
||||
}
|
||||
|
||||
return isConventionalTitle(pullRequestTitle)
|
||||
- name: Checkout repository so `gh` CLI works
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Remind PR authors to use conventional commit in the title
|
||||
if: ${{ steps.is-conventional-commit.outputs.result != 'true' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const { updateCommentForEmbedding } = require(".github/scripts/conventional-commit-pr-title-reminder/utils.js")
|
||||
|
||||
await updateCommentForEmbedding({github, context})
|
||||
script: |
|
||||
const { updateComment } = require(".github/scripts/conventional-commit-pr-title-reminder/utils.js")
|
||||
await updateComment({github, context})
|
||||
|
||||
182
.github/workflows/docs-generate-base.yml
vendored
@@ -1,182 +0,0 @@
|
||||
# .github/workflows/reusable-doc-update.yml
|
||||
name: Reusable - Update Documentation
|
||||
|
||||
# This workflow is designed to be called by other workflows.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
target_branch:
|
||||
description: "The branch to check out and create a PR against"
|
||||
required: true
|
||||
type: string
|
||||
m2_cache_key_suffix:
|
||||
description: "A unique suffix for the Maven cache key"
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
automation_token:
|
||||
description: "A token with permissions to create branches and PRs"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-docs:
|
||||
name: Update documentation for ${{ inputs.target_branch }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.automation_token }}
|
||||
ref: ${{ inputs.target_branch }}
|
||||
|
||||
- name: Prepare backend environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: "auto-update-docs-${{ inputs.m2_cache_key_suffix }}"
|
||||
|
||||
- name: Generate environment variables documentation
|
||||
id: generate_env_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
# Ensure we're on the target branch for documentation generation
|
||||
git checkout ${{ inputs.target_branch }}
|
||||
echo "Generating environment variables documentation from branch: ${{ inputs.target_branch }}"
|
||||
clojure -M:ee:doc environment-variables-documentation
|
||||
continue-on-error: false
|
||||
|
||||
- name: Generate config template documentation
|
||||
id: generate_config_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
echo "Generating config template documentation..."
|
||||
clojure -M:ee:doc config-template
|
||||
continue-on-error: false
|
||||
|
||||
- name: Generate API documentation
|
||||
id: generate_api_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
echo "Generating API documentation..."
|
||||
clojure -M:ee:doc api-documentation
|
||||
continue-on-error: false
|
||||
|
||||
- name: Check for changes
|
||||
id: check_changes
|
||||
run: |
|
||||
if git diff --quiet docs/; then
|
||||
echo "changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes detected in docs directory"
|
||||
else
|
||||
echo "changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected in docs directory"
|
||||
fi
|
||||
|
||||
- name: Create branch and commit changes
|
||||
id: commit_and_push
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
|
||||
BRANCH_NAME="docs/auto-update-${{ inputs.target_branch }}-$(date +%Y-%m-%d-%H%M%S)"
|
||||
echo "Creating branch: $BRANCH_NAME"
|
||||
|
||||
# Create and switch to new branch from current target branch
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add docs/
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git commit -m "Update generated docs (${{ inputs.target_branch }})" --no-verify
|
||||
git push -u origin "$BRANCH_NAME"
|
||||
|
||||
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
echo "Successfully created and pushed branch"
|
||||
|
||||
- name: Create pull request
|
||||
id: create_pr
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.automation_token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
CHANGES_SUMMARY=$(git diff --name-only HEAD~1 docs/ 2>/dev/null | head -10 | sed 's/^/- /' || echo "- No specific files detected")
|
||||
TOTAL_CHANGES=$(git diff --name-only HEAD~1 docs/ 2>/dev/null | wc -l || echo "0")
|
||||
BRANCH_NAME="${{ steps.commit_and_push.outputs.branch_name }}"
|
||||
|
||||
echo "Creating PR with branch: $BRANCH_NAME"
|
||||
echo "Changes detected: $TOTAL_CHANGES files"
|
||||
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i of 3..."
|
||||
if gh pr create \
|
||||
--base "${{ inputs.target_branch }}" \
|
||||
--head "$BRANCH_NAME" \
|
||||
--title "Auto-update documentation for ${{ inputs.target_branch }}" \
|
||||
--body "This PR contains automatically generated documentation updates.
|
||||
|
||||
## Changes detected
|
||||
The following documentation files were updated:
|
||||
$CHANGES_SUMMARY
|
||||
$([ "$TOTAL_CHANGES" -gt 10 ] && echo "- ... and $((TOTAL_CHANGES - 10)) more files")
|
||||
|
||||
## Generation commands
|
||||
Documentation was generated using:
|
||||
- \`clojure -M:ee:doc environment-variables-documentation\`
|
||||
- \`clojure -M:ee:doc config-template\`
|
||||
- \`clojure -M:ee:doc api-documentation\`
|
||||
|
||||
Please review the changes and merge if they look correct." \
|
||||
--label "Type:Documentation" \
|
||||
--label "no-backport" \
|
||||
--reviewer "metabase/tech-writers"; then
|
||||
echo "PR created successfully on attempt $i"
|
||||
break
|
||||
else
|
||||
echo "PR creation failed on attempt $i"
|
||||
if [ $i -eq 3 ]; then
|
||||
echo "All attempts failed. Exiting with error."
|
||||
exit 1
|
||||
fi
|
||||
echo "Waiting 10 seconds before retry..."
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Skip PR creation
|
||||
if: steps.check_changes.outputs.changes == 'false'
|
||||
run: |
|
||||
echo "No documentation changes detected, skipping PR creation"
|
||||
|
||||
- name: Workflow summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ steps.check_changes.outputs.changes }}" == "true" ]; then
|
||||
if [ "${{ steps.commit_and_push.outcome }}" == "success" ]; then
|
||||
if [ "${{ steps.create_pr.outcome }}" == "success" ]; then
|
||||
echo "## ✅ Documentation Updated Successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ steps.commit_and_push.outputs.branch_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- PR created targeting **${{ inputs.target_branch }}**" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "## ⚠️ Branch Created but PR Failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ steps.commit_and_push.outputs.branch_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Manual PR creation required" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "## ❌ Failed to Create Branch" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Check workflow logs for details" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "## ℹ️ No Changes Detected" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Documentation is up to date on **${{ inputs.target_branch }}**" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
36
.github/workflows/docs-links.yml
vendored
@@ -1,36 +0,0 @@
|
||||
name: Check doc links
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
link-checker:
|
||||
name: Check documentation links
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
docs
|
||||
.lychee
|
||||
|
||||
- name: Cache lychee
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/lychee
|
||||
key: lychee-${{ runner.os }}-${{ hashFiles('.lychee/config.toml') }}
|
||||
|
||||
- name: Run link checker
|
||||
id: link-check
|
||||
uses: lycheeverse/lychee-action@v2
|
||||
with:
|
||||
fail: true
|
||||
args: docs --config ./.lychee/config.toml --offline
|
||||
format: markdown
|
||||
16
.github/workflows/docs-master-generate.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: Auto-update documentation (master)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 1 * * 1-5" # Every Monday through Friday at 1 AM UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-master-docs:
|
||||
name: Call documentation update for master
|
||||
uses: ./.github/workflows/docs-generate-base.yml
|
||||
with:
|
||||
target_branch: "master"
|
||||
m2_cache_key_suffix: "master"
|
||||
secrets:
|
||||
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
16
.github/workflows/docs-release-generate.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: Auto-update documentation (release)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * 1-5" # Every Monday through Friday at 2 AM UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-release-docs:
|
||||
name: Call documentation update for release branch
|
||||
uses: ./.github/workflows/docs-generate-base.yml
|
||||
with:
|
||||
target_branch: "release-x.56.x"
|
||||
m2_cache_key_suffix: "release"
|
||||
secrets:
|
||||
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
43
.github/workflows/drivers-stress-test.yml
vendored
@@ -689,25 +689,24 @@ jobs:
|
||||
junit-name: 'be-tests-starburst-ee'
|
||||
test-args: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# be-tests-vertica-ee:
|
||||
# if: ${{ false && inputs.driver == 'Vertica' }}
|
||||
# runs-on: ubuntu-22.04
|
||||
# timeout-minutes: 90
|
||||
# env:
|
||||
# CI: 'true'
|
||||
# DRIVERS: vertica
|
||||
# services:
|
||||
# vertica:
|
||||
# image: vertica/vertica-ce:12.0.2-0
|
||||
# ports:
|
||||
# - "5433:5433"
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - 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: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
be-tests-vertica-ee:
|
||||
if: inputs.driver == 'Vertica'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: vertica
|
||||
services:
|
||||
vertica:
|
||||
image: vertica/vertica-ce:12.0.2-0
|
||||
ports:
|
||||
- "5433:5433"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
|
||||
205
.github/workflows/drivers.yml
vendored
@@ -21,17 +21,11 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Fetch base branch
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.base.ref != ''
|
||||
run: |
|
||||
# Fetch the base branch to ensure its history is available for diffing
|
||||
git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }}
|
||||
# Only run this if it's a pull request and the base ref exists
|
||||
- name: Check if tier3 drivers should run
|
||||
id: check_team_and_branch
|
||||
run: |
|
||||
IS_MASTER_OR_RELEASE="${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-') }}"
|
||||
HAS_TEAM_LABEL="${{ contains(github.event.pull_request.labels.*.name, '.Team/Drivers') || contains(github.event.pull_request.labels.*.name, '.Team/Querying') || contains(github.event.pull_request.labels.*.name, '.Team/SemanticLayer') || contains(github.event.pull_request.labels.*.name, '.Team/DevEx') }}"
|
||||
HAS_TEAM_LABEL="${{ contains(github.event.pull_request.labels.*.name, '.Team/Drivers') || contains(github.event.pull_request.labels.*.name, '.Team/Querying') || contains(github.event.pull_request.labels.*.name, '.Team/SemanticLayer') }}"
|
||||
|
||||
|
||||
echo "Is master or release: ${IS_MASTER_OR_RELEASE}"
|
||||
@@ -43,25 +37,8 @@ jobs:
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
echo "A relevant team label is present. Tier 3 driver tests will run."
|
||||
else
|
||||
echo "Checking for changes in relevant folders..."
|
||||
CHANGED_FILES=$(git diff --name-only $(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.sha }}) ${{ github.sha }})
|
||||
|
||||
# Initialize an empty array to store folders with changes
|
||||
CHANGED_FOLDERS=()
|
||||
for folder in "src/metabase/lib" "src/metabase/query_processor" "modules/drivers" "src/metabase/driver"; do
|
||||
if echo "$CHANGED_FILES" | grep -q "$folder"; then
|
||||
CHANGED_FOLDERS+=("$folder")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#CHANGED_FOLDERS[@]} -gt 0 ]]; then
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected in the following folders: ${CHANGED_FOLDERS[*]}."
|
||||
echo "Tier 3 driver tests will run."
|
||||
else
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "No relevant team label, not merging into master/release, and no changes in relevant folders. Tier 3 driver tests will be skipped."
|
||||
fi
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
echo "Not labeled with required team and not merging into master/release. Tier 3 driver tests will be skipped."
|
||||
fi
|
||||
shell: bash
|
||||
be-tests-athena-ee:
|
||||
@@ -73,11 +50,9 @@ jobs:
|
||||
CI: 'true'
|
||||
DRIVERS: athena
|
||||
MB_ATHENA_TEST_REGION: us-east-1
|
||||
MB_ATHENA_TEST_REGION_ROUTING: us-east-2
|
||||
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 }}
|
||||
MB_ATHENA_TEST_S3_STAGING_DIR_ROUTING: ${{ secrets.MB_ATHENA_TEST_S3_STAGING_DIR_ROUTING }}
|
||||
# These credentials are used to test the driver when the user does not have the athena:GetTableMetadata permission
|
||||
MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_ACCESS_KEY: ${{ secrets.MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_ACCESS_KEY }}
|
||||
MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY: ${{ secrets.MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY }}
|
||||
@@ -268,7 +243,6 @@ jobs:
|
||||
MB_DATABRICKS_TEST_HTTP_PATH: ${{ secrets.MB_DATABRICKS_JDBC_TEST_HTTP_PATH }}
|
||||
MB_DATABRICKS_TEST_TOKEN: ${{ secrets.MB_DATABRICKS_JDBC_TEST_TOKEN }}
|
||||
MB_DATABRICKS_TEST_CATALOG: 'metabase_ci'
|
||||
MB_DATABRICKS_TEST_CATALOG_ROUTING: 'metabase_routing_catalog'
|
||||
MB_DATABRICKS_TEST_CLIENT_ID: ${{ secrets.MB_DATABRICKS_JDBC_TEST_CLIENT_ID }}
|
||||
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
|
||||
name: Databricks
|
||||
@@ -305,7 +279,6 @@ jobs:
|
||||
MB_DATABRICKS_TEST_HTTP_PATH: ${{ secrets.MB_DATABRICKS_JDBC_TEST_HTTP_PATH }}
|
||||
MB_DATABRICKS_TEST_TOKEN: ${{ secrets.MB_DATABRICKS_JDBC_TEST_TOKEN }}
|
||||
MB_DATABRICKS_TEST_CATALOG: 'metabase_ci'
|
||||
MB_DATABRICKS_TEST_CATALOG_ROUTING: 'metabase_routing_catalog'
|
||||
MB_DATABRICKS_TEST_CLIENT_ID: ${{ secrets.MB_DATABRICKS_JDBC_TEST_CLIENT_ID }}
|
||||
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
|
||||
name: Databricks (Multi-Catalog)
|
||||
@@ -338,12 +311,6 @@ jobs:
|
||||
name: H2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run
|
||||
- name: Test H2 driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -448,12 +415,6 @@ jobs:
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -757,12 +718,6 @@ jobs:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run
|
||||
- name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -876,7 +831,6 @@ jobs:
|
||||
DRIVERS: redshift
|
||||
MB_REDSHIFT_TEST_USER: metabase_ci
|
||||
MB_REDSHIFT_TEST_DB: testdb
|
||||
MB_REDSHIFT_TEST_DB_ROUTING: dev
|
||||
MB_REDSHIFT_TEST_HOST: ${{ secrets.MB_REDSHIFT_TEST_HOST }}
|
||||
MB_REDSHIFT_TEST_PASSWORD: ${{ secrets.MB_REDSHIFT_TEST_PASSWORD }}
|
||||
name: ${{ matrix.job.name }}
|
||||
@@ -1058,81 +1012,79 @@ jobs:
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
# TODO(dpsutton, 2025-08-20): Re-enable starburst when we figure out why it randomly dies in CI
|
||||
# be-tests-starburst-ee:
|
||||
# needs: determine-driver-skips
|
||||
# if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
# runs-on: ubuntu-22.04
|
||||
# timeout-minutes: 60
|
||||
# env:
|
||||
# CI: 'true'
|
||||
# DRIVERS: starburst
|
||||
# services:
|
||||
# starburst:
|
||||
# image: trinodb/trino:latest
|
||||
# env:
|
||||
# CATALOG_MANAGEMENT: dynamic
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
# name: Starburst
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Make plugins directory
|
||||
# run: mkdir plugins
|
||||
# - name: Test Starburst driver
|
||||
# uses: ./.github/actions/test-driver
|
||||
# with:
|
||||
# junit-name: 'be-tests-starburst-ee'
|
||||
# test-args: >-
|
||||
# :only-tags [:mb/driver-tests]
|
||||
# - name: Upload Test Results
|
||||
# uses: ./.github/actions/upload-test-results
|
||||
# if: always()
|
||||
# with:
|
||||
# input-path: ./target/junit/
|
||||
# output-name: ${{ github.job }}
|
||||
# bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
# aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
# aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
# aws-region: ${{ vars.AWS_REGION }}
|
||||
# trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
be-tests-starburst-ee:
|
||||
needs: determine-driver-skips
|
||||
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: starburst
|
||||
services:
|
||||
starburst:
|
||||
image: trinodb/trino:latest
|
||||
env:
|
||||
CATALOG_MANAGEMENT: dynamic
|
||||
ports:
|
||||
- "8080:8080"
|
||||
name: Starburst
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Make plugins directory
|
||||
run: mkdir plugins
|
||||
- name: Test Starburst driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-starburst-ee'
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# be-tests-vertica-ee:
|
||||
# needs: determine-driver-skips
|
||||
# if: ${{ false && !inputs.skip && !(needs.determine-driver-skips.outputs.skip == '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"
|
||||
# name: Vertica
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - 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: >-
|
||||
# :only-tags [:mb/driver-tests]
|
||||
# - name: Upload Test Results
|
||||
# uses: ./.github/actions/upload-test-results
|
||||
# if: always()
|
||||
# with:
|
||||
# input-path: ./target/junit/
|
||||
# output-name: ${{ github.job }}
|
||||
# bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
# aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
# aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
# aws-region: ${{ vars.AWS_REGION }}
|
||||
# trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
be-tests-vertica-ee:
|
||||
needs: determine-driver-skips
|
||||
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == '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"
|
||||
name: Vertica
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
drivers-tests-result:
|
||||
needs:
|
||||
@@ -1155,9 +1107,8 @@ jobs:
|
||||
- be-tests-sparksql-ee
|
||||
- be-tests-sqlite-ee
|
||||
- be-tests-sqlserver
|
||||
# - be-tests-starburst-ee
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# - be-tests-vertica-ee
|
||||
- be-tests-starburst-ee
|
||||
- be-tests-vertica-ee
|
||||
- be-tests-clickhouse-ee
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
@@ -1179,7 +1130,7 @@ jobs:
|
||||
}));
|
||||
|
||||
// are all jobs skipped or successful?
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success' || job.name == 'be-tests-starburst-ee'))) {
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success'))) {
|
||||
console.log("");
|
||||
console.log(" _------. ");
|
||||
console.log(" / , \_ ");
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
# Thi workflow does the backward compatibility tests
|
||||
# between the Embedding SDK package of version N and Embedding SDK Bundle of version N - 1
|
||||
# N - 1 is a target of a PR
|
||||
name: Embedding SDK backward-compatibility E2E Component Tests
|
||||
name: E2E Cross-version Component Tests for Embedding SDK
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cached-embedding-sdk-dist-artifact-name:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: "SDK backward-compatibility E2E > Check which files changed"
|
||||
name: "SDK cross-version E2E > Check which files changed"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
|
||||
e2e_all: ${{ steps.changes.outputs.e2e_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
@@ -26,31 +19,11 @@ jobs:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
decide-target-ref:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
target-ref: ${{ steps.get-target-ref.outputs.value }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Decide ref to checkout
|
||||
id: get-target-ref
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
echo "value=${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "value=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
name: "SDK backward-compatibility E2E > [Backport only] Get build requirements"
|
||||
needs: [decide-target-ref]
|
||||
name: "SDK cross-version E2E > [Backport only] Get build requirements"
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.base_ref || github.ref, 'release-x')
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
@@ -59,7 +32,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
@@ -82,12 +54,76 @@ jobs:
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
e2e-tests:
|
||||
name: "SDK backward-compatibility E2E > Run e2e tests"
|
||||
needs: [files-changed, decide-target-ref, get-build-requirements]
|
||||
build:
|
||||
name: "SDK cross-version E2E > Build uberjar"
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.files-changed.outputs.e2e_embedding_sdk == 'true'
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
INTERACTIVE: false
|
||||
# make sure that builds on release branches get licenses, because we use them for releases
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 11 }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-cross-version
|
||||
|
||||
resolve-sdk-version:
|
||||
name: "SDK cross-version E2E > Resolve SDK version"
|
||||
if: |
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
sdk_version: ${{ fromJson(steps.dependencies.outputs.result).sdk_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get latest SDK release for this branch
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getSdkVersionFromReleaseBranchName } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const branchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const sdk_version = await getSdkVersionFromReleaseBranchName({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
branchName,
|
||||
});
|
||||
|
||||
return {
|
||||
sdk_version,
|
||||
};
|
||||
|
||||
e2e-tests:
|
||||
name: "SDK cross-version E2E > Run e2e tests"
|
||||
needs: [get-build-requirements, build, resolve-sdk-version]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
@@ -106,33 +142,45 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
# Needed to omit newly added tests for functionality that is not yet released
|
||||
- name: Sparse checkout tests from SDK release commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
|
||||
ref: embedding-sdk-${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
path: sdk-release-e2e
|
||||
sparse-checkout: e2e
|
||||
|
||||
- name: Move tests from the release commit into the repo
|
||||
run: |
|
||||
rm -rf ./e2e/support/*
|
||||
mv ./sdk-release-e2e/e2e/support/* ./e2e/support
|
||||
|
||||
rm -rf ./e2e/test-component/*
|
||||
mv ./sdk-release-e2e/e2e/test-component/* ./e2e/test-component
|
||||
shell: bash
|
||||
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-cross-version
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
- name: Retrieve Embedding SDK dist artifact
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Prepare JDK ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
name: ${{ inputs.cached-embedding-sdk-dist-artifact-name }}
|
||||
path: ${{ github.workspace }}/resources/embedding-sdk
|
||||
java-version: ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Install Embedding SDK package v${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
run: yarn add @metabase/embedding-sdk-react@${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
|
||||
- name: Run Metabase
|
||||
run: node e2e/runner/run_cypress_ci.js start
|
||||
|
||||
@@ -140,10 +188,7 @@ jobs:
|
||||
run: node e2e/runner/run_cypress_ci.js snapshot --browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run component tests for Embedding SDK
|
||||
run: |
|
||||
node e2e/runner/run_cypress_ci.js component \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }} \
|
||||
--env grepTags="-@skip-backward-compatibility",grepOmitFiltered=true
|
||||
run: node e2e/runner/run_cypress_ci.js component --browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
162
.github/workflows/e2e-cross-version-for-breaking-changes.yml
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
name: E2E cross-version for breaking changes
|
||||
|
||||
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
fe-ref:
|
||||
description: "Frontend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
default: "master"
|
||||
be-ref:
|
||||
description: "Backend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
default: "master"
|
||||
total-shards:
|
||||
description: "Total number of parallel test shards"
|
||||
type: number
|
||||
required: false
|
||||
default: 4
|
||||
workflow_call:
|
||||
inputs:
|
||||
fe-ref:
|
||||
description: "Frontend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
be-ref:
|
||||
description: "Backend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
total-shards:
|
||||
description: "Total number of parallel test shards"
|
||||
type: number
|
||||
required: false
|
||||
default: 4
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
name: "Breaking changes E2E > Generate matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix_json: ${{ steps.set_matrix.outputs.matrix_json }}
|
||||
shards_total: ${{ steps.set_matrix.outputs.shards_total }}
|
||||
steps:
|
||||
- name: Set up shard matrix
|
||||
id: set_matrix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
# generate an output like `{"matrixJson": "{\"shard\": [1, 2, 3, 4]}", "shardsTotal": 4}` to be used in the other jobs
|
||||
script: |
|
||||
const totalShards = parseInt(process.env.TOTAL_SHARDS_INPUT, 10);
|
||||
|
||||
const matrix = { shard: Array.from({ length: totalShards }, (_, i) => i + 1) };
|
||||
|
||||
console.log("Generated matrix JSON", matrix);
|
||||
console.log(`Total shards: ${totalShards}`);
|
||||
|
||||
core.setOutput('matrix_json', JSON.stringify(matrix));
|
||||
core.setOutput('shards_total', totalShards);
|
||||
env:
|
||||
TOTAL_SHARDS_INPUT: ${{ inputs.total-shards }}
|
||||
|
||||
build-jar:
|
||||
name: "Breaking changes E2E > Build jar"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Node.js
|
||||
# We're not using `actions/prepare-frontend` because we don't want to install deps from the root repo
|
||||
# nor we want to touch the cache as we'll be potentially be installing different versions of packages
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: cross-version-uberjar
|
||||
|
||||
- name: Build jar with different frontend and backend version
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
CYPRESS_CI: true
|
||||
run: |
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
build
|
||||
|
||||
- name: Upload Uberjar
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metabase-jar-cross-version
|
||||
path: .tmp/metabase-be/target/uberjar/metabase.jar
|
||||
if-no-files-found: error
|
||||
|
||||
run-breaking-changes-tests:
|
||||
name: "Breaking changes E2E > Run breaking changes tests"
|
||||
needs: [build-jar, generate-matrix]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
TOTAL_SHARDS: ${{ needs.generate-matrix.outputs.shards_total }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix_json) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: cross-version-uberjar
|
||||
|
||||
- name: Download Uberjar
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-jar-cross-version
|
||||
path: .tmp/metabase-be/target/uberjar/
|
||||
|
||||
- name: Download FE repo
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ inputs.fe-ref }} https://github.com/metabase/metabase.git .tmp/metabase-fe
|
||||
|
||||
- name: Install FE dependencies
|
||||
working-directory: .tmp/metabase-fe
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
with:
|
||||
working-directory: .tmp/metabase-fe
|
||||
|
||||
- name: Run the tests
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
|
||||
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
|
||||
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
|
||||
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
|
||||
CYPRESS_CI: true
|
||||
run: |
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
start > /dev/null & \
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
test ${{ matrix.shard}}/${{ env.TOTAL_SHARDS }}
|
||||
@@ -1,15 +1,20 @@
|
||||
name: "[NOT REQUIRED] SDK Compatibility tests"
|
||||
|
||||
# Note: these are currently never called, we're skipping them as they're failing, below is the original triggers
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "release-**"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- "master"
|
||||
- "release-**"
|
||||
workflow_call:
|
||||
|
||||
# Original trigger (commented for reference):
|
||||
# on:
|
||||
# push:
|
||||
# branches:
|
||||
# - "master"
|
||||
# - "release-**"
|
||||
# pull_request:
|
||||
# types: [opened, synchronize, reopened]
|
||||
# branches:
|
||||
# - "master"
|
||||
# - "release-**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
@@ -178,8 +183,12 @@ jobs:
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Compile CLJS
|
||||
run: yarn build-pure:cljs
|
||||
shell: bash
|
||||
|
||||
- name: Build Embedding SDK package
|
||||
run: yarn build-embedding-sdk-package
|
||||
run: yarn build-embedding-sdk
|
||||
|
||||
- name: Prepare Embedding SDK artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -192,7 +201,7 @@ jobs:
|
||||
# - starts it
|
||||
# - runs its Cypress tests against the local metabase.jar and local @metabase/embedding-sdk-react package.
|
||||
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
|
||||
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
e2e-sample-apps-tests:
|
||||
needs: [get-build-requirements, get-sample-apps-data, build]
|
||||
strategy:
|
||||
@@ -316,7 +325,7 @@ jobs:
|
||||
# - starts an app
|
||||
# - runs its Cypress tests against the e2e test metabase instance and local @metabase/embedding-sdk-react package.
|
||||
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
|
||||
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
e2e-host-apps-tests:
|
||||
needs: [get-build-requirements, build]
|
||||
strategy:
|
||||
|
||||
8
.github/workflows/e2e-test.yml
vendored
@@ -79,11 +79,9 @@ jobs:
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ inputs.edition }}
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ inputs.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
@@ -131,7 +129,7 @@ jobs:
|
||||
run: |
|
||||
echo "Running tests with specs: $SPEC_PATH"
|
||||
node e2e/runner/run_cypress_ci.js e2e \
|
||||
--env grepTags="-@mongo+-@flaky+-@OSS+-@skip",grepOmitFiltered=true \
|
||||
--env grepTags="-@mongo+-@flaky+-@OSS --@quarantine",grepOmitFiltered=true \
|
||||
--spec "$SPEC_PATH" \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
@@ -143,7 +141,7 @@ jobs:
|
||||
run: |
|
||||
echo "Running tests with specs: $SPEC_PATH"
|
||||
node e2e/runner/run_cypress_ci.js e2e \
|
||||
--env grepTags="${{inputs.tags}}+-@skip",grepOmitFiltered=true \
|
||||
--env grepTags="${{inputs.tags}} --@quarantine",grepOmitFiltered=true \
|
||||
--spec "$SPEC_PATH" \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
|
||||
80
.github/workflows/e2e-tests.yml
vendored
@@ -22,6 +22,72 @@ jobs:
|
||||
chunks: 50
|
||||
specs: ${{ inputs.specs }}
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getBuildRequirements, getVersionFromReleaseBranch } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const version = getVersionFromReleaseBranch('${{ github.ref }}');
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
needs: [get-build-requirements]
|
||||
if: ${{ !cancelled() && !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
INTERACTIVE: false
|
||||
# make sure that builds on release branches get licenses, because we use them for releases
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
timeout-minutes: 10
|
||||
run: ./bin/build.sh
|
||||
shell: bash
|
||||
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
reset-e2e-test-comment:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
@@ -58,8 +124,9 @@ jobs:
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs:
|
||||
- e2e-matrix-builder
|
||||
- build
|
||||
if: |
|
||||
!cancelled() && !inputs.skip
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
@@ -78,10 +145,11 @@ jobs:
|
||||
name: Flaky e2e Tests
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs:
|
||||
- build
|
||||
- e2e-matrix-builder
|
||||
# skip flaky test run if only e2e specs changed as an optimization
|
||||
if: |
|
||||
!cancelled() && !inputs.skip && needs.e2e-matrix-builder.outputs.isDefaultSpecPattern == 'true'
|
||||
!cancelled() && needs.build.result == 'success' && needs.e2e-matrix-builder.outputs.isDefaultSpecPattern == 'true'
|
||||
secrets: inherit
|
||||
with:
|
||||
name: Flaky
|
||||
@@ -113,3 +181,11 @@ jobs:
|
||||
echo "E2E Tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pr-env:
|
||||
needs: [build]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.event.pull_request.labels.*.name, 'PR-Env')
|
||||
uses: ./.github/workflows/pr-env.yml
|
||||
secrets: inherit
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
name: Embedding SDK Labels Reminder
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [auto_merge_enabled, review_requested, labeled, unlabeled, synchronize]
|
||||
branches:
|
||||
- "master"
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
frontend_embedding_sdk_package_sources: ${{ steps.changes.outputs.frontend_embedding_sdk_package_sources }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v3.0.0
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
embedding-sdk-package-no-release-notes-reminder:
|
||||
needs: [ files-changed ]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(needs.files-changed.outputs.frontend_embedding_sdk_package_sources == 'true')
|
||||
name: Embedding SDK package release-notes/no-release-notes label reminder
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jesusvasquez333/verify-pr-label-action@v1.4.0
|
||||
id: verify-release-notes-labels
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
valid-labels: 'release-notes, no-release-notes'
|
||||
disable-reviews: true
|
||||
- name: Comment on PR if label should be added
|
||||
if: ${{ always() }}
|
||||
uses: ./.github/actions/notify-pull-request
|
||||
with:
|
||||
remove-previous-comment: true
|
||||
add-new-comment: ${{ steps.verify-release-notes-labels.outcome == 'failure' }}
|
||||
message: "⚠️ Changes were made to the <b>Embedding SDK Package</b>. Review this PR and apply one of the following labels.<br><br>- <code>release-notes</code> — select if this PR must be included in the main Metabase changelog release notes.<br>- <code>no-release-notes</code> — select if this PR should not be included in the main Metabase changelog release notes."
|
||||
include-log: true
|
||||
29
.github/workflows/embedding-sdk.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
with:
|
||||
m2-cache-key: "cljs"
|
||||
- name: Build Embedding SDK package
|
||||
run: yarn build-embedding-sdk-package
|
||||
run: yarn build-embedding-sdk
|
||||
- name: Prepare Embedding SDK artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
if: ${{ steps.docs-generation.outcome == 'failure' }}
|
||||
run: exit 1
|
||||
|
||||
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
sdk-e2e-tests:
|
||||
name: "SDK e2e tests"
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk.yml
|
||||
@@ -146,13 +146,24 @@ jobs:
|
||||
with:
|
||||
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
e2e-component-tests-embedding-sdk-backward-compatibility:
|
||||
name: "SDK e2e backward compatibility tests"
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-backward-compatibility.yml
|
||||
needs: [build]
|
||||
e2e-component-tests-embedding-sdk-cross-version:
|
||||
name: "[Backport only] SDK e2e cross version tests"
|
||||
# run on: every push on release branches, and every pr that targets a release branch
|
||||
if: ${{ startsWith(github.ref, 'refs/heads/release-x.') || (github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.')) }}
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-cross-version.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
# Temporarily skipped because the cypress runner crashes
|
||||
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
|
||||
# cross-version-for-breaking-changes:
|
||||
# name: "[NOT REQUIRED - Experimental - Backport only] detect breaking changes with cross versions tests"
|
||||
# # run on: every pr that targets a release branch, it does NOT run for pr targeting master
|
||||
# if: ${{ github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.') }}
|
||||
# uses: ./.github/workflows/e2e-cross-version-for-breaking-changes.yml
|
||||
# secrets: inherit
|
||||
# with:
|
||||
# fe-ref: ${{ github.base_ref }}
|
||||
# be-ref: ${{ github.head_ref }}
|
||||
|
||||
embedding-sdk-tests-result:
|
||||
needs:
|
||||
@@ -160,7 +171,7 @@ jobs:
|
||||
- embedding-sdk-docs-snippets-type-check
|
||||
- embedding-sdk-api-documentation-generation-validation
|
||||
- sdk-e2e-tests
|
||||
- e2e-component-tests-embedding-sdk-backward-compatibility
|
||||
- e2e-component-tests-embedding-sdk-cross-version
|
||||
if: always() && !cancelled()
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
16
.github/workflows/frontend.yml
vendored
@@ -9,16 +9,6 @@ on:
|
||||
skip-lint:
|
||||
type: boolean
|
||||
default: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skip:
|
||||
description: "Skip main frontend jobs (type-check, unit tests, timezone tests)"
|
||||
type: boolean
|
||||
default: false
|
||||
skip-lint:
|
||||
description: "Skip linting jobs (prettier, eslint, css variables check)"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-frontend
|
||||
@@ -52,8 +42,6 @@ jobs:
|
||||
run: yarn run lint-prettier-pure
|
||||
- name: Run ESLint linter
|
||||
run: yarn run lint-eslint-pure
|
||||
- name: Run CSS linter
|
||||
run: yarn run lint-css
|
||||
|
||||
fe-type-check:
|
||||
if: ${{ !inputs.skip }}
|
||||
@@ -79,7 +67,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [1, 2] # 2 shards for parallel execution
|
||||
shard: [1, 2]
|
||||
env:
|
||||
SHARDS: 2 # should match matrix above
|
||||
JEST_JUNIT_OUTPUT_DIR: ./target/junit
|
||||
@@ -96,7 +84,7 @@ jobs:
|
||||
run: yarn run test-unit --silent --shard=${{ matrix.shard }}/${{ env.SHARDS }}
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always() && github.event_name != 'workflow_dispatch'
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: frontend-unit
|
||||
|
||||
32
.github/workflows/links.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Links
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
|
||||
jobs:
|
||||
linkChecker:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write # required for peter-evans/create-issue-from-file
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Link Checker
|
||||
id: lychee
|
||||
uses: lycheeverse/lychee-action@v2
|
||||
with:
|
||||
fail: false
|
||||
args: docs --include-fragments --config ./.lychee/config.toml --verbose --no-progress
|
||||
format: markdown
|
||||
|
||||
- name: Create Issue From File
|
||||
if: steps.lychee.outputs.exit_code != 0
|
||||
uses: peter-evans/create-issue-from-file@v5
|
||||
with:
|
||||
title: Link Checker Report
|
||||
content-filepath: ./.lychee/out.md
|
||||
labels: "Type:Documentation"
|
||||
assignees: jeff-bruemmer
|
||||
1
.github/workflows/optimize-images.yml
vendored
@@ -13,7 +13,6 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install pngcrush and bc
|
||||
|
||||
8
.github/workflows/perf-test-labeled.yml
vendored
@@ -9,13 +9,9 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
uberjar:
|
||||
if: ${{ github.event.label.name == 'Run-perf' }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
run-perf-test:
|
||||
needs: [uberjar]
|
||||
if: ${{ github.event.label.name == 'Run-perf' }}
|
||||
uses: ./.github/workflows/perf-test.yml
|
||||
with:
|
||||
wait_for_uberjar: true
|
||||
secrets: inherit
|
||||
|
||||
68
.github/workflows/perf-test.yml
vendored
@@ -3,6 +3,11 @@ run-name: Run perf test for ${{ github.ref_name }} by @${{ github.actor }}
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
wait_for_uberjar:
|
||||
description: "Wait for uberjar build"
|
||||
required: false
|
||||
type: boolean
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -26,12 +31,69 @@ jobs:
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
with:
|
||||
registries: "${{ secrets.PR_ENV_AWS_ACCOUNT_ID }}"
|
||||
- name: Wait for uberjar
|
||||
id: wait_for_uberjar
|
||||
if: ${{ inputs.wait_for_uberjar == true }}
|
||||
run: |
|
||||
## Get workflow run id for uberjar build
|
||||
curl -Ls --output e2e-tests.json \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/${{ github.repository }}/actions/workflows/run-tests.yml/runs?head_sha=${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ID=$(jq -r '.workflow_runs[0].id' e2e-tests.json)
|
||||
echo "Run ID: ${ID}"
|
||||
|
||||
## Get workflow run id for uberjar build
|
||||
while [ -z "$JOB_ID" ]; do
|
||||
NEXT_URL="https://api.github.com/repos/${{ github.repository }}/actions/runs/${ID}/jobs?filter=latest"
|
||||
|
||||
# Search for build job
|
||||
echo "Searching for build job..."
|
||||
while [ -z "$JOB_ID" ] && [ -n "$NEXT_URL" ]; do
|
||||
# Get one page of jobs
|
||||
RESPONSE=$(curl -s -i \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"$NEXT_URL")
|
||||
|
||||
# Extract headers and body
|
||||
HEADERS=$(echo "$RESPONSE" | sed -n '1,/^\r$/p')
|
||||
BODY=$(echo "$RESPONSE" | sed '1,/^\r$/d')
|
||||
LINK_HEADER=$(echo "$HEADERS" | grep -i '^link:' | sed 's/^link: //')
|
||||
|
||||
# Check for next page in Link header
|
||||
if echo "$LINK_HEADER" | grep -q 'rel="next"'; then
|
||||
NEXT_URL=$(echo "$LINK_HEADER" | sed -E 's/.*<([^>]+)>; rel="next".*/\1/')
|
||||
else
|
||||
NEXT_URL=""
|
||||
fi
|
||||
|
||||
# Check for build job
|
||||
JOB_ID=$(echo "$BODY" | jq -r '.jobs[] | select(.name | contains("build (ee)")) | .id')
|
||||
done
|
||||
done
|
||||
echo "Job ID: ${JOB_ID}"
|
||||
|
||||
## Wait for uberjar build to complete
|
||||
while [ true ]; do
|
||||
curl -Ls --output uberjar.json \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/${{ github.repository }}/actions/jobs/${JOB_ID}
|
||||
jq -r '.steps[] | select(.name == "Prepare uberjar artifact") | .status' uberjar.json | grep -q "completed" && break
|
||||
echo "Waiting for uberjar build..."
|
||||
sleep 10
|
||||
done
|
||||
echo "run_id=$(jq -r '.workflow_runs[0].id' e2e-tests.json)" >> $GITHUB_OUTPUT
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ inputs.wait_for_uberjar && steps.wait_for_uberjar.outputs.run_id || github.run_id }}
|
||||
- name: Move uberjar to bin/docker
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar
|
||||
|
||||
8
.github/workflows/pr-env-labeled.yml
vendored
@@ -9,13 +9,9 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
uberjar:
|
||||
if: ${{ github.event.label.name == 'PR-Env' }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
pr-env:
|
||||
needs: [uberjar]
|
||||
if: ${{ github.event.label.name == 'PR-Env' }}
|
||||
uses: ./.github/workflows/pr-env.yml
|
||||
with:
|
||||
wait_for_uberjar: true
|
||||
secrets: inherit
|
||||
|
||||
72
.github/workflows/pr-env.yml
vendored
@@ -3,6 +3,11 @@ run-name: Building Dynamic PR Environment for ${{ github.ref_name }} by @${{ git
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
wait_for_uberjar:
|
||||
description: "Wait for uberjar build"
|
||||
required: false
|
||||
type: boolean
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -26,12 +31,69 @@ jobs:
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
with:
|
||||
registries: "${{ secrets.PR_ENV_AWS_ACCOUNT_ID }}"
|
||||
- name: Wait for uberjar
|
||||
id: wait_for_uberjar
|
||||
if: ${{ inputs.wait_for_uberjar == true }}
|
||||
run: |
|
||||
## Get workflow run id for uberjar build
|
||||
curl -Ls --output e2e-tests.json \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/${{ github.repository }}/actions/workflows/run-tests.yml/runs?head_sha=${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ID=$(jq -r '.workflow_runs[0].id' e2e-tests.json)
|
||||
echo "Run ID: ${ID}"
|
||||
|
||||
## Get workflow run id for uberjar build
|
||||
while [ -z "$JOB_ID" ]; do
|
||||
NEXT_URL="https://api.github.com/repos/${{ github.repository }}/actions/runs/${ID}/jobs?filter=latest"
|
||||
|
||||
# Search for build job
|
||||
echo "Searching for build job..."
|
||||
while [ -z "$JOB_ID" ] && [ -n "$NEXT_URL" ]; do
|
||||
# Get one page of jobs
|
||||
RESPONSE=$(curl -s -i \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"$NEXT_URL")
|
||||
|
||||
# Extract headers and body
|
||||
HEADERS=$(echo "$RESPONSE" | sed -n '1,/^\r$/p')
|
||||
BODY=$(echo "$RESPONSE" | sed '1,/^\r$/d')
|
||||
LINK_HEADER=$(echo "$HEADERS" | grep -i '^link:' | sed 's/^link: //')
|
||||
|
||||
# Check for next page in Link header
|
||||
if echo "$LINK_HEADER" | grep -q 'rel="next"'; then
|
||||
NEXT_URL=$(echo "$LINK_HEADER" | sed -E 's/.*<([^>]+)>; rel="next".*/\1/')
|
||||
else
|
||||
NEXT_URL=""
|
||||
fi
|
||||
|
||||
# Check for build job
|
||||
JOB_ID=$(echo "$BODY" | jq -r '.jobs[] | select(.name | contains("build (ee)")) | .id')
|
||||
done
|
||||
done
|
||||
echo "Job ID: ${JOB_ID}"
|
||||
|
||||
## Wait for uberjar build to complete
|
||||
while [ true ]; do
|
||||
curl -Ls --output uberjar.json \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/${{ github.repository }}/actions/jobs/${JOB_ID}
|
||||
jq -r '.steps[] | select(.name == "Prepare uberjar artifact") | .status' uberjar.json | grep -q "completed" && break
|
||||
echo "Waiting for uberjar build..."
|
||||
sleep 10
|
||||
done
|
||||
echo "run_id=$(jq -r '.workflow_runs[0].id' e2e-tests.json)" >> $GITHUB_OUTPUT
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ inputs.wait_for_uberjar && steps.wait_for_uberjar.outputs.run_id || github.run_id }}
|
||||
- name: Move uberjar to bin/docker
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar
|
||||
@@ -45,7 +107,7 @@ jobs:
|
||||
tags: ${{ secrets.PR_ENV_AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/metabase-enterprise:pr${{ github.event.number }}
|
||||
push: true
|
||||
deploy_pr:
|
||||
needs: [build]
|
||||
needs: [ build ]
|
||||
runs-on: ubuntu-latest
|
||||
name: PR Review ENV
|
||||
permissions:
|
||||
@@ -129,7 +191,7 @@ jobs:
|
||||
kubectl apply -f ./metabase.yml
|
||||
preview_links:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy_pr]
|
||||
needs: [ deploy_pr ]
|
||||
steps:
|
||||
- uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
|
||||
118
.github/workflows/release-embedding-sdk.yml
vendored
@@ -5,12 +5,18 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: "Branch we want to release the SDK from (to release from other branches use the workflow from those branches)"
|
||||
description: "Branch we want to release the SDK from"
|
||||
type: choice
|
||||
required: true
|
||||
default: "master"
|
||||
options:
|
||||
- master
|
||||
- release-x.51.x
|
||||
- release-x.52.x
|
||||
- release-x.53.x
|
||||
- release-x.54.x
|
||||
- release-x.55.x
|
||||
- esbuild-main
|
||||
|
||||
concurrency:
|
||||
# We want to ensure only one job is running at a time per branch because
|
||||
@@ -171,39 +177,41 @@ jobs:
|
||||
outputs:
|
||||
sdk_version: ${{ fromJson(steps.new-sdk-version.outputs.result).version }}
|
||||
major_version: ${{ fromJson(steps.new-sdk-version.outputs.result).majorVersion }}
|
||||
pre_release_label: ${{ fromJson(steps.new-sdk-version.outputs.result).preReleaseLabel }}
|
||||
steps:
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Prepare build scripts
|
||||
run: yarn --cwd release --frozen-lockfile && yarn --cwd release build
|
||||
|
||||
- name: Get current SDK version
|
||||
id: current-sdk-version
|
||||
run: |
|
||||
VERSION=$(jq -r .version ./enterprise/frontend/src/embedding-sdk-package/package.template.json)
|
||||
VERSION=$(jq -r .version ./enterprise/frontend/src/embedding-sdk/package.template.json)
|
||||
echo "sdk_current_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get next SDK patch or pre-release version
|
||||
- name: Get next SDK patch version
|
||||
id: new-sdk-version
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const { getNextSdkVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const branch = "${{ inputs.branch }}";
|
||||
script: |
|
||||
const currentVersion = "${{ steps.current-sdk-version.outputs.sdk_current_version }}";
|
||||
const [currentVersionWithoutSuffix, suffix] = currentVersion.split("-");
|
||||
const versionParts = currentVersionWithoutSuffix.split(".");
|
||||
versionParts[versionParts.length - 1] = parseInt(versionParts.at(-1)) + 1;
|
||||
const newVersion = versionParts.join(".");
|
||||
const [_, majorVersion] = versionParts
|
||||
|
||||
const result = getNextSdkVersion(branch, currentVersion);
|
||||
if (!suffix) {
|
||||
return {
|
||||
version: newVersion,
|
||||
majorVersion
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
version: result.version,
|
||||
preReleaseLabel: result.preReleaseLabel,
|
||||
majorVersion: result.majorVersion
|
||||
};
|
||||
version: `${newVersion}-${suffix}`,
|
||||
majorVersion
|
||||
}
|
||||
|
||||
- name: Append workflow summary
|
||||
run: |
|
||||
@@ -285,8 +293,12 @@ jobs:
|
||||
run: |
|
||||
./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ needs.determine-sdk-version.outputs.sdk_version }}
|
||||
|
||||
- name: Build SDK package
|
||||
run: yarn run build-embedding-sdk-package
|
||||
- name: Update changelog
|
||||
run: |
|
||||
yarn embedding-sdk:generate-changelog -o changelog-diff
|
||||
|
||||
- name: Build SDK bundle
|
||||
run: yarn run build-embedding-sdk
|
||||
|
||||
- name: Generate SDK package.json in the build directory
|
||||
run: yarn run embedding-sdk:generate-package
|
||||
@@ -297,6 +309,12 @@ jobs:
|
||||
name: metabase-sdk
|
||||
path: ./resources/embedding-sdk
|
||||
|
||||
- name: Upload changelog diff
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdk-changelog-diff
|
||||
path: ./changelog-diff
|
||||
|
||||
publish-npm:
|
||||
needs: [build-sdk, determine-sdk-version]
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -317,7 +335,6 @@ jobs:
|
||||
git config --global user.name "Metabase Automation"
|
||||
|
||||
- name: Update readme
|
||||
if: inputs.branch != 'master'
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_readme ${{ env.sdk_version }}
|
||||
|
||||
@@ -325,26 +342,25 @@ jobs:
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ env.sdk_version }}
|
||||
|
||||
- name: Create a PR updating readme + published version (using GitHub Metabase Automation account)
|
||||
- name: Retrieve SDK changelog diff
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sdk-changelog-diff
|
||||
|
||||
- name: Update changelog
|
||||
run: |
|
||||
cat changelog-diff enterprise/frontend/src/embedding-sdk/CHANGELOG.md > new-changelog
|
||||
mv new-changelog enterprise/frontend/src/embedding-sdk/CHANGELOG.md
|
||||
|
||||
- name: Create a PR updating readme + published version, and changelog (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
git checkout -b update-sdk-version-${{ env.sdk_version }}
|
||||
|
||||
if [ "${{ inputs.branch }}" = "master" ]; then
|
||||
COMMIT_MSG="chore(sdk): Update published npm version to ${{ env.sdk_version }}"
|
||||
PR_TITLE="chore(sdk): Update SDK version to ${{ env.sdk_version }}"
|
||||
PR_BODY="Update published npm package version to ${{ env.sdk_version }}"
|
||||
else
|
||||
COMMIT_MSG="docs(sdk): Update Readme version references and published npm version to ${{ env.sdk_version }}"
|
||||
PR_TITLE="docs(sdk): Update SDK version to ${{ env.sdk_version }}"
|
||||
PR_BODY="Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
fi
|
||||
|
||||
git commit -a -m "$COMMIT_MSG"
|
||||
git commit -a -m 'Update Readme version references and published npm version to ${{ env.sdk_version }}'
|
||||
git push origin HEAD
|
||||
gh pr create --base "${{ inputs.branch }}" \
|
||||
--assignee "${GITHUB_ACTOR}" \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY"
|
||||
gh pr create --base ${{ inputs.branch }}\
|
||||
--assignee "${GITHUB_ACTOR}"\
|
||||
--title "docs(sdk): Update SDK version to ${{ env.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
|
||||
@@ -372,39 +388,15 @@ jobs:
|
||||
name: metabase-sdk
|
||||
path: sdk
|
||||
|
||||
- name: Compute master tag
|
||||
id: compute-tag
|
||||
run: |
|
||||
if [ -n "${{ needs.determine-sdk-version.outputs.pre_release_label }}" ]; then
|
||||
echo "masterTag=${{ needs.determine-sdk-version.outputs.pre_release_label }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "masterTag=nightly" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Publish to NPM
|
||||
working-directory: sdk
|
||||
run: |
|
||||
echo //registry.npmjs.org/:_authToken=${{ secrets.NPM_RELEASE_TOKEN }} > .npmrc
|
||||
|
||||
TAG=$(jq -r --null-input \
|
||||
--arg branch "${{ inputs.branch }}" \
|
||||
--arg masterTag "${{ steps.compute-tag.outputs.masterTag }}" '
|
||||
{
|
||||
"master": $masterTag,
|
||||
"release-x.51.x": "51-stable",
|
||||
"release-x.52.x": "52-stable",
|
||||
"release-x.53.x": "53-stable",
|
||||
"release-x.54.x": "54-stable",
|
||||
"release-x.55.x": "55-stable",
|
||||
"release-x.56.x": "56-stable"
|
||||
}[$branch]'
|
||||
)
|
||||
|
||||
echo "Resolved npm tag: $TAG"
|
||||
npm publish --tag "$TAG"
|
||||
# Please keep the value in sync with `inputs.branch`'s release branch
|
||||
npm publish --tag ${{fromJson('{"master": "nightly", "release-x.51.x": "51-stable", "release-x.52.x": "52-stable", "release-x.53.x": "53-stable", "release-x.54.x": "54-stable", "release-x.55.x": "55-stable", "esbuild-main": "56-esbuild"}')[inputs.branch]}}
|
||||
|
||||
- name: Add `latest` tag to the latest release branch (`release-x.55.x`) deployment
|
||||
if: ${{ inputs.branch == 'release-x.56.x' }}
|
||||
if: ${{ inputs.branch == 'release-x.55.x' }}
|
||||
working-directory: sdk
|
||||
run: |
|
||||
npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
|
||||
|
||||
2
.github/workflows/release-log.yml
vendored
@@ -7,7 +7,9 @@ on:
|
||||
- release-x.*
|
||||
tags:
|
||||
- v*
|
||||
- nightly-*
|
||||
- latest-*
|
||||
- beta-*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
|
||||
9
.github/workflows/release-notes-preview.yml
vendored
@@ -34,23 +34,18 @@ jobs:
|
||||
AWS_S3_DOWNLOADS_BUCKET: test_bucket
|
||||
with:
|
||||
script: | # js
|
||||
const R = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const { getChangelog } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const fs = require('fs');
|
||||
|
||||
const version = '${{ inputs.version }}';
|
||||
|
||||
const issues = await R.getMilestoneIssues({
|
||||
const notes = await getChangelog({
|
||||
version,
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
|
||||
const notes = R.getWebsiteChangelog({
|
||||
version,
|
||||
issues,
|
||||
});
|
||||
|
||||
fs.writeFileSync(`release-notes-preview-${version}.md`, notes);
|
||||
- name: Upload Release Notes
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
6
.github/workflows/release-tag.yml
vendored
@@ -12,6 +12,8 @@ on:
|
||||
description: Tag name to apply to this release
|
||||
type: choice
|
||||
options:
|
||||
- nightly
|
||||
- beta
|
||||
- latest
|
||||
required: true
|
||||
tag_rollout:
|
||||
@@ -34,6 +36,8 @@ on:
|
||||
tag_name:
|
||||
type: string
|
||||
# options:
|
||||
# - nightly
|
||||
# - beta
|
||||
# - latest
|
||||
# - none (skips everything)
|
||||
required: true
|
||||
@@ -266,7 +270,7 @@ jobs:
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
fetch-depth: 0 # we want all branches and tags
|
||||
fetch-tags: true
|
||||
- name: Add and push git tag for latest
|
||||
- name: Add and push git tag for nightly/beta/latest
|
||||
if: ${{ !inputs.dot-x-tag }}
|
||||
run: | # sh
|
||||
if [[ "${{ matrix.edition }}" == "ee" ]]; then
|
||||
|
||||
8
.github/workflows/release.yml
vendored
@@ -17,6 +17,8 @@ on:
|
||||
options:
|
||||
- none
|
||||
- latest
|
||||
- beta
|
||||
- nightly
|
||||
required: true
|
||||
default: 'none'
|
||||
auto:
|
||||
@@ -39,6 +41,8 @@ on:
|
||||
# options:
|
||||
# - none
|
||||
# - latest
|
||||
# - beta
|
||||
# - nightly
|
||||
required: true
|
||||
default: 'none'
|
||||
auto:
|
||||
@@ -399,9 +403,7 @@ jobs:
|
||||
});
|
||||
|
||||
trigger-ee-extra-pr:
|
||||
needs:
|
||||
- containerize-ee
|
||||
- verify-s3-download
|
||||
needs: verify-s3-download
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
|
||||
30
.github/workflows/run-tests.yml
vendored
@@ -23,7 +23,6 @@ jobs:
|
||||
backend_all: ${{ steps.changes.outputs.backend_all }}
|
||||
frontend_all: ${{ steps.changes.outputs.frontend_all }}
|
||||
frontend_sources: ${{ steps.changes.outputs.frontend_sources }}
|
||||
documentation: ${{ steps.changes.outputs.documentation }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
@@ -67,12 +66,6 @@ jobs:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/static-viz-sources.yaml
|
||||
|
||||
uberjar:
|
||||
needs: [files-changed, static-viz-files-changed]
|
||||
if: ${{ !cancelled() && !(needs.files-changed.outputs.documentation == 'true' && needs.files-changed.outputs.backend_all == 'false' && needs.files-changed.outputs.frontend_all == 'false' && needs.files-changed.outputs.e2e_all == 'false') }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
backend-tests:
|
||||
if: ${{ !cancelled() }}
|
||||
needs: [files-changed, static-viz-files-changed]
|
||||
@@ -111,8 +104,7 @@ jobs:
|
||||
skip-lint: ${{ needs.files-changed.outputs.frontend_all != 'true' && needs.files-changed.outputs.e2e_specs != 'true' }}
|
||||
|
||||
e2e-tests:
|
||||
needs: [files-changed, uberjar]
|
||||
if: always() && !cancelled()
|
||||
needs: files-changed
|
||||
uses: ./.github/workflows/e2e-tests.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
@@ -127,23 +119,3 @@ jobs:
|
||||
needs: files-changed
|
||||
uses: ./.github/workflows/embedding-sdk.yml
|
||||
secrets: inherit
|
||||
|
||||
pr-env:
|
||||
needs: [uberjar]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.event.pull_request.labels.*.name, 'PR-Env')
|
||||
uses: ./.github/workflows/pr-env.yml
|
||||
secrets: inherit
|
||||
|
||||
containerize:
|
||||
needs: [uberjar]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.uberjar.result == 'success' &&
|
||||
(
|
||||
(github.event_name == 'push' && contains(fromJson('["master", "metabot-v3-main", "internal-tools"]'), github.ref_name)) ||
|
||||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar'))
|
||||
)
|
||||
uses: ./.github/workflows/containerize-uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
251
.github/workflows/semantic-search.yml
vendored
@@ -12,7 +12,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
semantic-search-tests-h2:
|
||||
semantic-search-tests-pgvector:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
@@ -20,9 +20,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: H2 with pgvector pg17
|
||||
junit-name: semantic-search-tests-h2-pgvector-17
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: pgvector pg16
|
||||
junit-name: semantic-search-tests-pgvector-16
|
||||
image: pgvector/pgvector:pg16
|
||||
env:
|
||||
enable-ssl-tests: 'false'
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
@@ -32,7 +34,7 @@ jobs:
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
image: ${{ matrix.version.image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
@@ -40,6 +42,21 @@ jobs:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
env:
|
||||
# Only run old migrations tests on pushes to master or release branches. All other branches should skip tests
|
||||
# with the tag `mb/old-migrations-test`. `__ADDITIONAL_EXCLUDED_TAG__` is not used anywhere outside of splicing
|
||||
# it in to the command below.
|
||||
__ADDITIONAL_EXCLUDED_TAG__: >-
|
||||
${{
|
||||
(
|
||||
github.event_name == 'push' &&
|
||||
(
|
||||
github.ref == 'master' ||
|
||||
startsWith(github.ref, 'release-')
|
||||
) &&
|
||||
''
|
||||
) ||
|
||||
':mb/old-migrations-test'
|
||||
}}
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
CI: 'true'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
@@ -52,224 +69,7 @@ jobs:
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-mariadb:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: MariaDB 10.2 with pgvector pg17
|
||||
junit-name: semantic-search-tests-mariadb-10-2
|
||||
mariadb-image: circleci/mariadb:10.2.23
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: MariaDB Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-mariadb-latest
|
||||
mariadb-image: circleci/mariadb:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
mysql:
|
||||
image: ${{ matrix.version.mariadb-image }}
|
||||
ports:
|
||||
- "3306:3306"
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: circle_test
|
||||
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
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-mysql:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: MySQL 8.0 with pgvector pg17
|
||||
junit-name: semantic-search-tests-mysql-8-0
|
||||
mysql-image: cimg/mysql:8.0
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: MySQL Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-mysql-latest
|
||||
mysql-image: mysql:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
mysql:
|
||||
image: ${{ matrix.version.mysql-image }}
|
||||
ports:
|
||||
- "3306:3306"
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: circle_test
|
||||
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
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-postgres:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: Postgres 12.x with pgvector pg17
|
||||
junit-name: semantic-search-tests-postgres-12
|
||||
postgres-image: postgres:12-alpine
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: Postgres Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-postgres-latest
|
||||
postgres-image: postgres:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
postgres:
|
||||
image: ${{ matrix.version.postgres-image }}
|
||||
ports:
|
||||
- "5433:5432"
|
||||
env:
|
||||
POSTGRES_USER: mb_test
|
||||
POSTGRES_DB: mb_test
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
MB_DB_TYPE: postgres
|
||||
MB_DB_PORT: 5433
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_DBNAME: mb_test
|
||||
MB_DB_USER: mb_test
|
||||
MB_POSTGRESQL_TEST_USER: mb_test
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
:exclude-tags '[ ${{ matrix.job.exclude-tag }} ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -284,10 +84,7 @@ jobs:
|
||||
|
||||
semantic-search-tests-result:
|
||||
needs:
|
||||
- semantic-search-tests-h2
|
||||
- semantic-search-tests-mariadb
|
||||
- semantic-search-tests-mysql
|
||||
- semantic-search-tests-postgres
|
||||
- semantic-search-tests-pgvector
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
name: semantic-search-tests-result
|
||||
|
||||
147
.github/workflows/snyk.yml
vendored
@@ -13,11 +13,12 @@ on:
|
||||
schedule:
|
||||
- cron: '0 5 * * *'
|
||||
|
||||
|
||||
jobs:
|
||||
# Generate pom.xml files for all Maven projects
|
||||
generate-poms:
|
||||
monitor:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
name: Generate pom.xml files
|
||||
name: Generate Snyk report
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -25,144 +26,26 @@ jobs:
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: 'snyk'
|
||||
- uses: snyk/actions/setup@0.4.0
|
||||
- name: Generate all pom.xml
|
||||
run: .github/scripts/write-poms.sh
|
||||
- name: Upload pom files
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pom-files
|
||||
path: |
|
||||
pom.xml
|
||||
modules/drivers/*/pom.xml
|
||||
|
||||
# Yarn/NPM projects that don't need pom files
|
||||
frontend-projects:
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
name: ${{ matrix.project.name }}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
project:
|
||||
- name: Main Frontend (yarn)
|
||||
file: yarn.lock
|
||||
package-manager: yarn
|
||||
category: main-frontend-yarn
|
||||
- name: Embedding SDK Template
|
||||
file: bin/embedding-sdk/templates/yarn.lock
|
||||
package-manager: yarn
|
||||
category: embedding-sdk-template
|
||||
- name: E2E Angular 20 Host App
|
||||
file: e2e/embedding-sdk-host-apps/angular-20-host-app/package-lock.json
|
||||
package-manager: npm
|
||||
category: e2e-angular-host
|
||||
- name: E2E Next 15 App Router
|
||||
file: e2e/embedding-sdk-host-apps/next-15-app-router-host-app/package-lock.json
|
||||
package-manager: npm
|
||||
category: e2e-next-app-router
|
||||
- name: E2E Next 15 Pages Router
|
||||
file: e2e/embedding-sdk-host-apps/next-15-pages-router-host-app/package-lock.json
|
||||
package-manager: npm
|
||||
category: e2e-next-pages-router
|
||||
- name: E2E Vite 6 Host App
|
||||
file: e2e/embedding-sdk-host-apps/vite-6-host-app/package-lock.json
|
||||
package-manager: npm
|
||||
category: e2e-vite-host
|
||||
- name: Release Helper
|
||||
file: release/yarn.lock
|
||||
package-manager: yarn
|
||||
category: release-helper
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: snyk/actions/setup@0.4.0
|
||||
- name: Run snyk test
|
||||
- name: Run snyk main project
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
continue-on-error: true
|
||||
run: snyk test --org="metabase-AnD9iS4Wfu4eBYMsG2DZ5N" --remote-repo-url="https://github.com/metabase/metabase" --file=${{ matrix.project.file }} --package-manager=${{ matrix.project.package-manager }} --sarif-file-output=snyk-${{ matrix.project.category }}.sarif
|
||||
- name: Upload results
|
||||
run: snyk test --all-projects --exclude="modules" --sarif-file-output=snyk-main.sarif
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: snyk-${{ matrix.project.category }}.sarif
|
||||
category: ${{ matrix.project.category }}
|
||||
|
||||
# Maven projects that need pom files
|
||||
maven-projects:
|
||||
needs: generate-poms
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
name: ${{ matrix.project.name }}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
project:
|
||||
- name: Main Backend (maven)
|
||||
file: pom.xml
|
||||
category: main-backend-maven
|
||||
- name: Driver - Athena
|
||||
file: modules/drivers/athena/pom.xml
|
||||
category: driver-athena
|
||||
- name: Driver - BigQuery Cloud SDK
|
||||
file: modules/drivers/bigquery-cloud-sdk/pom.xml
|
||||
category: driver-bigquery-cloud-sdk
|
||||
- name: Driver - ClickHouse
|
||||
file: modules/drivers/clickhouse/pom.xml
|
||||
category: driver-clickhouse
|
||||
- name: Driver - Databricks
|
||||
file: modules/drivers/databricks/pom.xml
|
||||
category: driver-databricks
|
||||
- name: Driver - Druid
|
||||
file: modules/drivers/druid/pom.xml
|
||||
category: driver-druid
|
||||
- name: Driver - Druid JDBC
|
||||
file: modules/drivers/druid-jdbc/pom.xml
|
||||
category: driver-druid-jdbc
|
||||
- name: Driver - Hive-like
|
||||
file: modules/drivers/hive-like/pom.xml
|
||||
category: driver-hive-like
|
||||
- name: Driver - MongoDB
|
||||
file: modules/drivers/mongo/pom.xml
|
||||
category: driver-mongo
|
||||
- name: Driver - Oracle
|
||||
file: modules/drivers/oracle/pom.xml
|
||||
category: driver-oracle
|
||||
- name: Driver - Presto JDBC
|
||||
file: modules/drivers/presto-jdbc/pom.xml
|
||||
category: driver-presto-jdbc
|
||||
- name: Driver - Redshift
|
||||
file: modules/drivers/redshift/pom.xml
|
||||
category: driver-redshift
|
||||
- name: Driver - Snowflake
|
||||
file: modules/drivers/snowflake/pom.xml
|
||||
category: driver-snowflake
|
||||
- name: Driver - SparkSQL
|
||||
file: modules/drivers/sparksql/pom.xml
|
||||
category: driver-sparksql
|
||||
- name: Driver - SQLite
|
||||
file: modules/drivers/sqlite/pom.xml
|
||||
category: driver-sqlite
|
||||
- name: Driver - SQL Server
|
||||
file: modules/drivers/sqlserver/pom.xml
|
||||
category: driver-sqlserver
|
||||
- name: Driver - Starburst
|
||||
file: modules/drivers/starburst/pom.xml
|
||||
category: driver-starburst
|
||||
- name: Driver - Vertica
|
||||
file: modules/drivers/vertica/pom.xml
|
||||
category: driver-vertica
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: snyk/actions/setup@0.4.0
|
||||
- name: Download pom files
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pom-files
|
||||
- name: Run snyk test
|
||||
sarif_file: snyk-main.sarif
|
||||
category: main-project
|
||||
- name: Run snyk drivers
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
continue-on-error: true
|
||||
run: snyk test --org="metabase-AnD9iS4Wfu4eBYMsG2DZ5N" --remote-repo-url="https://github.com/metabase/metabase" --file=${{ matrix.project.file }} --package-manager=maven --sarif-file-output=snyk-${{ matrix.project.category }}.sarif
|
||||
|
||||
- name: Upload results
|
||||
run: cd modules && snyk test --all-projects --sarif-file-output=snyk-drivers.sarif
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: snyk-${{ matrix.project.category }}.sarif
|
||||
category: ${{ matrix.project.category }}
|
||||
sarif_file: modules/snyk-drivers.sarif
|
||||
category: drivers
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
name: Uberjar Containerize labeled
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize, reopened ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
uberjar:
|
||||
if: ${{ contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar') || github.event.label.name == 'build-docker-uberjar' }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
containerize:
|
||||
needs: [uberjar]
|
||||
if: ${{ contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar') || github.event.label.name == 'build-docker-uberjar' }}
|
||||
uses: ./.github/workflows/containerize-uberjar.yml
|
||||
secrets: inherit
|
||||
184
.github/workflows/uberjar.yml
vendored
@@ -1,17 +1,15 @@
|
||||
name: Build Uberjar
|
||||
name: Build + Docker Uberjar
|
||||
|
||||
# This workflow builds an uberjar and pushes it to dockerhub for any branch, either on-demand,
|
||||
# or automatically for the listed branches
|
||||
|
||||
concurrency:
|
||||
group: uberjar-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}
|
||||
cancel-in-progress: false
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- feature-visualizer
|
||||
- internal-tools
|
||||
- nm-semantic-search-in-metabase
|
||||
paths-ignore:
|
||||
# config files
|
||||
- ".**"
|
||||
@@ -22,106 +20,73 @@ on:
|
||||
- "**test/**"
|
||||
- "**_test.clj"
|
||||
- "**/frontend/**.unit.*"
|
||||
pull_request:
|
||||
types: [labeled, opened, synchronize, reopened]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit:
|
||||
description: "Optional full-length commit SHA-1 hash"
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
check-existing-artifacts:
|
||||
get-container-info:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: Get container info
|
||||
# Skip if this is a PR without the build-docker-uberjar label
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar')
|
||||
outputs:
|
||||
ee_exists: ${{ steps.check-ee.outcome == 'success' }}
|
||||
oss_exists: ${{ steps.check-oss.outcome == 'success' }}
|
||||
should_build: ${{ steps.decide.outputs.should_build }}
|
||||
editions: ${{ toJson(fromJson(steps.info.outputs.result).editions) }}
|
||||
ee: ${{ toJson(fromJson(steps.info.outputs.result).ee) }}
|
||||
oss: ${{ toJson(fromJson(steps.info.outputs.result).oss) }}
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Try to fetch existing EE artifact
|
||||
id: check-ee
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
output-name: metabase-ee.jar
|
||||
|
||||
- name: Try to fetch existing OSS artifact
|
||||
id: check-oss
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-oss-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
output-name: metabase-oss.jar
|
||||
|
||||
- name: Decide if build is needed
|
||||
id: decide
|
||||
run: |
|
||||
EE_EXISTS="${{ steps.check-ee.outcome == 'success' }}"
|
||||
OSS_EXISTS="${{ steps.check-oss.outcome == 'success' }}"
|
||||
|
||||
echo "EE exists: $EE_EXISTS"
|
||||
echo "OSS exists: $OSS_EXISTS"
|
||||
|
||||
# Build only if artifacts don't exist for this commit hash
|
||||
# Since we build by hash, if artifacts exist for this hash, we don't need to rebuild
|
||||
if [[ "$EE_EXISTS" == "false" ]] || [[ "$OSS_EXISTS" == "false" ]]; then
|
||||
SHOULD_BUILD="true"
|
||||
echo "Will build: ee_exists=$EE_EXISTS, oss_exists=$OSS_EXISTS"
|
||||
else
|
||||
SHOULD_BUILD="false"
|
||||
echo "Skipping build: artifacts exist for this commit hash"
|
||||
fi
|
||||
|
||||
echo "should_build=$SHOULD_BUILD" >> $GITHUB_OUTPUT
|
||||
|
||||
# if this is on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
- name: Get docker repo and tag
|
||||
id: info
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getBuildRequirements, getVersionFromReleaseBranch } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const branch = '${{ github.head_ref || github.ref_name }}';
|
||||
const owner = '${{ github.repository_owner }}';
|
||||
|
||||
const version = getVersionFromReleaseBranch('${{ github.ref }}');
|
||||
const requirements = getBuildRequirements(version);
|
||||
console.log(`Branch: ${branch}`);
|
||||
|
||||
if (branch === "master") {
|
||||
return {
|
||||
editions: ["ee", "oss"],
|
||||
ee: {
|
||||
repo: `${owner}/metabase-enterprise-head`,
|
||||
tag: "latest"
|
||||
},
|
||||
oss: {
|
||||
repo: `${owner}/metabase-head`,
|
||||
tag: "latest"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
editions: ["ee"],
|
||||
ee: {
|
||||
repo: `${owner}/metabase-dev`,
|
||||
tag: branch.replaceAll("/", "-"), // slashes make docker sad
|
||||
},
|
||||
};
|
||||
|
||||
- name: Print output
|
||||
run: |
|
||||
echo "${{ steps.info.outputs.result }}"
|
||||
|
||||
build:
|
||||
needs:
|
||||
[check-existing-artifacts, get-build-requirements]
|
||||
if: always() && !cancelled() && needs.check-existing-artifacts.outputs.should_build == 'true' && (needs.get-build-requirements.result == 'success' || needs.get-build-requirements.result == 'skipped')
|
||||
needs: get-container-info
|
||||
name: Build MB ${{ matrix.edition }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ["ee", "oss"]
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
INTERACTIVE: false
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }} # faster builds for dev
|
||||
SKIP_LICENSES: true # faster builds for dev
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
@@ -129,33 +94,28 @@ jobs:
|
||||
ref: ${{ github.event.inputs.commit }}
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version || '22' }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
|
||||
java-version: 21
|
||||
- name: Build
|
||||
run: ./bin/build.sh
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.sha }}-uberjar
|
||||
|
||||
check-jar-health:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
|
||||
needs: [build, check-existing-artifacts]
|
||||
if: always() && !cancelled() && (needs.build.result == 'success' || (needs.check-existing-artifacts.outputs.should_build == 'false' && needs.check-existing-artifacts.outputs.ee_exists == 'true' && needs.check-existing-artifacts.outputs.oss_exists == 'true'))
|
||||
needs: [build, get-container-info]
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ["ee", "oss"]
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
java-version: [21]
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare JRE (Java Run-time Environment)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -163,12 +123,56 @@ jobs:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: "temurin"
|
||||
- run: java -version
|
||||
- name: Retrieve uberjar artifact
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.sha }}-uberjar
|
||||
- name: Launch uberjar
|
||||
run: >-
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./metabase.jar &
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./target/uberjar/metabase.jar &
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
|
||||
containerize:
|
||||
needs: [check-jar-health, get-container-info]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
uses: ./.github/workflows/containerize-jar.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
artifact-name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.sha }}-uberjar
|
||||
commit: ${{ github.event.inputs.commit || github.sha }}
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
release: "false"
|
||||
build-args: |
|
||||
GIT_COMMIT_SHA=${{ github.event.inputs.commit || github.sha }}
|
||||
|
||||
run-trivy:
|
||||
needs: [get-container-info, containerize]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Trivy vulnerability scanner
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit || github.sha }}
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.29.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
with:
|
||||
image-ref: docker.io/${{ env.repo }}:${{ env.tag }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: "trivy-results.sarif"
|
||||
|
||||
14
.gitignore
vendored
@@ -51,7 +51,6 @@ cypress.env.json
|
||||
/lein-plugins/*/target
|
||||
/local
|
||||
/locales/metabase-*.pot
|
||||
/logs
|
||||
/modules/drivers/*/resources/namespaces.edn
|
||||
/modules/drivers/*/target
|
||||
/node_modules/
|
||||
@@ -61,9 +60,7 @@ cypress.env.json
|
||||
/resources/frontend_client/app/dist/
|
||||
/resources/frontend_client/app/locales
|
||||
/resources/frontend_client/app/embed.js
|
||||
/resources/frontend_client/app/embedding-sdk.js
|
||||
/resources/frontend_client/app/embedding-sdk.js.map
|
||||
/resources/frontend_client/tmp-*/
|
||||
/resources/frontend_client/tmp-embed-js/
|
||||
/resources/frontend_client/embed.html
|
||||
/resources/frontend_client/embed-sdk.html
|
||||
/resources/frontend_client/index.html
|
||||
@@ -98,13 +95,6 @@ xcuserdata
|
||||
dev/src/dev/nocommit/
|
||||
dev/serialization_deltas/
|
||||
*~
|
||||
|
||||
# TypeScript compilation artifacts
|
||||
/build/
|
||||
*.tsbuildinfo
|
||||
/trace-output/
|
||||
/temp-types/
|
||||
|
||||
**/cypress_sample_database.json
|
||||
**/cypress_sample_instance_data.json
|
||||
/frontend/src/cljs
|
||||
@@ -162,5 +152,3 @@ CLAUDE.local.md
|
||||
.eslintcache
|
||||
|
||||
/logs
|
||||
/.clojure-mcp
|
||||
__pycache__/
|
||||
|
||||
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
||||
[submodule "python-runner"]
|
||||
path = python-runner
|
||||
url = https://github.com/metabase/python-runner-container.git
|
||||
branch = prototype
|
||||
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 60 KiB |