Compare commits

...

723 Commits

Author SHA1 Message Date
Alexander Kiselev
197c85d13c Copied delay utility function into Cypress backend
runner to decouple from incoming TS refactors
2021-10-07 13:52:36 -07:00
Alexander Kiselev
b4e2f5469f added type roots 2021-10-07 11:56:52 -07:00
Alexander Kiselev
d29be80ad7 now update Icon 2021-10-07 10:35:26 -07:00
Alexander Kiselev
24f380f0aa rename icon again 2021-10-07 10:35:20 -07:00
Alexander Kiselev
443db9cb0e fixed more updates 2021-10-07 10:34:56 -07:00
Alexander Kiselev
183f02474b Fix collapse section 🤦 2021-10-07 10:34:34 -07:00
Alexander Kiselev
4fc3652fea ported some really basic styled components files to typescript 2021-10-07 10:33:48 -07:00
Alexander Lesnenko
8114af48f9 add basic typescript configuration (#18284)
* add basic typescript configuration

* convert a tiny hook use-debounced-value to typescript

* allow any for now?

* update terser and static viz configs

* adjust config

* change extension of QuestionActivityTimeline from jsx to js to match jest config

* adjust config

* skip failing tests

* Fix missing question method in unit tests (#18314)

* review fix

* fix

Co-authored-by: Anton Kulyk <kuliks.anton@gmail.com>
2021-10-07 19:00:08 +03:00
Anton Kulyk
28291680cd Fix invalid import (#18311)
* Fix invalid import

* Blank

* [ci nocache]
2021-10-07 15:02:46 +03:00
Nemanja Glumac
20fa050786 #17963 Repro: MongoDB cannot use filter expression comparing two fields (#18305) [ci nocache] 2021-10-07 12:38:51 +02:00
Anton Kulyk
8c43bd6218 Fix new questions don't appear in the Saved Questions picker (#18095)
* Enable repro

* Move saved questions virtual DB id to own file

* Add saved question helpers

* Add test-id to Metabase logo component

* Extend repro test to cover archived items handling

* Handle saved question actions in schema entity

* Handle saved question actions in table entity

* Fix moved file import

* Fix Cypress can't find logo in EE (whitelabeling)

* Fix saved questions order

* Fix saved questions included in database tables
2021-10-07 13:07:41 +03:00
Anton Kulyk
f68e1d49f6 Fix auto expanding nested collections (#18240)
* Remove not used prop

* Make CollectionSidebar a functional component

* Fix accidentaly closing some collections
2021-10-07 13:07:25 +03:00
Gustavo Saiani
d4110fda9a Fix typo in object key (#18306) 2021-10-06 19:08:28 -03:00
Alexander Polyankin
193547c460 Fix CSP issue for Google Analytics (#18295) 2021-10-06 22:34:13 +03:00
Nemanja Glumac
ab3c3955e1 #12439 Repro: Clicking on legend in native question breaks the UI (#18294) 2021-10-06 20:50:13 +02:00
Cam Saul
a98eb1d8c3 Static viz: allow rendering non-timeseries line charts (#18279)
* Static viz: respect custom X and Y axis labels

* Static viz: allow rendering non-timeseries line charts

* Test fixes 🔧
2021-10-06 11:32:54 -07:00
Alexander Polyankin
aec9462406 Approved domains tests (#18075) 2021-10-06 21:21:36 +03:00
Alexander Polyankin
3ea737ad55 Reset filter value when widget type changes (#18256) 2021-10-06 21:20:07 +03:00
Alexander Polyankin
7f1b701aaa Fix whitelabel issues with color function (#18217) 2021-10-06 21:18:54 +03:00
Cam Saul
e85c11228a Static viz: respect custom X and Y axis labels (#18276) 2021-10-06 10:19:37 -07:00
Jeff Evans
e622519f0e Change implementation of docsUrl to handle RC suffixes for EE versions (#18270)
Change implementation of docsUrl to handle RC suffixes for EE versions

Change the regex used to test the tag to detect any OSS or EE version, including (possibly) an arbitrary suffix after the major and minor parts, and normalize to the major OSS equivalent version instead.  If the suffix, OTOH, is `-SNAPSHOT` (ignoring case), then the doc tag will be `latest`, on the theory that this is as local development build.

v0.41.0 => v0.41
v1.41.1 => v0.41
v1.41.2-RC1 => v0.41
v1.42.0-SNAPSHOT => latest

Adding unit tests for all cases

Update behavior so that -SNAPSHOT suffix points to "latest"
2021-10-06 11:16:29 -05:00
Cam Saul
7bf631074b Static viz: respect whitelabel colors (#18277) 2021-10-06 08:46:00 -07:00
Nemanja Glumac
76cc6ca94d #18114 Repro: Dashboard Textbox does not render links unless using Markdown (#18265) 2021-10-06 16:48:59 +02:00
Noah Moss
6f2baf6f5f Add is-hosted? setting based on metastore token (#17256) 2021-10-06 10:30:36 -04:00
Jeff Bruemmer
ab6a473b41 docs - updates to auditing, landing page, and more (#18266) 2021-10-06 09:52:56 -04:00
Noah Moss
3d7a1c53de Fix datetime formatting for pulse/dashboard subscription attachments (#18225) 2021-10-06 09:49:07 -04:00
Nemanja Glumac
ea87c9303b #18148 Repro: "Save" button shouldn't appear before one selects the source for a native question (#18259) 2021-10-06 14:19:50 +02:00
Nemanja Glumac
f94c3c96f6 Cypress email setup (#18247)
* Add `setupSMTP` helper function

* Remove deprecated `setupDummySMTP` helper

* Re-use `setupSMTP` helper in tests

* Always clear Webmail's inbox after setting up the SMTP
2021-10-06 13:46:26 +02:00
Pawit Pornkitprasan
86fb6c5d86 Fix subscriptions being sent for the wrong dashboard (#18281) 2021-10-06 12:06:26 +03:00
Howon Lee
384218e646 Erroring question page nits (#18190)
Previous PRs for error cards page were laser focused on getting everything to work, as opposed to actually conforming to spec. This one gets it closer to spec, although product wants reloading animations which are not there yet. To wit,

- Indicates to end user what the current running state is. Given the many orders of magnitude in DB query run times I think something robust and non-ephemeral is necessary here (looking at some sort of expanded QE model) but Maz suggested expedient method and I took it
- No more left nav on the table page
- Page heading for table page
- Independent scroll-x behavior on the table
- Styling for the error section on the table page
- Select-all component. Note that the interaction behavior with pagination is fiddly. (but less fiddly now that it's all based on card id's instead of row numbers)
- Coalescing default behavior for Our Analytics collection (default collection) and null number of dashboards
Rename error name to error content search
2021-10-06 00:59:38 -07:00
Raphaël Merx
a1d08db6fa Currency list: Add Papua New Guinean kina (#18234) 2021-10-06 09:31:24 +07:00
Maz Ameli
e56ba89e5c pull in translations for 0.41 (#18268) 2021-10-05 15:05:14 -07:00
Alexander Lesnenko
6600f4c596 Fix virtual fields are not passed to ParameterValueWidget (#18223)
* Fix virtual fields are missing in ParameterValueWidget

* fix fk filter parameters
2021-10-06 00:17:40 +03:00
Jeff Evans
e441ff30ee Snowflake: fix error in aggregation expression having different casing in order clause (#18221)
Remove the `driver/format-custom-field-name` implementation for :snowflake, which was causing the problem and appears to be no longer needed anyway

Add test for this scenario to `metabase.query-processor-test.expression-aggregations-test`
2021-10-05 15:57:33 -05:00
Cam Saul
8f4d867bc4 Fix Dashboard Subscription email validation (second pass) (#18237)
* Fix Dashboard Subscription email validation (second pass)

* Always validate Pulse channels in test endpoint
2021-10-05 13:10:52 -07:00
Noah Moss
a7e1d254a1 Use UTC as default timezone in alert template when report timezone isn't set (#18257) 2021-10-05 15:54:36 -04:00
Anton Kulyk
78f4ab6b43 Disable question's "Save" button until native query can be run (#18252)
* Update Link component's code style

* Add disabled style to Link

* Disable "Save" button when can't run query

* Animate Link color and opacity changes
2021-10-05 22:30:02 +03:00
Maz Ameli
93e7efcdd3 Restyle the Verify button (#18134)
* restyle the Verify button

* remove unused components

* make the verify button blue
2021-10-05 12:23:20 -07:00
Ariya Hidayat
8c62e8a047 Docker build: just one build stage (#18196) 2021-10-05 10:48:25 -07:00
Alexander Polyankin
3f07a31838 Static viz whitelabel colors (#18248) 2021-10-05 20:27:38 +03:00
Howon Lee
194d1dc0d5 Fix cache native queries not working (underlying problem is unit conversion actually) (18160) (#18230)
Cache TTL is defined in the nice new column things as per hour. The actual cache wanted it in seconds. There wasn't a conversion hours->secs before, which was the underlying illusion that gave rise to #18160 - with a properly set cache ttl the cache works fine. But the cache ttl's weren't getting set to proper values because of that lack of unit conversion. So here's the conversion, hours->secs.
2021-10-05 09:59:17 -07:00
Alexander Lesnenko
5c34833326 decrease data picker search results to 50 (#18250) 2021-10-05 19:49:02 +03:00
Alexander Polyankin
90a77fb5b8 Add missing categorical charts (#18186) 2021-10-05 16:40:49 +03:00
Alexander Polyankin
fc535276ce Fix empty state in the Erroring questions page (#18188) 2021-10-05 15:57:38 +03:00
Pawit Pornkitprasan
3ab0a13f8e Make webpack output closer to webpack 4 and fix whitelabelling (#18238)
* Make webpack output closer to webpack 4 and fix whitelabelling

* Fix recently-viewed.cy.spec.js

Not sure why it's started failing with this PR, but adding wait for text.
2021-10-05 17:13:28 +07:00
Alexander Polyankin
b7a8b4291d Fix composite chart layout (#18195) 2021-10-05 13:03:39 +03:00
Alexander Polyankin
7e201eaa9b Revert "Fix combined tooltip for charts (#17946)" (#18227) 2021-10-05 13:03:17 +03:00
Dalton
295f40d75a Remove unused function props passed to ParameterWidget (#18202) 2021-10-04 16:01:33 -07:00
Dalton
651386bdeb Fix DataSelector infinite loop (#18228)
When all the necessary data hasn't been fetched you can find yourself in
stuck in a loop between the invalid state checks in DataSelector's
componentDidUpdate method and the skipSteps method.

1. there seems to always be a single schema (the "Everything Else"
   schema) available on instantiation
2. the skipSteps method auto-selects this schema when no other schemas
   exist
3. there's some pre-existing logic to avoid getting in this loop by
   checking the is_saved_questions property of the database in the
   selectedSchema. However, for whatever reason this property doesn't
   exist until AFTER we've fetched some things.

The fix is checking a property that is guaranteed to exist, the ID for
the "Everything Else" database
2021-10-04 15:47:50 -07:00
Cam Saul
38faad602e GET /api/database/:id/schemas should not return 'empty' schemas (#18123) 2021-10-04 11:38:17 -07:00
Ariya Hidayat
6725c0cf15 Make temporal fields selectable for max/min summary (#18135) 2021-10-04 10:18:34 -07:00
Noah Moss
e6023765b6 Fix exports for queries with aggregations (#18205) 2021-10-04 10:50:09 -04:00
Alexander Lesnenko
ae2027e768 fix missing prop types import after renaming (#18213) 2021-10-04 16:08:25 +03:00
Alexander Polyankin
ed4ec6c92c Fix /account authentication and session deletion behavior (#18151) 2021-10-04 14:05:42 +03:00
Ariya Hidayat
3a67ddc1ff Rename NODE_ENV to WEBPACK_BUNDLE (#18087)
NODE_ENV interferes with other tools (e.g. `yarn` won't pull
devDependencies). Since what we need is only a flag indicating Webpack
to bundle for production vs developement, invent our own env.

This also solves the mystery of unable to call `yarn build` in the build
script `bin/build-mb/src/build.clj`.
2021-10-03 21:44:55 -07:00
Pawit Pornkitprasan
c7b2fd5ceb Allow JDBC additional-options in Redshift plugin (#18111)
Co-authored-by: Justin McCarthy <justin@strongdm.com>
2021-10-04 09:40:51 +07:00
Ariya Hidayat
465480d35e Reject less/greater than operators on booleans (#18206) 2021-10-03 11:20:22 -07:00
Alexander Lesnenko
8c0858638d Show permissions for hidden tables (#18171)
* Show hidden tables permissions, load tables only when needed

* fix padding

* remove loader div wrapper

* remove redundant wrappers
2021-10-02 00:43:17 +03:00
Dalton
9588033b0f Fetch and use fields associated with a parameter to parse parameter values found in URL query (#18104)
* move logic in dashboard selectors to meta/Dashboard

* rmv usage of syncQueryParamsWithURL

* add syncQueryParamsWithURL logic to meta/Parameters.js

* Fix public questions

* fix dashboards

* fix query builder

* don't normalize when value is empty string

* rmv unused setMultipleParameterValues fn

* replace selector logic with meta/Dashboard fn

* filter out nil fields

we need to do more work before we can properly use
fields from nested questions when parsing parameter values.

* add field to dash parameter so we can correctly type nested native query fields

* fix tests

* code style tweaks per review
2021-10-01 12:14:44 -07:00
Nemanja Glumac
de22490dd6 Cypress E2E MySQL snapshot (#18193)
* Create `mysql-8` snapshot

* Use `mysql-8` snapshot in tests

* Extract repro for #15342

* Relocate mysql `add` spec

* Extract mysql GUI query tests

* Relocate mysql `query` spec

* Extract repro for #12445

* Remove `metabase-db` from Cypress

* Update Cypress README
2021-10-01 20:57:15 +02:00
Noah Moss
9b2fbc7162 Convert deprecated k:mm time style to HH:mm on viz settings normalization (#18167) 2021-10-01 11:21:36 -07:00
Nemanja Glumac
2cf6dc552f Cypress E2E Mongo snapshot (#18184)
* Create `mongo-4` snapshot

* Use `mongo-4` snapshot in tests

* Restore and authenticate

* Relocate mongo `line` spec

* Relocate mongo `native` spec

* Relocate mongo `add` spec

* Extract repro for #13097

* Relocate mongo `query` spec

* Remove mongo from `metabase-db`
2021-10-01 18:09:44 +02:00
Nemanja Glumac
170a2b849f Separate qa db snapshots (#18179)
- a56b640 broke Percy workflow on master and introduced a major inconvenience for developers who wish to run Cypress locally. In both cases, it's required to have all supported QA DB docker images running at all times. Otherwise, the Cypress snapshot creation phase breaks.

This PR:
- uses the existing ENV var to conditionally skip qa db snapshots
- this doesn't affect CircleCI workflow - it merely makes life easier for developers running Cypress locally and for a Percy workflow that runs on GitHub Actions (where we still don't have QA docker images available)
2021-10-01 14:10:14 +02:00
Alexander Polyankin
2b91b3e8b2 Add scrolling to SQL error messages (#18144) 2021-10-01 12:14:31 +03:00
Jeff Evans
cb05523b06 Fix errors from disallowed characters in BigQuery custom expression names (#18055)
Add `escape-alias` multimethod to `sql.qp` to handle translating an alias (whether for a field or expression) into something supported by the driver in quesion

Add default impl that is essentially identity

Marking `sql.qp/field->alias` as deprecated, and changing its default implementation to invoke the new `sql.qp/escape-alias` on the field's `:name` (with the intention of removing it in a future release, since individual driver won't need to override this, so much as they'll need to override `escape-alias` itself).

Override `sql.qp/escape-alias` method for both BigQuery drivers to run through the same `->valid-field-identifier` function already defined for this purpose

Add test for a custom expression with weird characters
2021-09-30 16:44:21 -05:00
Nemanja Glumac
6978a836dc Translate Whitelabel color options (#18170)
Closes #18168.
2021-09-30 23:26:21 +02:00
Nemanja Glumac
a56b640dfc Cypress E2E postgres snapshot (#18106)
* Create `postgres-12` snapshot

* Use `postgres-12` snapshot in tests

* Relocate postgres `add` spec

* Relocate postgres `sandboxes` spec

* Relocate postgres `native` spec

This actually didn't have anything to do with the native questions.
We simply used native editor because it was easier to reproduce the issue.

* Relocate postgres `permissions` spec

* Relocate postgres `query` spec

* Relocate postgres `custom-column` spec

* Remove postgres from `metabase-db`
2021-09-30 20:51:06 +02:00
Alexander Lesnenko
c56df9ce6f fix filters alignment (#18139) 2021-09-30 21:34:29 +03:00
Howon Lee
9eced49570 Do not emit view logs when there's no card id for query viewlogs (fixes #18136) (#18138)
There is a problem when there are no card ids for a userland query (so not all userland queries are non-adhoc queries: they can be adhoc), where viewlog needs a card id so it chokes. Just adds a check so it doesn't even try to emit a viewlog, since the auditing is for non-adhoc queries only.
2021-09-30 11:14:48 -07:00
Gustavo Saiani
f87ce232f3 Don't compress content when opening sidebar in Question page (#18128) 2021-09-30 13:17:43 -03:00
Jeff Bruemmer
d0e0325190 docs - updated permissions (#17882) 2021-09-30 11:26:33 -04:00
Nemanja Glumac
538a5e6c0a Run all QA DB docker images at once in CI (#18129) 2021-09-30 17:04:25 +02:00
Jeff Bruemmer
2a48071e59 docs - question details sidebar (#17926) 2021-09-30 09:28:22 -04:00
Jeff Bruemmer
349fc25ee4 docs - multi-column joins (#17948) 2021-09-30 09:23:43 -04:00
Alexander Polyankin
ec1496debf Fix cutting of data points in line/area/bar charts (#18119) 2021-09-30 16:07:31 +03:00
Alexander Polyankin
12ff480ede Add cypress tests (#18140) 2021-09-30 15:13:25 +03:00
Jeff Evans
6ff4eda63e Check feature flag on backend /graph PUT API for block permission (#18109)
Check feature flag on backend /graph PUT API for block permission

Check for the `:advanced-permissions` flag in `update-db-permissions!`, when a `:schemas` `:block` entry is present in the graph

Set feature flag in tests when using API

Add new test to ensure failure in the case that feature flag is missing
2021-09-29 19:02:41 -05:00
Noah Moss
d4bc553cba Alert schedule in email template (#18084) 2021-09-29 15:58:52 -07:00
Gustavo Saiani
f044c7d7a8 Remove animation from ViewSidebar under reduce motion (#18102) 2021-09-29 19:07:10 -03:00
Noah Moss
ba1f8dcb63 Include dashboard filters in email & slack subscriptions (#17824) 2021-09-29 14:47:04 -07:00
Nemanja Glumac
c897ff8fea Programmatically wait for the QA DB metadata to load (#18116)
* Set the timeout to 2s because of Mongo
2021-09-29 23:41:54 +02:00
Cam Saul
27e32d7f1a Remove placeholder code for the new 41 premium features (#18126) 2021-09-29 14:31:29 -07:00
Cam Saul
2b0a6c79d7 Remove special cases in tests for Snowflake (#18127) 2021-09-29 13:15:10 -07:00
Cam Saul
ee134cf91d Enforce allowed domains when sending test Pulses (#18122) 2021-09-29 12:20:33 -07:00
Gustavo Saiani
cac3beaaa6 Refactor query builder sidebar (#18098) 2021-09-29 16:06:12 -03:00
Cam Saul
44ccf236cf Minor async require cleanup (#18059)
* Minor async require cleanup

* Sort namespaces
2021-09-29 10:57:45 -07:00
Howon Lee
4853b79368 Revert reversion of error cards details page (#18107)
Overall purpose of PR is to add row drill-ins to the tools to fix broken questions, so you can take a look-see into what the broken questions are.

A tiny nit thing wasn't caught by CI and broke master. This was because there's a CI cache. I can confirm that this didn't hit the CI cache and the other thing that broke isn't breaking anymore
2021-09-29 10:55:11 -07:00
Noah Moss
4dc3974c0d unskip repro for markdown in dashboard subscriptions (#18110) 2021-09-29 09:51:49 -07:00
Alexander Polyankin
b27c8f4b77 Do not truncate X labels in timeseries charts (#18100) 2021-09-29 19:09:10 +03:00
Pawit Pornkitprasan
a31a7d087e Fix loading sample dataset in Redshift (#18089)
- `TEXT` in Redshift is equivalent to `VARCHAR(256)`, use
  `VARCHAR(1024)` instead
- Unskip all tests skipped on Redshift due to sample dataset issue
- Add explicit `:order-by` to `join-source-queries-with-joins-test`
  to make it pass in Redshift as Redshift does not preserve order
  after join (like a lot of other distributed query engines)
- Add `VACUUM` and `ANALYZE` call after INSERT to improve performance
2021-09-29 09:37:13 +07:00
dpsutton
a750e4a57a Unverify cards when they are edited (#17997)
from maz in slack:
Should not remove verification:
 - Moving to another collection
 - Pinning/unpinning
 - Adding/removing an alert on the question
 - Turning sharing on the question on/off
Should remove verification:
 - Editing the query
 - Editing the visualization or viz settings
 - Editing the title or description

This really just identifies when not to remove verification, otherwise
does remove verification. Alerts are not related to questions through
the api so no worries there. Everything else is just excluding
attributes from the diff calculation.

In tests, went perhaps a bit haywire with the macrolet, allowing to
define macros inline rather than farther away from the call site. Used
twice:
- once to optionally add in moderation review into the with-temp. This
macro is handy to ensure we always have a fresh state of card and don't
have leftover changes or verifications. Has to be a macro since i want
to dynamically change whether there are verifications in the with-temp*
vector binding
- a way to more easily reduce repetition when asserting something is
verified, do an action, and assert it is still verified
2021-09-28 16:27:21 -07:00
Howon Lee
d7898af888 Audit cache controls 2 (#18046)
Cache controls all landed but is lacking in the audit capacity wanted for in the notion doc. This PR adds that audit capability and by the by changes the ViewLog model in order to be able to deliver on the question of whether ViewLogs were cache hits or not.
2021-09-28 14:10:57 -07:00
Howon Lee
72a5584d29 Revert "Tool to fix broken questions, details page (#18022)" (#18103)
This reverts commit f94510a34a.
2021-09-28 13:35:09 -07:00
Alexander Lesnenko
20ec1869ee Do not change display on drill to questions (#18008)
* Do not change display on drill down to questions

* unskip repro

* include displayIsLocked explicitly otherwise it breaks almost the entire app
2021-09-28 22:56:05 +03:00
Alexander Lesnenko
64bbf8e7cd do not show time for date columns (#18056) 2021-09-28 22:42:45 +03:00
Howon Lee
f94510a34a Tool to fix broken questions, details page (#18022)
Details page for tools to fix broken questions. Also the PR ran long enough that nemanja found some bugs in the details page. Does not include any loading overlay or anything to indicate that reloads are happening, which is for 41.1 I guess
2021-09-28 12:10:32 -07:00
Jeff Bruemmer
6e487b33fa revise activation guide (#17861) 2021-09-28 15:06:02 -04:00
Alexander Polyankin
e70c2e7ed8 Fix stacked charts breaking waterfall charts (#18093) 2021-09-28 21:19:10 +03:00
Jeff Evans
bca22d9766 Fix BigQuery Percentile and Median expressions not using correct backtick quoting (#17979)
Fix BigQuery Percentile and Median expressions not using correct backtick quoting

Ensure the identifier components are quoted by reifying `ToSql` for the `APPROX_QUANTILES` expression

Add test to ensure query is created properly

Mark `:percentile-aggregations` as being supported in the new driver
2021-09-28 11:16:46 -05:00
Gustavo Saiani
0bcf87123a Simplify function in LoadingAndErrorWrapper (#18081) 2021-09-28 10:02:51 -03:00
Gustavo Saiani
a46baf7ee4 Simplify LoadingSpinner animation in reduced motion (#18082) 2021-09-28 09:23:19 -03:00
Alexander Polyankin
3a2c4d3848 Add total value to static donut chart (#18091) 2021-09-28 15:13:28 +03:00
Nemanja Glumac
f1fcb7544e #18021 Repro: "Recents" list in search should display the Verified badge (#18080) 2021-09-28 13:59:46 +02:00
Alexander Polyankin
9784b89fe8 Revert "Separate positive / negative stacked charts (#18007)" (#18088)
This reverts commit 46c76c95ae.
2021-09-28 11:39:27 +03:00
Pawit Pornkitprasan
3565136042 Fix {0} being shown when locale is "pt" (#17875)
This is a combination of 2 issues:
 1) pt got renamed to pt_BR in x.39.x but the old
    "pt" value may still be stored in the database
 2) when making a release, an unclean build
    directory may be used containing old "pt"
    resource which gets leaked into the release build

1) is fixed by adding a function to treat "pt" as "pt_BR"
to support users who were on "pt" since pre-x.39.
(This is done by finding the closest fallback locale)

2) is fixed by emptying the folder before generating locales
so any old locales are deleted.

Fixes #16690
2021-09-28 10:28:04 +07:00
Pawit Pornkitprasan
594c4b070a Fix saving chart with custom expressions only retains first 2 data series (#17855)
See https://github.com/metabase/metabase/issues/15882#issuecomment-917984049 for detailed explanation.

Fixes #15882
2021-09-28 10:26:44 +07:00
Pawit Pornkitprasan
3826966878 Fix slow query when using nested native question with many rows (#18023)
`query->native` works by having `nativef` throws an exception
which causes `mbql->native` to set native query to `nil` which
then cause the rest of the execution to be skipped.

However, because the existing code skips overriding the native
query for queries already native, the execution is not skipped.

This causes bad performance for nested native question because
`query->native` is called for the sub-query which causes the
sub-query to be executed on its own, potentially without any
limit or filtering.
2021-09-28 09:18:35 +07:00
Jeff Evans
deeebec986 Adjust driver deprecation language ("a future" instead of "the next") (#18083)
Because we can't fully implement all the driver deprecation UX in time for release 41, we will adjust the language to allow flexibility for when to actually start the deprecation clock
2021-09-27 18:29:30 -05:00
Jeff Evans
25aac41480 Add test for ordering when nils are present (#17914)
Add test for ordering when nils are present

Adding test to ensure that we can handle a column containing nils in an ORDER BY clause

Adding `format-name` override for `bigquery-cloud-sdk` to convert dash to underscore in test table names

Adding comment showing IDs of each row in the daily-bird-counts.edn file

Format last column as int to make Oracle happy

Add impls for `presto` and `presto-jdbc` `sorts-nil-first?` as false

Make the `sorts-nil-first?` multimethod accept a base type in order to return an answer

Vertica, at least, has a different answer for different types; see:
https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/AnalyzingData/Optimizations/NULLPlacementByAnalyticFunctions.htm#2

Updating Vertica implementation to consider the `base-type` as per its documentation

Updating all invocations of `sorts-nil-first?` in tests to pass the relevant base type
2021-09-27 16:56:35 -05:00
Greg Wilson
db7e7a0c9b Troubleshooting the app database (#17669) 2021-09-27 16:21:50 -04:00
Jeff Evans
3aeac641be Support query cancellation in new BigQuery driver (#17959)
Support query cancellation in new BigQuery driver

Remove now unused 60 second timeout

Remove a bunch of unneeded code (`with-finished-response`) from the legacy driver

Add support for canceling query, which stops pagination of results

Add test to confirm pagination stops upon cancellation

Add test to confirm that max rows enforcement via middleware prevents unnecessary pages from being fetched
2021-09-27 14:41:45 -05:00
Nemanja Glumac
e157821d61 #9027 Repro: New questions do not appear in 'Saved Questions' until you refresh the browser (#18076) 2021-09-27 20:39:02 +02:00
Nemanja Glumac
4e70f2012b Add initial E2E coverage for "Tools to fix question errors" (#18057)
* Add initial e2e test for erroring questions

* Add repro for #18050

* Add repro for #18048

* Add test section with that contains broken questions

* Improve test and add another scenario
2021-09-27 20:06:38 +02:00
Gustavo Saiani
6fbb1311b4 Start Cypress browser with prefers-reduced-motion set to true (#18041) 2021-09-27 14:54:55 -03:00
Nemanja Glumac
450bbfd297 #18063 Repro: Pin map with null locations shows tooltip of the wrong row (#18070) 2021-09-27 18:58:57 +02:00
Nemanja Glumac
8fd9318e32 Git ignore clj-kondo cache (#18071) 2021-09-27 18:57:40 +02:00
Alexander Polyankin
46c76c95ae Separate positive / negative stacked charts (#18007) 2021-09-27 19:35:50 +03:00
Nemanja Glumac
53c85aa80c #18061 Repro(s): Pin map only containing null location results crashes the frontend (#18073)
Covers all three scenarios listed in the original issue.
2021-09-27 18:32:29 +02:00
Alexander Polyankin
3c0bb00c31 Add labels to settings fields (#18072) 2021-09-27 18:50:41 +03:00
Anton Kulyk
0c81e4fdf5 Fix personal sub-collections are hidden in item picker (#18068)
* Enable repro test

* Fix personal subcollection in item picker hidden
2021-09-27 18:35:13 +03:00
Alexander Lesnenko
c276ea3381 Fix drillPK for composite keys (#18039) 2021-09-27 14:33:43 +03:00
Alexander Polyankin
24988bba20 Do not stack up channels when creating a new dashboard subscription (#18054) 2021-09-27 13:04:10 +03:00
Anton Kulyk
ba95b27028 Fix dashboard filters get invisible while dragging & text selection while dragging (#18053) 2021-09-27 11:48:25 +03:00
Alexander Kiselev
67470a082c Fix #18003 regression by adding a check for borderless buttons (#18020)
* added check for borderless buttons when setting compact padding

* fix my own silly regression

* added visual tests for run button regressions

* added minWidth to percy snapshot

* shoudl have read the docs

* Sync VIEWPORT_WIDTH and percy snapshot width
2021-09-24 14:01:32 -07:00
Jeff Bruemmer
e521360ac2 update link in troubleshooting article (#18037) 2021-09-24 16:53:46 -04:00
Alexander Polyankin
1280096183 Fix approved domains validation for alerts and dashboard subscriptions (#18049) 2021-09-24 21:55:31 +03:00
Noah Moss
97906486c4 Escape HTML in markdown cards when rendered for emails (#18000) 2021-09-24 10:26:49 -07:00
Alexander Lesnenko
42e2bda817 Update subscriptions and alerts tables when data changes (#18052) 2021-09-24 19:41:44 +03:00
Maz Ameli
f9143d322e Grammar and microcopy tweaks to Unsubscribe modal (#18040)
* grammar and microcopy tweaks

* update cypress test

* fix another test

* update test again
2021-09-24 09:40:36 -07:00
Anton Kulyk
571488b05a Fix x-ray dashboards crash on first open (#18045) 2021-09-24 18:47:05 +03:00
Anton Kulyk
c51553d645 Fix Audit logging not showing ad-hoc native queries (#18044)
* Fix test's describe block

* Mention #16845 repro

* Assert native query text is displayed in Audit

* Enable the repro test

* Fix ad-hoc native query not displayed in Audit correctly

* Don't display native query sidebar in read-only mode
2021-09-24 18:44:13 +03:00
Anton Kulyk
c225ace8e6 Fix text selection while rearranging table columns (#18032) 2021-09-24 11:34:09 +03:00
Anton Kulyk
3f7420d63a Fix drag-n-drop in dashboard visualisation settings modal (#18031)
* Add a prop to bubble mouse events on SandboxedPortal

* Fix drag-n-drop on dashoboard's viz settings modal

* Enable repro test
2021-09-24 11:32:36 +03:00
Alexander Polyankin
b557b69ce2 Skip subscriptions audit tests (#18038) 2021-09-23 23:13:05 +03:00
Nemanja Glumac
92f7549bc4 #18009 Repro: Nodata user can create dashboard subscription, but receives an error (#18014) 2021-09-23 21:37:21 +02:00
Alexander Lesnenko
10f40205f5 Handle composite pk filters (#18016)
* Handle composite PK filters as well as filtering by non unique PK fields

* unskip repro

* fix

* fix

* fixes
2021-09-23 22:35:30 +03:00
Howon Lee
82742ccc1f Tools to fix broken questions timeout fix (#17985)
Previous implementation was dog slow. This one is faster
2021-09-23 12:33:24 -07:00
Alexander Lesnenko
a4e85417bd add PK icon (#18015)
* add PK icon

* key -> label
2021-09-23 22:05:06 +03:00
Nemanja Glumac
4bb0042959 #18028 Repro: X-ray dashboards crash on first opening immediately after they are saved (#18033) 2021-09-23 20:02:25 +02:00
Alexander Polyankin
14a775f173 Revert changes to ModalRoute (#18034) 2021-09-23 20:51:05 +03:00
Jeff Bruemmer
7014115160 docs - update api doc gen code (#17994)
* update api doc gen code

* update test
2021-09-23 13:37:21 -04:00
Dalton
c74164ea3c Fetch fields before parsing parameter values so we correctly parse values for boolean fields (#17999)
* add template tag fields as dependent metadata for native queries

* check for a field_id property added by getValueAndFieldIdPopulatedParametersFromCard

* Add NativeQuery dependentMetadata unit test

* add test for loadMetadataForQuery
2021-09-23 09:22:31 -07:00
Nemanja Glumac
4188b2b5dd #6239 Repro: Not possible to sort by Custom Expression fields (#18029) 2021-09-23 18:21:27 +02:00
Ariya Hidayat
d5377a5a08 Fix #15893 by disallowing literal left-hand side in comparison (#18017) 2021-09-23 07:47:26 -07:00
Alexander Lesnenko
9393a03b1d Subscriptions and alerts audit (#17765)
* subscriptions and alerts audit

* Add tables

* Add tables

* Extract to lib

* Extract to lib

* Add modal

* Add modal

* Add modal

* Fix modals

* Fix modals

* Add children for displaying modals

* Add children for displaying modals

* Add children for displaying modals

* Add children for displaying modals

* Add edit dialogs

* Add edit dialogs

* Add edit dialogs

* Add edit dialogs

* Remove deletion

* Remove deletion

* Add users

* Add users

* Fix selection issues

* Add placeholder

* Add placeholder

* Add delete button

* Fix wrapping issues

* F

* Small fixes

* Add reloading

* fixes

* cypress specs

* fixes

* post rebase fixes

* rebase fixes

* review fixes

Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
2021-09-23 17:35:10 +03:00
Nemanja Glumac
a5b85e2c3b Fix ENV case for QA_DB_ENABLED (#18027) 2021-09-23 15:44:14 +02:00
Jeff Bruemmer
419a8266ad docs - restore original file name (#18026)
* restore original file name

* links
2021-09-23 09:01:10 -04:00
Alexander Lesnenko
467eca89ac show meaningful error for waterfall chart of multiple series questions (#17992)
* show meaningful error for waterfall chart of multiple series questions

* increase readability
2021-09-23 14:31:04 +03:00
Alexander Polyankin
7401832362 Fix default formatting options for numeric types (#17978) 2021-09-23 14:27:55 +03:00
Alexander Lesnenko
14e742b89c fix tables are not clickable in recents (#17995) 2021-09-23 12:32:59 +03:00
Ariya Hidayat
2bd3d707a1 Fix #17975 by supporting getting MBQL field literal (#17982) 2021-09-22 17:24:35 -07:00
dpsutton
de39de8a35 Static Viz Formatting (#17957)
* Formatting

return a format string so it can be used over multiple rows. The rules
for formatting are quite annoying because there are defaults that are
assumed rather than present. IE, if you set a column as currency it
doesn't set the number style sometimes and defaults to USD without that
being in the settings. In the future would be far preferable to always
create a fully fleshed map of defaults rather than inferring them in
random places.

* appease our doc string supervisor

* Include column information for formatting numbers

really important for requiring two decimal places by default on doubles
and none on integers. Its close to correct ignoring it and using
"#,###.##" and this leaves non decimal places on integers and allows
only up to two on doubles, but things like 31.10 will format as 31.1 and
that is improper

* Remove unneeded metabase.test

* Update tests with nil column

* Get global viz settings in middleware, pass entire to formatting

Passing the entire viz settings to the formatting stuff makes the
calling code much simpler and the places where we merge global settings,
possibly get currency settings, etc, just in one place. We already had
the col information there so just use it.

* Remove public settings now that we get it from the metadata
2021-09-22 17:02:06 -07:00
Alexander Kiselev
428bbe31d4 Fix #17397 - "Showing first 2000 rows" is always displayed when results are loading (#17954)
* Check for existing result set when displaying
"Showing [X] rows" instead of the max limit

* added cypress test

* broke up nested ternary operators in QuestionRowCount
2021-09-22 16:10:51 -07:00
Alexander Kiselev
1fe1c7a649 Fix #16810: Dashboard "isDirty" property is set to true after the Dashboard title is updated. (#17955)
* added isDirty flag to SET_DASHBOARD_ATTRIBUTES action

* added reducer tests for SET_DASHBOARD_ATTRIBUTES with isDirty

* lint
2021-09-22 13:03:07 -07:00
Gustavo Saiani
0bb97c2039 Wrap long question titles to prevent overflows (#17996) 2021-09-22 16:26:16 -03:00
Alexander Polyankin
713ff5a84e Add unsubscribe user modal in admin (#17803) 2021-09-22 20:34:50 +03:00
Anton Kulyk
1982ba3ab9 Allow searching a table in a specific database in DataPicker (#17987) 2021-09-22 19:19:48 +03:00
Howon Lee
adc985e0b6 Audit cache controls (#18001)
We added cache control fields for dashboard and database and actually use it for cards: presumably EE folks want to audit that stuff. Here is the addition of those fields to the table views.
2021-09-22 04:25:53 -07:00
pawit-metabase
fa86e49180 fix wrong data used for click actions in old pivot table (#17937)
In `getTableClickedObjectRowData`, we try to get the
original row of the data from the rowIndex but because
the rowIndex of the pivoted table and the original table
does not necessarily match, we get the wrong data.

This commit fixes it by storing a mapping between
pivoted (row, col) and the original row number and using
that to determine which row to use for the data.

Fixes #17920
2021-09-22 09:23:33 +07:00
pawit-metabase
ae25011ff2 fix dashboard subscription default value for non-field filters (#17967)
When loading dashboard filters, the default value is in `:default`
not in `:value`. In the field filter code path, the default is
copied to `:value`. Fix the issue by calling the same code for
non-field filters too.

Fixes #15705
2021-09-22 09:23:00 +07:00
Cam Saul
da1c518eb6 Improve defsetting validation and other misc small tweaks (#17896)
* Move email->domain and email-in-domain? util functions to metabase.util

* Improve the error handling for with-temp a little more.

* Extra error context for with-temporary-setting-values

* Improve Setting docstring forms validation: handle aliased forms like `i18n/deferred-tru`

* Fix missing :require
2021-09-21 17:55:56 -07:00
Cam Saul
faf007aaa4 DELETE /api/ee/audit-app/user/:id/subscriptions archive Pulses created by user (#17981) 2021-09-21 17:55:38 -07:00
Cam Saul
d925eeb5e0 Add DashboardSubscription and Alert audit queries (#17818)
* Add DashboardSubscription and Alert table audit queries

* metastore -> premium-features
2021-09-21 17:55:29 -07:00
Dalton
d7c1e458bc When fetching field also fetch field associated with its human_readable_field_id (#17958)
* When fetching Field also fetch its associated human_readable_field_id

* add unit tests
2021-09-21 15:39:05 -07:00
Noah Moss
0305c346d6 Fully deprecate alert deletion, and rename some alert/subscription endpoints (#17740)
Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
2021-09-21 12:16:21 -07:00
Noah Moss
094211eb26 GeoJSON URL validation fix (#17990) 2021-09-21 11:14:03 -07:00
Alexander Lesnenko
1f3b45aba7 handle unaggregated data warning for waterfall chart (#17988) 2021-09-21 19:15:10 +03:00
Dalton
595d75f284 treat empty string parameter in url like it is unset (#17912)
* treat empty string parameter in url like it is unset

* refactor parameter collection utils
2021-09-21 08:57:57 -07:00
Dalton
7ec9b026c6 Disable parameter widget input when not mapped to a card on dashboard (#17956)
* Add meta/Dashboard utils for checking mapped dash params

* Add tests for meta/Dashboard utils

* Add disabled prop to TextWidget

* Disable widgets using isDashboardParameterWithoutMapping fn

* Update tooltip text

Co-authored-by: Maz Ameli <maz@metabase.com>

Co-authored-by: Maz Ameli <maz@metabase.com>
2021-09-21 08:57:25 -07:00
Alexander Lesnenko
c4ab8329df Allow using Grid map in native questies questions (#17930)
* Fix grid map is not rendered for native questions

* add check for map button
2021-09-21 17:24:55 +03:00
dpsutton
6d440668a7 For sparklines, check that viz type is line (#17950)
* For sparklines, check that viz type is line

this actually goes to fix waterfalls. They would match these
requirements but the viz type of waterfall would give results that would
dip out of the viewport. Fallback to table rendering

* Prevent waterfall rendering as sparkline

* please run that cancelled test again, GitHub®
2021-09-21 08:45:33 -05:00
Alexander Polyankin
3c417b001b Fix whitelabel overriding CSS value priority (#17924) 2021-09-21 15:06:19 +03:00
Anton Kulyk
3ea94d1503 Fix incorrect table names on join dimensions (#17976)
* Add reproduction for #17968

* Fix showing incorrect join field table names

* Test previous results str
2021-09-21 11:11:06 +03:00
Ariya Hidayat
5581b7ba6b Add repro for #17975 (#17980) 2021-09-20 14:26:05 -07:00
Jeff Evans
9b7c713b2a Handle retryable exceptions in new BigQuery driver (#17908)
Add separate catch clause for BigQueryException, to `execute-bigquery`, which conveniently includes a property to indicate whether it's retryable, and add that to the ex-data map

Add test that confirms a retryable exception is, in fact, retried
2021-09-20 16:21:17 -05:00
Alexander Polyankin
d92338ba61 Fix combined tooltip for charts (#17946) 2021-09-20 20:54:40 +03:00
Cam Saul
da97222e59 EE API endpoint code reorganization (#17913)
* EE API endpoint code reorganization

* Remove accidental commit

* test fixes 🔧

* Remove unused namespace

* Remove unused var

* Rename metabase-enterprise.audit.* -> metabase-enterprise.audit-app.*

* Move the new delete subscriptions endpoint from :advanced-config -> :audit

* Prettier
2021-09-20 10:37:29 -07:00
Alexander Lesnenko
6035c777d8 Fix missing translation of Others on the row chart (#17972) 2021-09-20 20:37:14 +03:00
Alexander Lesnenko
91d12f3765 Fix missing formatting on the x axis of the row chart (#17974) 2021-09-20 20:36:51 +03:00
Alexander Kiselev
361d8816ec added padding override to .RunButton class (#17953) 2021-09-20 09:57:49 -07:00
Anton Kulyk
3ecc0044b1 Select temporal units for join date-time dimensions (#17883)
* Test join's setDimension methods can remove dimensions

* Specify temporal-unit for Join unit tests data

* Ensure join dimensions' temporal units are the same

* Display dimension's temporal unit on Join UI

* Add E2E test for join fields temporal units

* Select temporal units for join dimensions

* Sync parent and join dimensions temporal units

* Refactor Join dimension setters

* Update subdimension check

* Update overwrite check
2021-09-20 19:45:04 +03:00
Ariya Hidayat
08d0e20971 Update order-by field when the breakout changes (#17960)
This should fix #16770.
2021-09-20 09:25:41 -07:00
Anton Kulyk
3a38c1b267 Fix questions with joins or filters cause re-run overlay after first save (#17971)
* Fix typo

* Add unit tests for `normalizeQuery`

* Normalize query clause classes for comparison

* Enable the repro test

* Rename variable
2021-09-20 19:13:33 +03:00
Alexander Polyankin
9b2064e270 Fix data points for scatter charts (#17973) 2021-09-20 18:23:18 +03:00
Alexander Lesnenko
25179f743e Move block permission under advanced permissions flag (#17927)
* Move block permission under advanced permissions flag

* fix flag name
2021-09-20 14:48:14 +03:00
Alexander Polyankin
c039d43239 Fix grid map tooltips without metric column (#17969) 2021-09-20 14:26:16 +03:00
Kim Hallen
a18eb400ea Make docs a bit more clear what values to use for MB_LDAP_SECURITY. (#17745) 2021-09-20 15:57:56 +07:00
Anton Kulyk
da6f78d57e Fix SaveQuestionModal's submit button state (#17951) 2021-09-20 10:36:44 +03:00
pawit-metabase
4dc1ab826a Fix issues reverting dashboard (#17899)
* fix reverting dashboard with card deletion

`delete-dashboard-card!` expects the :dashboard_id
parameter to be defined.

* fix frontend issues related to dashboard reverts

1) fix the dashboard not being reloaded to the
   reverted version after revert
2) fix the history list being reloaded to include
   the latest change
2021-09-20 09:30:38 +07:00
Alexander Polyankin
43cf431767 Fix the bulk actions bar on the archive page to reveal the last item (#17947) 2021-09-17 21:37:00 +03:00
Dalton
0d9ffe2e52 fix clearing of sidebar state when removing a parameter (#17934)
* fix clearing of sidebar state when removing a parameter

* add a cy test
2021-09-17 09:25:34 -07:00
Alexander Lesnenko
4e8716c6e6 Add approved domains for notifications setting (#17685) 2021-09-17 19:02:58 +03:00
Alexander Polyankin
5e961419ba Show error messages when rendering card fails (#17929) 2021-09-17 15:42:20 +03:00
Anton Kulyk
7d6e031bb0 Feature | More Granular Caching Controls (Frontend) (#17802)
* Rename dashboard details edit action

* Use render props at dashboard edit form

* Add enterprise caching plugin

* Move dashboard entity forms to own file

* Make FormField's margin configurable

* Pass custom style to FormField

* Use null as a default cacheTTLFormField value

* Add tests for DashboardDetailsModal

* Add cache_ttl field to DashboardDetailsModal

* Add tests for CreateDashboardModal

* Test cache_ttl is invisible when creating a dashboard

* Remove not used mocks

* Add tests for EditQuestionInfoModal

* Move question entity forms to own file

* Add cache_ttl field to EditQuestionInfoModal

* Test cache_ttl is invisible when creating a question

* Extract CacheTTLField component

* Don't show cache field if caching is disabled

* Fix typo

* Update cache_ttl field look

* Revert "Pass custom style to FormField"

This reverts commit 3944ca8ff1dcad478f0f1c3a1973f454447c88c1.

* Revert "Make FormField's margin configurable"

This reverts commit ca7dc434532038da736012147f6889e6cc01ec11.

* Fix CacheTTLField width

* Add descriptionPosition prop to FormField

* Add DatabaseCacheTTLField

* Show cache_ttl field on database form

* Use 24h as a default database cache TTL field value

* Fallback to database cache_ttl in question form

* Remove console.log

* Fix request body assertion for CreateDashboardModal

* Fix request body assertions for EditQuestionModal

* Fix request body assertions for DashboardDetailsModal

* Fix cache_ttl not included in `PUT /api/card/:id`

* Use simple for for EditQuestionInfoModal

* Refactor how unit tests mock caching settings

* Add dashboard caching EE test

* Add question caching EE test

* Add caching e2e test for database add/edit

* Remove debug stuff

* Add error state to CacheTTLField

* Fix DB cache field reverts to default value on 0

* Validate cache_ttl field

* Add getQuestionsImplicitCacheTTL helper

* Remove redundant tests

* Remove not used import

* Nomalize `cache_ttl: 0` to null

* Fix duplicated card update request

* Add QuestionCacheTTLField component

* Add test-id to Radio's option names

* Use a new cache TTL field for questions

* Check setting cache_ttl to null in E2E tests

* Style question cache TTL field

* Add dashboard ID to query request body

* Extend `duration` formatting helper to support hours

* Fix default caching duration display

* Fix tests

* Fix old dashboard edit action title

* Fix missing translations

* Add prop types to EditQuestionInfoModal

* Remove `test.todo`

* Simplify `getQuestionsImplicitCacheTTL`

* Use `space` style helper

* Add `key` prop to `jt`

* Move time coverting utils to lib/time

* Hide caching field label if just showing the input

* Fix unit tests

* Fix flacky E2E test

* Add hover style for "More options" control

* Fix missing translation

* Use placeholder for cache inputs

* Fix E2E tests to use cache field's placeholder

* Feature flag for caching UI
2021-09-17 12:15:58 +03:00
Dalton
550152d5c5 invalidate revision entities cache when questions/dashboards updated/deleted (#17887)
* invalidate revision entities when questions/dashboards updated/deleted

* you can't update a revision

* add a cy test to cover revision cache clearing

* let's be a little looser with revision text
2021-09-16 16:57:17 -07:00
Jeff Evans
f0b4f2f7a1 Handle REPEATED mode fields in BigQuery sync (#17907)
Recognize mode=REPEATED and return :type/Array for it

Add test for temp table using an array type column to ensure base type is recongized properly
2021-09-16 13:14:32 -05:00
Gustavo Saiani
b1d63f4a06 Do not display dashboard sticky filter container if no filters set (#17928) 2021-09-16 15:05:55 -03:00
Cam Saul
81a1a95952 Add subscription-allowed-domains allow list Setting (#17897)
* Add subscription-allowed-domains allow list Setting

* Move email->domain and email-in-domain? util functions to metabase.util

* Fix missing require

* Test fix 🔧

* Remove useless namespace

* Make subscription-allowed-domains a :string Setting rather than :csv
2021-09-16 11:02:09 -07:00
Alexander Polyankin
624e5c1179 Fix data points formatting for multi-series (#17925) 2021-09-16 20:49:40 +03:00
Howon Lee
b4b5200ee8 Tools to fix broken questions (ee) (#16842)
Tools are there. Modal is not, along with some styling, but BE has been languishing for months so I wanted to get this in
2021-09-16 01:04:38 -07:00
Ariya Hidayat
80172ee61c Test the JAR with Java 17, the new LTS (#17911) 2021-09-15 19:41:43 -07:00
pawit-metabase
72727a23d6 dashboard filter: do not display "No matching..." if not filtered (#17900)
Fixes #17211
2021-09-16 09:21:34 +07:00
Dalton
aab00d7922 fix a few prop errors causing console warnings (#17840)
* fix a few prop errors causing console warnings

* fix LastEditInfoLabel test
2021-09-15 18:19:29 -07:00
Ariya Hidayat
6939d4af39 Remove some left-over references to Leiningen (#17909)
Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-09-15 14:06:42 -07:00
Alexander Lesnenko
0d90f0adfe do not unlock question display if it was locked in unsensible visualization (#17860) 2021-09-15 20:36:27 +02:00
Alexander Polyankin
55f5b9e77d Fix whitelabling for chart colors (#17903) 2021-09-15 20:33:18 +03:00
Ariya Hidayat
227a1e9c6b Tweak Avatar: don't use attrs() with styled (#17890) 2021-09-15 09:46:47 -07:00
Jeff Evans
66ac8c99d3 Presto JDBC driver: hide Kerberos related properties when Kerberos is not enabled (#17868)
Make use of new visible-if property in plugin definition
2021-09-15 09:29:21 -05:00
pawit-metabase
5017651f35 Update URL when converting to native query (#17873)
In addition, mode should be switched to "view" to
remove "/notebook" from URL.
2021-09-15 09:24:35 +07:00
pawit-metabase
eaf06d2131 Fix showing saved value in language picker (#17853)
The locale list sent to the UI is formatted "pt-BR" but
when it is saved to the database, we re-format the locale to
"pt_BR", thus on next load, the UI cannot match the saved locale
with the locale list.

Fix the issue by using normalized value (e.g. "pt_BR") in the
available locale list.

Fixes #15657, fixes #16654
2021-09-15 09:22:59 +07:00
pawit-metabase
77c202ebe3 Fix "Include today" for relative "Next" (#17854)
"include-current" was implemented for "prev" but not for "next".

Fixes #17551
2021-09-15 09:21:08 +07:00
pawit-metabase
b178e30e81 i18n: do not remove missing plural from translation (#17799)
The ttag library expect the plural array to be exactly the size as
the number of plural forms defined in the header.

If we remove empty plural, the array will have the wrong size and
the library will crash when the trying to use the non-existent
plural.

By leaving the empty string there, the ttag library will correctly
detect it and use the English version for the missing variant.

This does not affect the backend because the backend does not
support plurals.

Fixes #16323
2021-09-15 09:19:05 +07:00
Cam Saul
8efd53712e Add new Settings (placeholders) for the new 0.41.0+ premium features (#17891)
* Add new Settings (placeholders) for the new 0.41.0+ premium features

* Code cleanup

* Add new features to the `:premium-features` Setting (for FE consumption)

* Fix busted ns declarations
2021-09-14 19:02:10 -07:00
Dalton
698109ece4 combine sidebar state for various dashboard sidebars (#17843)
* combine sidebar state for various dashboard sidebars

* replace hideClickBehaviorSidebar action with closeSidebar

* move sidebar name strings to a constants file

* add some tests
2021-09-14 18:40:26 -07:00
Cam Saul
e14854c938 Better with-temp error messages (#17889)
* Better with-temp error messages

* Undo wacky indentation
2021-09-14 17:10:39 -07:00
Alexander Kiselev
3c83fb6e54 Removed extra border-bottom on EntityItemWrapper (#17867)
styled component
2021-09-14 16:54:27 -07:00
Cam Saul
86be4ce403 Test fix 🔧 (#17888) 2021-09-14 16:41:31 -07:00
Jeff Bruemmer
bd53aed6bc docs - update API docs format (#17716)
* update API docs format

* account for other terminal punctuation

* clarify api namespace target

* update schema test, add-period test

* update period test

* parens

* test endpoint-section

* cleanup

* Cam edits

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>

* trim whitespace

* file newlines

* Sort namespaces

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: Cam Saul <github@camsaul.com>
2021-09-14 14:52:57 -07:00
Alexander Polyankin
99e9e3304d Do not reset filters when saving, cancelling, refreshing dashboards periodically (#17165) 2021-09-14 21:17:09 +03:00
Alexander Lesnenko
a9dd888e4c unskip 17738 repro (#17877)
* unskip 17738 repro

* move the repro to run in EE
2021-09-14 19:11:49 +02:00
Alexander Polyankin
b7d52e5f23 Add extra space and text trimming for static viz axes labels (#17859) 2021-09-14 18:09:44 +03:00
Ariya Hidayat
4158b783ae Remove outdated resolutions in package.json (#17863) 2021-09-14 08:01:13 -07:00
dpsutton
89b1cbe72b Handle expressions viz settings (#17866)
added the viz-settings parsing middleware to static viz. Column settings are
spec'd for regular columns and by name, but we forgot expressions apparently.
2021-09-14 09:34:02 -05:00
dpsutton
c1de8e1397 Ignore hidden tables in search (#17804) 2021-09-14 09:29:14 -05:00
Anton Kulyk
6aae28233d Add E2E test for joins on multiple fields (#17878) 2021-09-14 14:18:13 +03:00
Anton Kulyk
277e83f483 Fix removing a notebook section can remove other sections (#17727)
* Add test ID for notebook's action buttons

* Add repro for #17712

* Use `Join.clean` in join step's clean callback

* Always show a remove icon

* Fix referencing an empty dimension

* Improve Join's validity check

* Don't cleanup incomplete join sections

* Fix structured query tests

* Don't use MBQL field literals in notebook tests

https://github.com/metabase/metabase/issues/14824
2021-09-14 13:06:41 +03:00
pawit-metabase
d4e71d076e Unskip: Cannot add filter for an integer field in a question based on a saved native question (#17872)
This was already fixed since 0.40.
2021-09-14 16:34:31 +07:00
Noah Moss
552ab7d94a New email design for dashboard subscriptions, alerts and pulses (#17781) 2021-09-13 15:05:53 -07:00
Cam Saul
075124cc90 Refactor audit queries to use defmethod instead of ^:internal-query-fn metadata (#17817)
* Refactor audit queries to use defmethod instead of weird ^:internal-query-fn metadata

* Sort namespaces

* Test fix 🔧

* invoke-internal-query -> resolve-internal-query

* Fix indentation 🔧

* Minor code cleanup

* Revert change to pulse/schedule-frame?

* More test fixes 🔧
2021-09-13 14:56:14 -07:00
Cam Saul
b0e5822fd0 Fix race conditions when loading drivers (part 2) (#17368)
* Fix race conditions when loading drivers (part 2)

* Test fixes & code cleanup
2021-09-13 14:55:52 -07:00
Ariya Hidayat
90930dc6ea Fix test title (#17864)
Co-authored-by: Nemanja <31325167+nemanjaglumac@users.noreply.github.com>
2021-09-13 12:48:18 -07:00
Dalton
0025354d1a split dashboard.js into actions + reducers + utils (#17816)
* split dashboard.js into actions + reducers + utils

* move test files
2021-09-13 12:40:09 -07:00
Gustavo Saiani
7905f34515 Update logic to hide db add/edit fields (#17845) 2021-09-13 16:35:15 -03:00
Alexander Lesnenko
86e196b997 permissions fixes (#17757)
* permissions fixes

* database block to granular should set no self service

* unskip repro
2021-09-13 21:43:40 +03:00
Howon Lee
fd8865a845 Cache ttls nillable now (#17852) 2021-09-13 11:18:20 -07:00
Cam Saul
1a29ab8b28 Delete user pulse/alert/dashboard sub subscriptions when User becomes inactive (#17809)
* Delete user pulse/alert/dashboard subscription subscriptions when they get archived

* Automatically archive Pulses when last subscription is deleted (#17812)

* Automatically archive Pulse when its last subscription is deleted

* Test fix 🔧

* Fix occasionally-failing rotate-encryption-key!-test

* Update pulse_test.clj
2021-09-13 11:17:31 -07:00
Albert Lai
90289d4a7a Update 05-visualizing-results.md (#17684)
Correct typos
2021-09-13 10:04:05 -07:00
Ariya Hidayat
e229c5dbde Visual test for UserAvatar component (via _internal) (#17847) 2021-09-13 09:38:29 -07:00
Dalton
1129627336 move fullscreen toggle onClick to button from icon el (#17844) 2021-09-13 09:35:32 -07:00
Dalton
48658c630a Don't pass a component with propTypes to forwardRef (#17836) 2021-09-13 09:35:17 -07:00
Gustavo Saiani
fdcb310112 Update link to e2e doc page (#17857) 2021-09-13 13:26:14 -03:00
Alexander Polyankin
e865ed59f1 Fix dashboard subscriptions sidebar for sandboxed users (#17823) 2021-09-13 19:07:42 +03:00
Jeff Evans
75f2207de3 Fix support for NUMERIC and BIGNUMERIC types (#17837)
Add parameter handling for BigDecimal that checks whether the value is in range for BIGNUMERIC or BIGDECIMAL and sets accordingly

Updating parameter test to hit both these cases

Modifying test code/macros to support a with-table semantic for testing the decimal types via a temp table

Writing new test to confirm that all numeric types are synced correctly and can be queried for
2021-09-13 10:02:34 -05:00
Greg Wilson
874750ee04 Filling in missing text (#17835) 2021-09-13 10:23:15 -04:00
Jeff Bruemmer
6e046fb87e docs - dev guide links (#17842)
* raw tags

* index to start

* update toc link

* reference link
2021-09-11 09:08:02 -04:00
Ariya Hidayat
f3a170994c Basic skeleton of front-end dependencies analyzer (#17743)
* Basic skeleton of front-end dependencies analyzer

* Parse enterprise/frontend

* Handle good ol' require

* For sanity, bail out immediately when encountering a parse errr

* Split into commands (currently returning JSON)

* Filter dependents from stdin

* Track down all dependents, including the indirect/transitive ones

* Fix filtering not including the enterprise

* Map a directory to its index.js, if it exists

* Refactor common functions

* Matrix and count dependents
2021-09-10 20:40:17 -07:00
Howon Lee
9774e08da5 BQ expression fixes (#17347)
This was a miserable grind in the old BQ syntax but a happy fun time in the new BQ syntax, basically just turning it on and squashing a bunch of test bugs.

One test bug to note especially is that the underscore-transformed set of bird scarcity data for the bird scarcity tests is actually necessary, because BQ will hit you with a complaint about underscores even if you successfully and correctly quote the table names.
2021-09-10 14:49:37 -07:00
Ariya Hidayat
9863bd7834 Ignore the coverage of semi-constructors only for type hints (#17841) 2021-09-10 14:48:09 -07:00
Dalton
b26fadd75a fix PropTypes console warning (#17838) 2021-09-10 14:32:26 -07:00
Dalton
520a8a16fc add keys to arrays of routes (#17839) 2021-09-10 14:32:14 -07:00
pawit-metabase
af83e559a9 Do not bin relation fields even if they have fingerprints (#17782)
Fixes #17768
2021-09-10 14:45:45 +07:00
Howon Lee
73c7a9d1ac DB and Dashboard-contingent caching backend (#17679)
There's more to come WRT the audits, but anton and I agreed to merge something faster and work on that stuff after
2021-09-09 18:20:00 -07:00
Dalton
faad557b6d don't show exact seconds for a formatted relative time (#17828)
* don't show exact seconds for a formatted relative time

* add a couple of getRelativeTimeAbbreviated tests
2021-09-09 16:04:55 -07:00
Alexander Polyankin
bae75e2045 Fix settings saving behavior (#17810) 2021-09-09 21:59:48 +03:00
Cam Saul
3e86afd683 Unify .dir-locals.el files (#17815) 2021-09-09 10:02:33 -07:00
Gustavo Saiani
1872363942 Remove unused arguments from functions (#17805) 2021-09-08 18:50:38 -03:00
Noah Moss
5c30146b6d Allow creating & editing dashboard subscriptions if you have view-only access to a collection (#17722) 2021-09-08 14:41:24 -07:00
Dalton
9a0c989fd1 translate options in SchedulePicker (#17792) 2021-09-08 14:25:51 -07:00
Dalton
76ccd32a46 remove a random console.log call (#17806) 2021-09-08 13:19:46 -07:00
Alexander Polyankin
755d8a1aa7 Adds paid plan-specific links (#17748) 2021-09-08 23:03:35 +03:00
dpsutton
6aba6f1e8a Static viz send viz settings (#17736)
* Pass along date formatting

* extract and rename some things

* Number formatting

* Update tests

* Improve test validation of svg labels

* Clean up tests

* Move static-viz interface file to custom file
2021-09-08 14:31:19 -05:00
Nemanja Glumac
8bdcb06c1d Attempt to fix #17751: filter widget input value overflowing (#17761)
Merging on behalf of Nemanja

* Attempt to fix #17751

* Revert limiting max-width on a parent div

* Inherit min-width from a parent div

* Unskip repro
2021-09-08 19:48:40 +02:00
Dalton
a697c29aad don't set pulse on SharingSidebar mount to prevent race condition when moving between sidebar views (#17791)
* don't set pulse on SharingSidebar mount

* remove some old, unused code
2021-09-08 09:50:48 -07:00
Dalton
037ee68ccd let users disable attachments with questions checked (#17793)
* let users disable attachments with questions checked

* use more declarative assertions in unit tests

* use aria-label over testid

* translate aria label
2021-09-08 09:50:31 -07:00
Nemanja Glumac
0f2aa5aff7 Move notifications spec to the onboarding folder (#17794) 2021-09-08 12:43:45 +02:00
Doni Rubiagatra
faf54500a0 bugfix: browse data sorted using display name (#17542) 2021-09-08 14:35:01 +07:00
pawit-metabase
2ffb8cb0a7 dimension list: hide sub-dimensions for fields that are FK (#17783)
Fixes #16787
2021-09-08 10:37:30 +07:00
pawit-metabase
e10adcdff6 Fix SAML login with OpenAM (#17785)
OpenAM SAMLResponse contains "\r\n" every 76 characters
leading our SAML code to think it's not base64-encoded.

Fix by relaxing our valid base64 check to ignore all spaces.

Fixes #15567
2021-09-08 10:33:51 +07:00
pawit-metabase
32c5b2a4ba Fix unable to click "Learn more" on custom expression (#17774)
* expression editor: allow clearing help text with Escape key

Move the code to clear help text to "clearSuggestions" method
allowing the Escape key to also be used to close the help popup.

* expression editor: don't show error on window unfocus

* expression editor: allow clicking on "Learn more"

Clicking on the "Lean more" link removes the focus
from the input box, causing the help dialog to get
hidden and become unclickable.

Fix by cancelling the mouse down event causing the
input box to maintain the focus.

Fixes #17548

* add cypress test
2021-09-08 09:49:53 +07:00
Nemanja Glumac
3ffed24722 #17763 Repro: Trying to set "Granular" permissions after "Block" is broken (#17787) 2021-09-08 00:07:56 +02:00
Nemanja Glumac
15b2a6d1af #17777 Repro: Hiding all tables in data model removes them from the permissions page (#17779) 2021-09-07 23:51:26 +02:00
Dalton
6561cda1d8 remove Parameters component defaultProps to get rid of warning message (#17788) 2021-09-07 13:09:51 -07:00
Dalton
37810686b6 rmv .info.js files from coverage (#17766) 2021-09-07 10:24:05 -07:00
Noah Moss
6df2894bab XLSX export formatting for pulse attachments (#17755) 2021-09-07 07:05:01 -07:00
Nemanja Glumac
3f083b8da8 #16785 Repro: Search shows hidden tables (#17786) 2021-09-07 15:29:40 +02:00
Alexander Polyankin
5ae6e2d0c1 Fix sorting admin sections by order (#17759) 2021-09-07 14:58:06 +03:00
Greg Wilson
6a6e1c6cd3 Fixing a missing link in Markdown (#17735) 2021-09-07 07:46:59 -04:00
Nemanja Glumac
8bda46bd01 #17775 Repro: Dashboard filter on a custom column doesn't work (#17780) 2021-09-07 12:54:09 +02:00
Nemanja Glumac
7809582168 New permissions E2E CI group (#17778) 2021-09-07 09:30:27 +02:00
Anton Kulyk
9ecd368043 Refactor CollapseSection (#17754) 2021-09-07 10:14:51 +03:00
Nemanja Glumac
9a9a987d61 #17768 Repro: If Entity Key fields are fingerprinted, then they show binning options in GUI (#17776)
* Add repro for #17768

* Wait for the sync to finish programatically
2021-09-06 22:41:41 +02:00
pawit-metabase
52c9a610ad Fix field filter no longer responding after selecting "None" (#17746)
Uncontrollable.jsx treats "undefined" value specially breaking
the onClick handler

Fixes #13825
2021-09-06 09:28:10 +07:00
Gustavo Saiani
ceb0af3762 Make dashboard filters sticky in edit mode (#17719) 2021-09-03 21:16:25 -03:00
Nemanja Glumac
f200351569 #17738 Repro: "Native query editing" permission selector is inconsistent between "No self service" and "Block" permissions (#17742)
* Add repro for #17738

* Update repro according to the product requirements
2021-09-04 01:05:30 +02:00
Nemanja Glumac
e0ded3a98f #17751 Repro: Filter with a single long value hides the remove-button (#17760) 2021-09-04 00:51:59 +02:00
Nemanja Glumac
b4a41beef1 Edit Permissions help text (#17741) 2021-09-03 17:35:26 +02:00
Nemanja Glumac
dd5d635f68 Run Percy (sanity check) visual tests in CircleCI (#17747)
* Run percy (sanity check) visual tests in CircleCI

* Update path for visual tests

* Make `--folder` flag optional

* visual tests docs

Co-authored-by: Alexander Lesnenko <alxnddr@users.noreply.github.com>
2021-09-03 14:42:14 +02:00
Noah Moss
f9a649db41 Remove deprecated pulse DELETE API (#17700) 2021-09-02 19:49:24 -07:00
Alexander Lesnenko
70d905be4f fix percy cypress tests (#17733) 2021-09-02 18:39:05 +03:00
Alexander Polyankin
0c646eb9d2 Hide configurations that are handled by Cloud (#17730) 2021-09-02 18:35:09 +03:00
Alexander Polyankin
7aecb4ef27 Donut fixes (#17731) 2021-09-02 17:44:18 +03:00
Alexander Polyankin
1a22829120 Refactor static viz, add formatting, add area chart (#17728) 2021-09-02 15:54:55 +03:00
Alexander Lesnenko
bf67b51329 Block permission front-end (#17638)
* Block permission

* Update frontend/src/metabase/admin/permissions/components/DataPermissionsHelp/DataPermissionsHelp.jsx

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
2021-09-02 09:54:33 +03:00
Ariya Hidayat
e11b1c9f32 Migrate frontend docs from wiki (#17720) 2021-09-01 17:31:05 -07:00
Noah Moss
512c9deab6 Add archived parameter to GET /api/alert/question/:id (#17645) 2021-09-01 15:45:01 -07:00
Cam Saul
4a0db8e1e0 Fix chain filter search against FieldValues that contains nil (#17706)
* Fix the chain filter functions with nil FieldValues (fix #17659)

* Reorganize test a bit.

* Simplify test

* More simplification

* Test fix 🔧

* Test fix part 2

* [ci nocache]
2021-09-01 14:04:45 -07:00
Cam Saul
4d4ca72f46 Make sure built drivers do not contain clojure core classes. Handle either string or keyword args to build scripts (#17608)
* No Clojure core classes please

* Don't try to make paths absolute twice. Build scripts should handle keyword args like ':driver'

* parse-as-keyword should return keywords as is

* Test fix 🔧

* Test fix 🔧

* Test fix part 2
2021-09-01 14:04:29 -07:00
Dalton
1803035951 use preventScroll in focus call in ListSearchField (#17692)
* use preventScroll in focus call in ListSearchField

* add a few ListSearchField unit tests
2021-09-01 12:01:29 -07:00
Dalton
786a4b7ee0 only apply DataSelectorContainer css hack in QuestionDataSelector (#17676)
* only apply DataSelectorContainer hack in QuestionDataSelector

* unskip repro
2021-09-01 12:01:18 -07:00
Anton Kulyk
8dab3a31de Fix joins with incomplete conditions are removed on query run (#17708) 2021-09-01 21:58:13 +03:00
Noah Moss
f092db5a36 Only delete alert for card with multiple breakouts when a goal is defined (#17678) 2021-09-01 11:52:28 -07:00
Anton Kulyk
e1fbaad296 Add jest-watch-typeahead plugin (#17713) [ci nocache]
* Install jest-watch-typeahead
2021-09-01 19:35:22 +02:00
Gustavo Saiani
7f175cdf6b Close all descendant collections when clicking on an open parent (#17703) 2021-09-01 13:24:37 -03:00
Gustavo Saiani
37b84980cd Collection sidebar: expand/collapse children when clicking on parent collection name (#17680) 2021-09-01 13:24:01 -03:00
dpsutton
4717d2ff6c Collapse small donut slices into a single "Other" category (#17637)
* Collapse small donut slices into a single "Other" category

* Locale aware decimal formatting

A followup PR will add all of the formatting options for scalars and
smart scalars so this function is largely temporary and will be
subsumed into a namespace that knows about all formatting options.

* empty with no cache [ci nocache]
2021-09-01 10:40:10 -05:00
Nemanja Glumac
9baebf4dc0 Remove Cypress from yarn resolutions (#17715)
Since the Webpack and Babel upgrades, this shouldn't be needed any more. In the past, we had to explicitly resolve to the specific version of Cypress. Now it resolves to this version by default.
2021-09-01 16:06:01 +02:00
Nemanja Glumac
d1e086efd8 Fix #17673: Rounded buttons have excessive white background (#17697)
* Remove white background from `Select` component's container

* Remove superfluous `text-bold` class from the `Select` component
2021-09-01 14:45:09 +02:00
Luis Paolini
44e5987a26 Fix Cypress binary not being available (#17705)
The node_modules folder was being persisted in the first step (checkout) as it's doing the building of the static viz package. This had an impact in the fe-deps step, so wiping the folder and doing a clean install should make the trick
2021-09-01 09:18:48 -03:00
pawit-metabase
2b037d838b sqlite: update sqlite-jdbc to 3.36.0.1 and improve date/time handling (#17567)
* update sqlite-jdbc to 3.36.0.1

The new version includes arm64 binaries and allows Cypress,
which uses SQLite, to run on Apple Silicon.

* Improve date/time handling in SQLite
2021-09-01 17:28:51 +07:00
Cam Saul
cd758c966f Fix failing geolocation test 🔧 (#17707) 2021-09-01 11:00:16 +02:00
Cam Saul
6593266572 Test init code: read driver parents from driver deps.edn (#17612)
* Test init code: read driver parents from driver deps.edn

* Rename :metabase.build-driver/parents -> :metabase.driver/parents
2021-08-31 19:04:52 -07:00
Nemanja Glumac
404e6f8865 #17658 Repro: Not possible to delete dashboard subscription unless dashboard is in root collection (#17699) 2021-09-01 01:44:09 +02:00
Cam Saul
e6358cc9fb Fix setting Block permissions in the permissions/graph API endpoints (#17651)
* Fix setting Block permissions in the permissions/graph API endpoints

* Revert changes to .dir-locals

* Perms graph: don't validate DB :schemas + :native unless both are present.

* PR feedback
2021-08-31 16:33:15 -07:00
Noah Moss
3344e09e81 Only include dashboard subscriptions in GET /api/pulse if user_id param is included (#17647) 2021-08-31 15:36:14 -07:00
dpsutton
538c94a9dd Svg test improvements (#17652)
* Ensure that data_readers functions are included in tests

`clj -X:dev:test :only metabase.pulse.render.js-svg-test` uses the
`#t` data reader, which passes the value to
`metabase.util.date-2/parse` but this function hasn't been evaluated
yet and it errors

```shell
% clj -X:dev:test :only metabase.pulse.render.js-svg-test
Warning: environ value /Users/dan/.sdkman/candidates/java/current for key :java-home has been overwritten with /Users/dan/.sdkman/candidates/java/11.0.11.hs-adpt
Running tests in metabase.pulse.render.js-svg-test
Syntax error reading source at (metabase/pulse/render/js_svg_test.clj:71:27).
Attempting to call unbound fn: #'metabase.util.date-2/parse
```

* Throw an error if resource is not found when loading sources

```shell
ERROR in metabase.pulse.render.js-svg-test/categorical-donut-test (js_engine.clj:37)
Uncaught exception, not in assertion.

clojure.lang.ExceptionInfo: Javascript resource not found: frontend_client/app/dist/lib-static-viz.bundle.js
    source: "frontend_client/app/dist/lib-static-viz.bundle.js"
   metabase.pulse.render.js-engine/load-resource    js_engine.clj:   37
    metabase.pulse.render.js-svg/load-viz-bundle       js_svg.clj:   94
 metabase.pulse.render.js-svg/static-viz-context       js_svg.clj:  100
                 metabase.pulse.render.js-svg/fn       js_svg.clj:  106
                                             ...
                              clojure.core/deref         core.clj: 2324
metabase.pulse.render.js-svg/timelineseries-line       js_svg.clj:  167
         metabase.pulse.render.js-svg-test/fn/fn  js_svg_test.clj:   75
            metabase.pulse.render.js-svg-test/fn  js_svg_test.clj:   74
                        clojure.test/test-var/fn         test.clj:  717
                           clojure.test/test-var         test.clj:  717
                   metabase.test-runner/run-test  test_runner.clj:  107

...
```

```shell
ERROR in metabase.pulse.render.js-svg-test/categorical-donut-test (Objects.java:221)
Uncaught exception, not in assertion.

java.lang.NullPointerException:
                java.util.Objects.requireNonNull     Objects.java:  221
      org.graalvm.polyglot.Source$Builder.<init>      Source.java:  725
          org.graalvm.polyglot.Source.newBuilder      Source.java:  546
   metabase.pulse.render.js-engine/load-resource    js_engine.clj:   34
    metabase.pulse.render.js-svg/load-viz-bundle       js_svg.clj:   94
 metabase.pulse.render.js-svg/static-viz-context       js_svg.clj:  100
                 metabase.pulse.render.js-svg/fn       js_svg.clj:  106
```

* Sort effects namespace
2021-08-31 17:31:27 -05:00
Noah Moss
f696b25f55 Don't throw exception when archiving a dashboard in non-root collection (#17670) 2021-08-31 15:31:17 -07:00
Ariya Hidayat
0165980760 Remove some superfluous return types in the queries library (#17681)
All of these can be correctly inferred already, thus there is no need to
the explicit type annotations.
2021-08-31 13:29:14 -07:00
Nemanja Glumac
8e4dc2960d Add "on" string to translation (#17696) 2021-08-31 21:01:11 +02:00
dpsutton
fd6414e8c7 Turn dataset_query into structured data in search results (#17690)
* Turn dataset_query into structured data in search results

* sort scoring test ns

* Fixup tests

we are no longer returning string results. The cards in the test have
empty queries, which the model turns into {} but normalization removes
empty clauses and returns nil. The tests would be too annoying to hook
this up to work properly and this functionality is tested in other
places.

* Unskip repro for #15959

* Update repro test

Co-authored-by: Anton Kulyk <kuliks.anton@gmail.com>
2021-08-31 12:49:23 -05:00
dpsutton
ab75c941e5 Add i18n to js engine (INTL) (#17688) 2021-08-31 10:23:40 -05:00
Anton Kulyk
7eb47a9289 Allow joins on multiple fields in the notebook editor (#17633)
* Separate Join unit tests with newlines

* Refactor Join's unit tests

* Add join type getters (by conditions count)

* Add getter and setter for join conditions by index

* Remove old comment

* Extract method converting dimensions

* Update setParentDimension

* Update setJoinDimension

* Update joinDimensions method

* Update joinDimensions method

* Update join alias setter

* Update default condition setter

* Update isValid method

* Add getConditions method

* Add addEmptyDimensionsPair method

* Render multiple join conditions

* Fix JoinStep align-items

* Fix join dimension methods usage

* Fix join dimensions alignment

* Temporary disable auto opening pickers

* Test adding a new dimensions pair

* Fix "add" join icon visibility

* Add "on" label between join conditions

* Remove redundant `else`

* Add `removeCondition` method for `Join`

* Fix JoinDimensionPicker's prop types

* Allow removing empty dimension pairs

* Add space between join dimensions

* Simplify JoinStep tests setup

* Automatically open dimension pickers

* Test JoinStep updates `Join` instance correctly

* Display dimensions source name

* Allow overwriting NotebookCell's padding

* Fix JoinStep layout

* Allow to clear a selected dimension

* Disable "no-unused-vars" for Join file

* Fix parentDimension usage

* Fix StructuredQuery's `Join` usage

* Update notebook visual test

* Fix E2E test

* Fix JoinStep look when no dimensions selected

* Extract JoinDimensionsRightControl component

* Extract JoinDimensionCellItem component

* Increase JoinStep's tests timeout

* Extract `_getExplicitJoinsSet` from StucturedQuery

* Fix unused variables in Join class

* Add a comment about setTimeout

* Fix join condition label

* Fix dimensions picker opens when dimension is set

* Make table icon container clickable

* Hide fields picker tooltip on picker open

* Fix Preview button overflowing JoinStep

* Fix table picker click area
2021-08-31 17:19:48 +03:00
Noah Moss
0c48f947e4 unskip repro (#17674) 2021-08-31 07:14:44 -07:00
Nemanja Glumac
e55cbe36db Fix #17657: No recipients causes error resulting in blank screen (#17668)
* Invalidate the pulse if it contains no recipients

Switch statement was returning `true`, resulting in falsely "valid" pulse
in the case there were no recipients but the schedule was set to month.

This commit fixes that.

* Move all conditions before the switch statement

* Enable repro for #17657

* Guard against the error that causes the white screen

* Add another repro for #17657

* Fix typo in the test name

* Fix typo in the unrelated comment
2021-08-31 15:02:10 +02:00
Gustavo Saiani
c762e34ef2 Fix better source map option and add documentation (#17675) 2021-08-31 09:12:17 -03:00
Alexander Polyankin
e5dbebd032 Add vertical labels for bar chart (#17664) 2021-08-31 14:40:40 +03:00
Ariya Hidayat
b0a9dbeec2 CI with GitHub Actions: bump the timeout for front-end unit tests (#17682)
With the code being instrumented for code coverage, and another
additional time to analyze + send the code coverage to codecov.io,
the typical execution runs awfully close to the 10-min limit.
Hence, add some extra room.
2021-08-30 21:18:57 -07:00
Gustavo Saiani
a7351e9b30 When creating database, pass syncing schedule options to api (#17639) 2021-08-30 15:52:47 -03:00
Nemanja Glumac
8c33a9d465 #17657 Repro: Subscriptions are enabled without the recipient, which leads to an error (#17666) 2021-08-30 19:09:47 +02:00
Kyle Doherty
23f6b761d0 match tick stroke color to axis stroke color (#17665) 2021-08-30 12:43:50 -04:00
Jeff Evans
417736688b Isolate BigQuery legacy and new driver test runs (#17626)
* Randomize BigQuery test view names

Use tu/random-name instead of a name based on the output of gensym

* Add extra prefix for legacy BigQuery driver created databases

* Update legacy BigQuery driver to have unique name for transient datasets

For those datasets created and destroyed by the legacy BigQuery driver QP tests, add an additional prefix so that it doesn't conflict with the new BigQuery driver tests
2021-08-30 11:43:30 -05:00
Alexander Polyankin
dd6f0cc453 Vertical legend fixes for LineAreaBarChart (#17552) 2021-08-30 19:10:35 +03:00
Alexander Polyankin
c5058a78e0 Fix notification management FE issues (#17618) 2021-08-30 17:00:14 +03:00
Nemanja Glumac
eff984039d Consolidate dashboard sql filters (#17661)
* Rename file to make it more specific

* Extract dashboard sql filters into separate folder and CI group

* Add short descriptions to dashboard filters repros

* Extract dashboard sql filters helpers (data objects)
2021-08-30 15:41:42 +02:00
Ariya Hidayat
864e78d6af ESLint rules to prevent prop shorthands for w and h (#17656) 2021-08-30 06:07:54 -07:00
Nemanja Glumac
1a062c36d9 Add test for dashboard filter applied to the explicitly joined field (#17650) 2021-08-28 21:13:25 +02:00
Gustavo Saiani
eb6708b593 Extract sidebar component from DatabaseEditingApp (#17597) 2021-08-28 06:04:20 -03:00
Ariya Hidayat
f16bf7b021 GridItem should not use prop shorthand (#17610) 2021-08-27 23:13:54 -07:00
Ariya Hidayat
1b75128f47 Avoid prop shorthand in month-year parameter widget (#17654) 2021-08-27 19:28:43 -07:00
Noah Moss
76514a2e59 Fix options menu in visualization settings sidebar (#17629) 2021-08-27 17:55:28 -07:00
Ariya Hidayat
ccdbb8e999 Components in store admin should not use prop shorthands (#17640) 2021-08-27 17:19:01 -07:00
Alexander Lesnenko
ea95633064 Add recent views list (#17582)
* slightly split existing search components

* add recent views list

* fix recent items moving when reopened

* extract TablePath component

* Add e2e specs for recents

* add specs

* add in table view logs so we get recent table looks

* review fixes

* use display_name for tables in recents list

* display name

* add loader threshold, return only 5 recents

Co-authored-by: Howon Lee <hlee.howon@gmail.com>
2021-08-28 01:39:09 +03:00
Alexander Lesnenko
de7141af6e slightly split existing search components (#17581)
* slightly split existing search components

* address review comments

* review fixes
2021-08-28 01:39:09 +03:00
Nemanja Glumac
4826248e13 [Dashboard filters coverage] Add test for required and default values set on dashboard SQL filters (#17628)
* Add test for required and default values set on dashboard SQL field filters

* Add test for required and default values set on dashboard SQL simple filter
2021-08-27 21:59:47 +02:00
Nemanja Glumac
245004dde1 Unskip and relocate (extract) repro for #13960 (#17641) 2021-08-27 21:59:13 +02:00
Greg Wilson
5f8366a5a2 Troubleshooting: can't log in (#17558)
* Outline for login troubleshooting guide

* Update docs/troubleshooting-guide/cant-log-in.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-log-in.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Importing material

* Prosifying

* Updates based on feedback

* Another update to login troubleshooting

* Fixing typo

* One more update

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-08-27 15:26:08 -04:00
Jeff Bruemmer
4beb075747 docs - troubleshooting sandboxing (#17593)
* draft update to sandbox troubleshooting

* update link

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Update docs/troubleshooting-guide/sandboxing.md

* Removing double blank line

* updates based on feedback from flamber

Co-authored-by: Greg Wilson <gvwilson@third-bit.com>
2021-08-27 15:25:54 -04:00
Ariya Hidayat
5e6da0d198 Revamped Developer's Guide (#17625) 2021-08-27 08:48:05 -07:00
Nemanja Glumac
813bb1f5f9 Add initial set of tests around SQL dashboard ID filters (#17607) 2021-08-27 14:43:55 +02:00
Nemanja Glumac
e913ee907f #17490 Repro: Field Filter variable type cut off by Nav for SQL questions (#17605) 2021-08-27 14:42:07 +02:00
Nemanja Glumac
e1324eb874 #17615 Repro: Valid Email settings disappear on save (#17624) 2021-08-26 22:54:08 +02:00
Nemanja Glumac
517ffdc97c Unskip "email" part of the reproduction for #16226 (#17623) 2021-08-26 22:25:24 +02:00
Nemanja Glumac
029d717886 #17619 Repro: "More options" menu not opening (#17622) 2021-08-26 21:12:28 +02:00
Jeff Evans
babbffbc44 Improve driver deprecation UX (#17281)
* Improve driver deprecation UX

Reworking the DriverWarning component to be able to change the engine itself by firing the event (so that the "go to older/newer version" links actually work)

Some styling fixes to match Figma mockup

Remove all grid-styled usage

Remove all styling (except class names) from DriverWarning jsx file, move to the styled-component

Implement db-ids-with-deprecated-drivers API endpoint for fetching DB IDs using deprecated drivers

Add some plugin test init code to properly handle the test legacy/new drivers

Adding test for new API

Adding new entry in `MetabaseApi` frontend component for new API method
2021-08-26 14:02:11 -05:00
Nemanja Glumac
60146bf4ce Keep mongo 4.0 for backend tests until its end of life (#17575) 2021-08-26 20:47:26 +02:00
dpsutton
18659376eb categorical bar on the backend (#17620) 2021-08-26 13:25:43 -05:00
Cam Saul
da3a3f5824 Support building and hacking on third-party drivers with our new Clojure CLI setup (#17606)
* Determine MB project root directory relative to source directory of build scripts

* Support calling build-driver! as a -X fn, and support dirs outside of modules/drivers

* Support loading 3rd-party driver manifest files at (dev) launch

* Fix log4j not working on latest version of CIDER (unrelated)

* Fix dissoc

* project-root-directory is supposed to be a string
2021-08-26 10:11:57 -07:00
Alexander Polyankin
e498004c99 Add simple static categorical bar (#17600) 2021-08-26 18:26:27 +03:00
Ariya Hidayat
25a5fd4ea7 Correct the instruction to run E2E tests (#17603) 2021-08-26 06:06:42 -07:00
Ariya Hidayat
a951668d23 Avoid prop shorthand in query download widget (#17611) 2021-08-25 17:47:57 -07:00
Cam Saul
bf2ba1f31d Block permissions backend (#17428)
* ⛔ B L O C K ⚠ permissions ✅

* Fix test failure in OSS since EE namespace doesn't exist.

* Remove unused var

* Oops, uncomment a commented-out test

* Clean up the new perms documentation a bit
2021-08-25 17:03:44 -07:00
Ariya Hidayat
7dc5d97797 Example snippet should not use prop shorthand (#17604) 2021-08-25 16:58:04 -07:00
Noah Moss
9da5466553 Include markdown cards in Slack dashboard subscriptions (#17457) 2021-08-25 12:31:13 -07:00
Jeff Evans
0023987f49 Update Presto JDBC lib version (#17591)
0.254 -> 0.260
2021-08-25 14:04:45 -05:00
Alexander Lesnenko
5c3e84ec25 fix permissions editor missing scroll (#17595) 2021-08-25 21:03:21 +03:00
Alexander Lesnenko
80f8813b89 use backticks in auto-backport workflow (#17594) 2021-08-25 20:50:27 +03:00
Alexander Polyankin
3d874e2732 Add modals to unsubscribe from and archive notifications (#17516) 2021-08-25 20:35:17 +03:00
Anton Kulyk
548358a4b1 Fix run overlay not going away on GUI questions (#17590)
* Enable repro tests

* Don't sync stuctured questions on query complete
2021-08-25 10:00:49 -07:00
dpsutton
c8c984feb6 User details on moderation review (#17482)
```bash

% curl 'http://localhost:3000/api/card/760' -H <stuff omitted> | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2003    0  2003    0     0   102k      0 --:--:-- --:--:-- --:--:--  102k
{
  "description": null,
  "archived": false,
  "collection_position": null,
  "table_id": 2,
  "creator_id": 1,
  "moderation_reviews": [
    {
      "most_recent": true,
      "moderator_id": 1,
      "updated_at": "2021-08-16T21:30:00.665952Z",
      "status": "verified",
      "id": 1026,
      "user": {
        "email": "dan@metabase.com",
        "first_name": "dan",
        "last_login": "2021-08-10T21:17:35.366176Z",
        "is_qbnewb": false,
        "is_superuser": true,
        "id": 1,
        "last_name": "sutton",
        "date_joined": "2021-03-15T20:42:55.751834Z",
        "common_name": "dan sutton"
      },
      "moderated_item_id": 760,
      "created_at": "2021-08-16T21:30:00.665952Z",
      "moderated_item_type": "card",
      "text": null
    }
  ],
  "dataset_query": {
    "database": 1,
    "query": {
      "source-table": 2
    },
    "type": "query"
  },
  "id": 760,
  "display": "table",
  "last-edit-info": {
    "id": 1,
    "email": "dan@metabase.com",
    "first_name": "dan",
    "last_name": "sutton",
    "timestamp": "2021-05-12T22:04:57.205978Z"
  },
  ...
}
```
2021-08-25 09:50:30 -05:00
dpsutton
32a0d6cb54 Effective type in result cols (#17533)
* Include the results base type as the cols effective type

previously was merged the effective type from the col which caused
issues with dates when selecting a particular temporal unit, ie month.

Queries like this return months as integers so the base and effective
types are :type/Integer, and something somewhere else is responsible
for the unit conversion of `1` to January (or feb, months get weird i
think)

```clojure

;; after
{:description "The date and time an order was submitted.",
 :unit :month-of-year,
 :name "CREATED_AT",
 :field_ref [:field 4 {:temporal-unit :month-of-year}],
 :effective_type :type/Integer, ;; we have the proper effective type
 :display_name "Created At",
 :base_type :type/Integer}

;; before:
{:description "The date and time an order was submitted.",
 :unit :month-of-year,
 :name "CREATED_AT",
 :field_ref [:field 4 {:temporal-unit :month-of-year}],
 :effective_type :type/DateTime, ;; included effective type from db
 :display_name "Created At",
 :base_type :type/Integer}
```

* tests

* Driver tests

* Ignore effective/base types in breakout tests

sparksql is weird and its totally unrelated to the file under test

* Use correct options for datetimes that are projected to month, etc

When aggregating by a datetime column, you can choose a unit: month,
hour-of-day, week, etc. You often (always?) end up with an
integer. Previously the base_type was (inexplicably) :type/Integer and
the effective_type was :type/DateTime which really just didn't make
sense. The ideal solution is :type/DateTime as the base_type and
:type/Integer as the effective_type. But this breaks the frontend as
it expects to treat these columns in a special way. But it expected
them to report as date columns.

I've changed it only here. I thought about making isDate understand
the `column.unit` attribute and recognize that these are in fact
dates, but that seems wrong. These are integers that are special
cases. It seems that the contexts that need to talk about dates should
understand integers in a special way than all date code needs to be
aware that integers might flow through.

This might mean extra work but ultimately feels better as the correct
solution.

* unit is not default
2021-08-25 09:37:21 -05:00
Nemanja Glumac
d469362e71 Fix references to the possessive form of 'its' (#17589) 2021-08-25 15:25:45 +02:00
Anton Kulyk
79ea2d32d3 Update notebook editor's join step UI (#17523)
* Move JoinStep's NotebookCell down to JoinClause

* Break JoinClause into two NotebookCells

* Update labels

* Use `space` helper function

* Simplify conditional statement

* Fix not translated string
2021-08-25 15:34:20 +03:00
Alexander Polyankin
5a79539ed4 Add read-only Notifications tab (#17503) 2021-08-25 15:25:21 +03:00
Ariya Hidayat
6a815f5d34 Make the front-end metadata sources valid JavaScript (#17539) 2021-08-24 20:04:00 -07:00
Gustavo Saiani
0136165b96 Unify styled component file extensions: .styled.js → .styled.jsx (#17580) 2021-08-24 20:28:05 -03:00
Jeff Evans
f5cf47480b Add Kerberos support to Presto JDBC Driver (#16307)
* Add Kerberos support to Presto JDBC Driver

Adding Kerberos properties as DB details properties

Refactoring utility methods for dealing with additional options

Adding test for Kerb properties -> connection string

Adding GitHub action to run integration test

Start to move logic for capturing necessary files to new script, and calling that from mba run

Adjust settings in `metabase.test.data.presto-jdbc` to capture test parameters
2021-08-24 17:18:26 -05:00
Jeff Evans
ee73902a68 Support counting grouped on an aggregated field in BigQuery (#17536)
Fix counting on grouped aggregated field

Adding QP test

Reworking the BigQuery version of the :breakout to more closely match the structure of the standard sql.qp version
2021-08-24 17:17:13 -05:00
Gustavo Saiani
c9799b16a9 Improve EntityForm component (#17583) 2021-08-24 18:33:40 -03:00
Noah Moss
163fa801ae Keep collection_id of dashboard subscriptions in sync with same field on dashboard (#17537) 2021-08-24 13:59:24 -07:00
Nemanja Glumac
2f446214e0 #17512 Repro: Custom Expression case is using wrong field reference when nested query (#17576) 2021-08-24 20:56:04 +02:00
Alexander Lesnenko
d012c89b17 New Permissions Pages (#17328)
* add PermissionSelect component

* add PermissionSidebar component

* add PermissionTable component

* add PermissionEditor component

* add useLeaveConfirmation hook

* add selectors for the collections permissions page

* add selectors for the data permissions pages

* add confirmation creators to use in selectors

* sandboxing permissions modal: redirect to parent route when closed

* Add PermissionsPageLayout component

* Adjust CollectionPermissionsModal to use new permissions UI

* Add CollectionPermissionsPage

* Add data permissions pages

* Adjust collection permissions modal route

* Adjust permissions routes according new pages structure

* update permissions actions, reducers

* adjust sandboxing

* remove old permissions code

* support admin colorScheme in Radio

* support admin colorScheme in TextInput

* support admin colorScheme in Tree

* update permissions specs

* fix data permissions url typo

* fix sandboxing

* add search debounce to permission pages

* exclude schemas from search, make it flat

* fix permissions for databases without schemas

* fix copy for native queries permissions, show table display_name instead of raw name

* fix before leave warning shown when change collections

* permissions sidebar: make database name clickable

* fix string groupIds lead to bugs in permissions editor

* fix disabling table permissions shows all tables permission disabled

* fix permissions copy

* fix permissions disabled tooltips copy

* fix, add specs

* fix permissions edit bar button colors, fix breadcrumbs on schemaless dbs

* fix official collection color, make sidebar tree scrollable

* fix scroll in permissions modal

* fix breadcrumbs

* change table icon

* create helpers for entity ids and permissions url creation

* remove hardcoded colors

* make confirmations an array

* store confirmAction in state

* add ModalRoute specs

* fix propTypes, typo

* build permission pages urls with helpers

* revert switching from ref to state for confirm action function due to react invokes it on a render

* move mapStateToProps to the top of the files

* add visual specs

* add more specs

* fix edit sandbox access action

* add cypress spec for sandboxing
2021-08-24 21:30:21 +03:00
Ariya Hidayat
6ef0eceb72 Move our E2E guide from wiki to in-repo .md (#17540) 2021-08-24 10:27:13 -07:00
Ariya Hidayat
9bec76bc8f Visual tests for static-viz (via _internal) (#17561) 2021-08-24 10:24:06 -07:00
Nemanja Glumac
32ffbadfb4 #17524 Reproductions: Visualization type is not always respected, when filters are applied (#17565) 2021-08-24 15:34:43 +02:00
Nemanja Glumac
1278500b79 Update dev guide with info on deprecated Debugger for Chrome (#17571) 2021-08-24 15:33:33 +02:00
Nemanja Glumac
2948df3023 Revert Mongo QA Docker image update back to the version 4.0 (#17574)
* Try reverting mongo QA image back to 4.0

* Update mongo query assertion
2021-08-24 14:22:02 +02:00
Nemanja Glumac
240a189322 #17547 Repro: Editing an alert causes it to be deleted in some circumstances (#17563) 2021-08-24 09:51:22 +02:00
Ariya Hidayat
b795f9f102 Avoid prop shorthand in the login page (#17566) 2021-08-23 21:03:59 -07:00
Dalton
3776db6c27 enable default parameters to be unset on dashboards (#17522)
* enable unset default params on dashboard

* add unit tests
2021-08-23 18:34:52 -07:00
Gustavo Saiani
1096573bac Do not track testing coverage for styled.js* files (#17505) 2021-08-23 18:54:58 -03:00
Nemanja Glumac
35b272d8b5 Refactor cy.editDashbardCard Cypress custom command (#17560)
* Update parameter names in `editDashboardCard` Cypress custom command

* Update tests
2021-08-23 23:34:50 +02:00
Howon Lee
eb25bc7113 Mongo custom expressions (#17117)
Mongo custom expressions now are turned on for mongo 5.0 and after only. One idiosyncrasy is that we don't really support the BSON ID format at all in our typesystem despite having it in there, but both of my attempts to get them to work with the native mongo pipeline commands bounced because they really aren't strings, they're BSON ID's. We do rely on the pipeline commands heavily which is the reason for the version requirement.
2021-08-23 14:33:24 -07:00
Ariya Hidayat
83d3fd73f6 Avoid prop shorthand in the database/schema/table browser (#17559) 2021-08-23 14:03:15 -07:00
Ariya Hidayat
6d0bb1515d Add typing hints to isa to assist type inference (#17530)
This requires unfortunately an additional layer of indirection, however
I believe it's super cheap and it shouldn't impact execution speed.

In the mean time, many other predicates (isFoo etc) which rely on isa()
will be correctly type-inferred, which gives a huge win for editing and
debugging purposes.
2021-08-23 14:02:38 -07:00
Noah Moss
ea56ae35b5 New endpoints for fetching alerts & subscriptions (#17531) 2021-08-23 13:42:08 -07:00
Nemanja Glumac
538835f0d0 #17551 Repro: Dashboard date filter "Include today" does not work for relative "Next" (#17557)
* Expand `setAdHocFilter` helper function to include current date

* Add repro for #17551

* Update test title
2021-08-23 22:10:51 +02:00
dpsutton
d765d16da1 Don't warn when running interpreted js (#17529)
I'm not sure we can fix this. We need the graal compiler which doesn't
appear to be jdk 8 compatible but I can't actually find javadocs for
it. Its not clear from
https://github.com/oracle/graaljs/blob/master/docs/user/RunOnJDK.md
how you can actually run it.

I tried adding the graal compiler but that seems to assume you are in
a graal vm and fails not finding a class.

To get a list of all the options available for a context's engine,

```clojure
(doto 'metabase.pulse.render.js-engine require in-ns)
(map (comp (juxt :name :help) bean)
     (.getOptions (.getEngine (context))))
```

I've done some profiling

```clojure
(dotimes [_ 5]
  (time
   (do (let [rows [["apples" 2]
                   ["bananas" 3]]
             colors {"apples" "red" "bananas" "yellow"}]
         (js-svg/categorical-donut rows colors))
       nil)))

"Elapsed time: 210.32659 msecs"
"Elapsed time: 193.211736 msecs"
"Elapsed time: 190.97775 msecs"
"Elapsed time: 195.843254 msecs"
"Elapsed time: 188.077405 msecs"
nil
```

For interpreted and in another language, this doesn't seem the end of
the world.

And adding more quantities
```clojure
(letfn [(rand-string [] (str/join "-" (repeatedly 4 #(rand-nth ["banana" "horse" "battery" "cloak"]))))]
  (dotimes [_ 5]
    (let [rows (repeatedly 20 (fn [] [(rand-string) (rand-int 100)]))
          colors (zipmap (map first rows) (cycle ["red" "green" "blue" "yellow"]))]
      (time
       (js-svg/categorical-donut rows colors)))))

"Elapsed time: 288.659887 msecs"
"Elapsed time: 334.733071 msecs"
"Elapsed time: 317.369294 msecs"
"Elapsed time: 272.084918 msecs"
"Elapsed time: 272.7203 msecs"
nil
```

For a timeline line chart, rendering one datapoint per day for a whole
year:

```clojure
(dotimes [_ 5]
  (let [dates (take 365 (iterate #(.plusDays % 1) #t "2020"))
        rows   (map (fn [d] [d (rand-int 200)]) dates)
        labels {:left "count" :bottom "year"}]
    (time
     (js-svg/timelineseries-line rows labels))))

"Elapsed time: 569.691124 msecs"
"Elapsed time: 544.415676 msecs"
"Elapsed time: 539.131092 msecs"
"Elapsed time: 492.60486 msecs"
"Elapsed time: 523.765691 msecs"
nil
```
2021-08-23 14:35:13 -05:00
Noah Moss
356dd75b71 Formatting & whitespace fixes in Clojure files (#17441) 2021-08-23 10:05:45 -07:00
Alexander Lesnenko
93f5851191 add workflow that creates backport PRs which had a backport label before merge (#17550) 2021-08-23 19:38:55 +03:00
Greg Wilson
42f2a1e528 Unifying all troubleshooting guides so far (#17553)
* Troubleshooting guide for filters.

After conversation with @flamber, split this into one guide for simple filters and one for linked filters. The explanation at the top of the second page may still need some work...

* Updating filter troubleshooting

* Troubleshooting when you can't see the tables you should.

* Why is my dashboard slow?

* Troubleshooting: can't send email

* Adding @flamber's batch script-style guide

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Fixing first item

* Addressing feedback

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-send-email.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Adding flamber's comment

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Splitting entry

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Troubleshooting timezones

* Reformatting the filter troubleshooting guides

* Partial update to troubleshooting filters

* specify sql questions

* link

* update relative links

* more link fixes

* still more links

* specify dashboard filters

* fix typo

* Italicizing one more word

* Unifying all troubleshooting guides so far

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/cant-see-tables.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Incorporating suggestion

* Update docs/troubleshooting-guide/my-dashboard-is-slow.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/my-dashboard-is-slow.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/my-dashboard-is-slow.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/my-dashboard-is-slow.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/my-dashboard-is-slow.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Another small fix

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>
Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
Co-authored-by: jeff bruemmer <jeff.bruemmer@gmail.com>
2021-08-23 11:37:12 -04:00
Alexander Polyankin
591684bba1 Add day of week formatting with formatting options (#17549) 2021-08-23 15:32:18 +03:00
Alexander Polyankin
5a057ea905 Add formatTimeWithUnit (#17527) 2021-08-23 12:28:52 +03:00
Nemanja Glumac
60e9778f0d #17514 Repros: Run-overlay not going away on GUI question (#17534) 2021-08-22 03:30:37 +02:00
Nemanja Glumac
06b50d65af #13468 Repro: Question with joins causes re-run overlay after first save (#17535) 2021-08-22 03:29:41 +02:00
Jeff Evans
e8c7140a04 Fix serialization P2 issues (#17388)
* Fix serialization dump error when there are no collections

Update `select-collections` to correctly handle the case where there are no collections

Adding new test that removes all collections, then ensures that dump works with no errors

* Fix serialization load error into empty/blank target DB

Rethrowing exception in cmd when overall load fails

Add test to ensure that a dump containing a user can be loaded into a blank target app DB successfully

Adding a few missing bindings to the `with-temp-empty-app-db` code to set the connection vars under metabase.db.connection

In upsert, add hooks for a :pre-insert-fn and :post-insert-fn to be invoked for new entity instances created by the upsert process, since whether an entity will be an insert or update isn't necessarily known by the load process (only by upsert once identity-condition is checked for each)

In load, setting the pre and post insert functions for a User instance to initialize :password with a random value, and to generate and send a password reset email to the newly inserted user's email, respectively

NOTE: this post insert fn (to send a password reset email for newly inserted users) is NOT hooked up for User as of x.41 release, since it is considered a bugfix, but this can be enabled in a future release)

Adding new defs for the magic permission group names to make those easier to override from tests that might need to (such as the one added for this commit)

* Fix serialization objects being incorrectly updated on skip

Remove `maybe-fixup-card-template-ids!`, which was forcing mode :update, since the existing retry logic should cover what it was trying to do

Update Card and Metric models to delete any Dependency instances for which they are the `:model_id` (to make serialization tests after other tests created temporary Card/Dependency pairs)

Adding missing assertions for Dependency serialization

* Serialization: Fix reload entity logic

Now that the `:mode` is always respected instead of being ignored sometimes, we need to update our "second pass" reload functions to always make the mode `:update` on the second pass, or else that entity would just be skipped, which is bad

Also updated the test to use `:mode` `:skip` from the beginning to be more stringent
2021-08-20 17:04:13 -05:00
Dalton
02713dd302 refactor/move parameter object transformations to one place (#17461)
* refactor/move parameter object transformations to one place

* use hasParameterValue in place of nil check

* remove enableDefaultParameters arg since it is unused
2021-08-20 10:23:36 -07:00
Gustavo Saiani
c9bbfbc7c2 Make filters sticky in Dashboard page (#17406) 2021-08-20 13:19:30 -03:00
Jeff Evans
a980e08588 New BigQuery Driver (#16746)
New BigQuery Driver

Create new :bigquery-cloud-sdk driver using the google-cloud-bigquery library instead, and whose source is adapted from the :bigquery driver

https://cloud.google.com/bigquery/docs/reference/libraries

Marking existing :bigquery driver as deprecated, and superseded-by the new one (bigquery-cloud-sdk)

Update new driver and query processor code to use newer Google SDK

Switch test data loading over to use new API

Add project-id connection property to override the value from the service account JSON, and use it as part of qualified names in the query processor if set

Updating google driver so its libraries are compatible with the newer ones used in BigQuery

Update date bucketing tests to skip :bigquery-cloud-sdk (new driver) where :bigquery is skipped

Update `with-bigquery-fks` to take in the driver, since there are now multiple ones

Adding test to confirm that overriding project-id for a public BQ project works (sync and query)

Fixing a bunch of whitespace alignment errors in tests
2021-08-20 10:04:59 -05:00
Ariya Hidayat
91640fdacb Enable proper type inference for call, bind, and apply (#17518)
https://www.typescriptlang.org/tsconfig#strictBindCallApply
2021-08-20 06:01:19 -07:00
Ariya Hidayat
3480ca8941 Remove some superfluous return types in the metadata code (#17519)
Type inference can already correctly infer those return types, no need
to explicit anymore.
2021-08-20 06:00:23 -07:00
Ariya Hidayat
57e50c79ef Avoid prop shorthand in collections (#17517) 2021-08-20 05:59:57 -07:00
Nemanja Glumac
184be52396 Edit Cypress custom command cy.createDashboard() (#17521)
* Update `dashboard` custom Cypress command

* Update composite custom commands to accommodate new syntax

* Update tests that use `cy.createDashboard()` custom command

* Update default snapshot generator
2021-08-20 13:37:41 +02:00
Anton Kulyk
4b0afb6768 New columns picker for notebook editor (#17511) 2021-08-19 20:58:17 +03:00
Dalton
99380075be don't prefetch data for the data selector (#17455)
* don't prefetch data for the data selector

* rmv prefetch cy test

* fix mongo test
2021-08-19 09:38:09 -07:00
Alexander Lesnenko
b63ea17253 replace backport label with a more flexible backport command (#17497)
* replace backport label with a more flexible backport command

* fix backport bot command
2021-08-19 19:23:38 +03:00
Ariya Hidayat
3d5b0524d4 Fix tracking and reporting front-end coverage for EE (#17506) 2021-08-19 07:47:34 -07:00
Alexander Polyankin
ae26bb6e60 Split UserSettings into routes and individual components (#17474) 2021-08-19 17:07:18 +03:00
Anton Kulyk
6f8324debe Add right prop to NotebookCellItem (#17435)
* Remove not displayed NotebookCell's 'icon` prop

* Refactor NotebookCell to accent `right` prop

* Fix cypress getter

* Fix icons opacity

* Fix margins and paddings

* Pass initialState to getStore test helper

* Add basic tests for JoinStep

* Test automatic join fields assignment

* Add selectTable test helper

* Fix private property access

* Add join fields tests

* Test join is correctly applied to query

* Add more tests for join dimension pickers

* Test selecting joined table columns

* Disable failing JoinStep test (jest timeout)

* Extend timeout for JoinStep tests
2021-08-19 13:30:29 +03:00
Alexander Lesnenko
129644413b fix ModalRoute close removes last segment instead of navigating to the parent path (#17508) 2021-08-19 12:00:10 +03:00
dpsutton
ecf10466ad Build static viz in the dockerfile (#17507) 2021-08-18 22:12:34 -04:00
Nemanja Glumac
ce406d242a Add editDashboardCard Cypress custom command (#17493) 2021-08-19 00:23:58 +02:00
Jeff Bruemmer
ef46b7642d docs headings (#17492) 2021-08-18 16:22:03 -04:00
Ariya Hidayat
15465b2d18 Fix incorrect navbar width (#17496)
Regression in PR #17460
2021-08-18 10:01:27 -07:00
Anton Kulyk
b874ab1835 Display official collection tooltips (#17453)
* Add tooltips to authority level configs

* Use tooltips for CollectionAuthorityLevelIcon

* Pass tooltips to getCollectionIcon result

* Display tooltip in CollectionHeader

* Display tooltip in collections sidebar

* Display tooltip on the homepage

* Display tooltip in ItemPicker

* Accept icon props as a TreeNode's icon prop value

* Display tooltip in saved question picker

* Accept icon props as a SelectListItem's icon prop value

* Display tooltip in dashboard's question picker

* Add "Belongs to an Official collection" tooltip

* Fix prop-types errors

* Add tests for CollectionAuthorityLevelIcon

* Add tests for isRegularCollection

* Fix search results collection icons

* Show "Official Collection" label in search results

* Don't show tooltips for official collections in search

* Fix ItemPicker's prop type

* Add basic test for ItemPicker

* Test read-only collections are not displayed

* Add test IDs to ItemPicker

* Refresh Redux store in each ItemPicker's test

* Test opening a nested collection

* Test default breadcrumbs state

* Fix ItemPicker's header test ID

* Test ItemPicker read-only items visibility

* Add test for onChange prop

* Test navigating back from an open collection

* Test personal collections are grouped in ItemPicker

* Assert number of ItemPicker items

* Test getCollectionIcon in EE

* Add a workaround for tooltip offsets

* Add describe block for CollectionsList tests

* Make CollectionsList test shorter

* Test collection types on CollectionList

* Fix SearchResult's info

* Add SearchResult tests

* Use isRegularCollection for AuthorityLevelIcon
2021-08-18 19:41:48 +03:00
Ariya Hidayat
6e9900e70b codecov config: disable patch checking (#17502)
codecov patch calculation is incorrect. Thus, let's rely only on the
whole-project calculation and threshold (which is working fine).
2021-08-18 09:22:51 -07:00
Nemanja Glumac
921e7dd663 [Dashboard filters coverage] Add initial set of tests for dashboard SQL date filters (#17483) 2021-08-18 17:56:31 +02:00
Nemanja Glumac
b838f4a77a Refine create question custom commands (#17459)
* Refactor and dry up `question` custom Cypress commands

* Example of `loadMetadata` custom option in action

* Example of `visitQuestion` custom option in action

* Annotate functions using JSDoc
2021-08-18 14:03:32 +02:00
Cam Saul
97bcb67055 Warn if .lein-env is present on launch (dev-only) (#17477)
* Help avoid the .lein-env gotchas

* Learn to spell @camsaul

* Revert the .gitignore change -- too  D A N G E R O U S

* Fix version numbers (thanks @jeff303)
2021-08-17 20:52:49 -07:00
Cam Saul
94432ff14f Ensure Setting :default values match the Setting :type; fix user-facing-value for calculated Settings. Cleanup & extra tests for email settings (#17442)
* Change of plans. get-string (etc) only return default if it matches the type

* Better docstrings

* More tests & rework the validate-default-value logic a bit.

* Fix lint error

* Add an additional test for GET /api/setting

* Consolidate exception-chain util functions

* Email error message humanization improvements

* More tests for util ex-chain

* Clean up email error handling and add lots of extra tests

* Fix docstring indentation

* Even more email tests

* Test fixes 🔧

* Update Cypress test again

* Code cleanup
2021-08-17 17:03:09 -07:00
dpsutton
31df07b9d0 Svg/percentages (#17415)
* Backend SVG rendering proof of concept [ci skip]

* Update cssbox to 5.0.0

* Render bar, line, and pie charts in js to svg

sparkline is now done in js, bar is now recognized and done in js, new
:categorical/donut as well

* Remove api route for render

* pass along render-type, not hardcoded to :inline

* Move bar chart above sparkline and remove line check

In order to introduce the bar chart type need it above the sparkline
check since it is otherwise the same except for display property of
the card. But lots of tests assume that this will get hit with a nil
display type set in testing so remove checking for `:line` allows all
the testing cases to hit the right type

* Fix tests now that bar graphs aren't html but images

* Include attachments for bar charts

* Move over to in-tree bundle

* Force everything [ci noskip]

trying to ensure that the built jar includes the newer
"resources/frontend_client/app/dist/lib-static-viz.bundle.js"

* Run `yarn build-static-viz` in backend-deps in CI

this js file is now a hard dependency of the backend so it fits in
this tsk. All such things that depend on the backend sources will need
it. Makes me think perhaps we want a checked in version but i'm not
sure yet.

* Look on classpath not filesystem for js bundle [ci noskip]

* Move yarn build-static-viz into the checkout step

* License information for antlr4-runtime

* create attachment for categorical donuts

* add ordinal legend to donuts (#17177)

* set widths of html image and svg image to 1200

* Revert "add ordinal legend to donuts (#17177)"

This reverts commit 1eb81d2ebf.

* Helper functions to render html easily

* readme in dev

* readme ensure that static viz bundle exists

* Cleanup ns after removing proxy

* Donut chart colors and legend (#17251)

* use external color map for fill per dimension

* Add support new color legend for donut

* Ensure text doesn't appear as link

entire thing is actually the body of a link tag for emails but we want
a decent text color rather than a default link color

* use chart colors from https://stats.metabase.com/_internal/colors

* Make checkers happy

- remove unused imports
- add a docstring
- don't shadow fn with a local

* cleanup ns import

* Remove reflective call

* Cleanup ns on correct branch

Co-authored-by: dan sutton <dan@dpsutton.com>

* X-axis: just use (approx) 5 ticks to avoid overlapping labels (#17287)

* increase gap between arcs (#17271)

* Set rendering hints on html->image

* ignore width for now and make them larger

* Ns deprecation and some cleanup

* make namespace checker happy

* Simple tests for detecting chart type

* Rename from poc

* Tests for scalar/smartscalar

* cleanup js svg namespace a bit

* Tests of svg engine

* ns sorting after renaming

* Unify our two different js engine usages

settled on the js context. Has typed returns `(.asString ^Value ...)`
instead of perhaps capturing std out?
https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html

Context is a bit more friendly for getting source into it. One
downside is that the invocable bit isn't quite as nice. The old way
would return a java.util.functionFunction but the difference is

(.apply function (object-array args))

vs

(.execute fn-ref (object-array args))

* Don't io/resource the io/resource

* js engine tests

* Ns cleanup in js-svg

type hints in the js-engine ns mean we don't need as many classes from
polyglot here

* Include percentages in rendered donut charts

* Testing for percentages

Co-authored-by: Cam Saul <github@camsaul.com>
Co-authored-by: Kyle Doherty <5248953+kdoh@users.noreply.github.com>
Co-authored-by: Ariya Hidayat <ariya@metabase.com>
2021-08-17 18:01:49 -04:00
Kyle Doherty
b8c9302932 Svg/labels (#17413)
* Backend SVG rendering proof of concept [ci skip]

* Update cssbox to 5.0.0

* Render bar, line, and pie charts in js to svg

sparkline is now done in js, bar is now recognized and done in js, new
:categorical/donut as well

* Remove api route for render

* pass along render-type, not hardcoded to :inline

* Move bar chart above sparkline and remove line check

In order to introduce the bar chart type need it above the sparkline
check since it is otherwise the same except for display property of
the card. But lots of tests assume that this will get hit with a nil
display type set in testing so remove checking for `:line` allows all
the testing cases to hit the right type

* Fix tests now that bar graphs aren't html but images

* Include attachments for bar charts

* Move over to in-tree bundle

* Force everything [ci noskip]

trying to ensure that the built jar includes the newer
"resources/frontend_client/app/dist/lib-static-viz.bundle.js"

* Run `yarn build-static-viz` in backend-deps in CI

this js file is now a hard dependency of the backend so it fits in
this tsk. All such things that depend on the backend sources will need
it. Makes me think perhaps we want a checked in version but i'm not
sure yet.

* Look on classpath not filesystem for js bundle [ci noskip]

* Move yarn build-static-viz into the checkout step

* License information for antlr4-runtime

* create attachment for categorical donuts

* add ordinal legend to donuts (#17177)

* set widths of html image and svg image to 1200

* Revert "add ordinal legend to donuts (#17177)"

This reverts commit 1eb81d2ebf.

* Helper functions to render html easily

* readme in dev

* readme ensure that static viz bundle exists

* Cleanup ns after removing proxy

* Donut chart colors and legend (#17251)

* use external color map for fill per dimension

* Add support new color legend for donut

* Ensure text doesn't appear as link

entire thing is actually the body of a link tag for emails but we want
a decent text color rather than a default link color

* use chart colors from https://stats.metabase.com/_internal/colors

* Make checkers happy

- remove unused imports
- add a docstring
- don't shadow fn with a local

* cleanup ns import

* Remove reflective call

* Cleanup ns on correct branch

Co-authored-by: dan sutton <dan@dpsutton.com>

* X-axis: just use (approx) 5 ticks to avoid overlapping labels (#17287)

* increase gap between arcs (#17271)

* Set rendering hints on html->image

* ignore width for now and make them larger

* Ns deprecation and some cleanup

* make namespace checker happy

* Simple tests for detecting chart type

* Rename from poc

* Tests for scalar/smartscalar

* cleanup js svg namespace a bit

* Tests of svg engine

* ns sorting after renaming

* Unify our two different js engine usages

settled on the js context. Has typed returns `(.asString ^Value ...)`
instead of perhaps capturing std out?
https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html

Context is a bit more friendly for getting source into it. One
downside is that the invocable bit isn't quite as nice. The old way
would return a java.util.functionFunction but the difference is

(.apply function (object-array args))

vs

(.execute fn-ref (object-array args))

* Don't io/resource the io/resource

* js engine tests

* Ns cleanup in js-svg

type hints in the js-engine ns mean we don't need as many classes from
polyglot here

* add custom labels

* clean up margin

* Include labels in backend

* alignment

Co-authored-by: Cam Saul <github@camsaul.com>
Co-authored-by: dan sutton <dan@dpsutton.com>
Co-authored-by: Ariya Hidayat <ariya@metabase.com>
2021-08-17 15:47:59 -04:00
Jeff Bruemmer
efce02166d docs - links to dashboard subscriptions (#17489) 2021-08-17 15:08:10 -04:00
Cam Saul
bf00aa99c7 Backend SVG rendering proof of concept [ci skip] (#15781)
* Backend SVG rendering proof of concept [ci skip]

* Update cssbox to 5.0.0

* Render bar, line, and pie charts in js to svg

sparkline is now done in js, bar is now recognized and done in js, new
:categorical/donut as well

* Remove api route for render

* pass along render-type, not hardcoded to :inline

* Move bar chart above sparkline and remove line check

In order to introduce the bar chart type need it above the sparkline
check since it is otherwise the same except for display property of
the card. But lots of tests assume that this will get hit with a nil
display type set in testing so remove checking for `:line` allows all
the testing cases to hit the right type

* Fix tests now that bar graphs aren't html but images

* Include attachments for bar charts

* Move over to in-tree bundle

* Force everything [ci noskip]

trying to ensure that the built jar includes the newer
"resources/frontend_client/app/dist/lib-static-viz.bundle.js"

* Run `yarn build-static-viz` in backend-deps in CI

this js file is now a hard dependency of the backend so it fits in
this tsk. All such things that depend on the backend sources will need
it. Makes me think perhaps we want a checked in version but i'm not
sure yet.

* Look on classpath not filesystem for js bundle [ci noskip]

* Move yarn build-static-viz into the checkout step

* License information for antlr4-runtime

* create attachment for categorical donuts

* add ordinal legend to donuts (#17177)

* set widths of html image and svg image to 1200

* Revert "add ordinal legend to donuts (#17177)"

This reverts commit 1eb81d2ebf.

* Helper functions to render html easily

* readme in dev

* readme ensure that static viz bundle exists

* Cleanup ns after removing proxy

* Donut chart colors and legend (#17251)

* use external color map for fill per dimension

* Add support new color legend for donut

* Ensure text doesn't appear as link

entire thing is actually the body of a link tag for emails but we want
a decent text color rather than a default link color

* use chart colors from https://stats.metabase.com/_internal/colors

* Make checkers happy

- remove unused imports
- add a docstring
- don't shadow fn with a local

* cleanup ns import

* Remove reflective call

* Cleanup ns on correct branch

Co-authored-by: dan sutton <dan@dpsutton.com>

* X-axis: just use (approx) 5 ticks to avoid overlapping labels (#17287)

* increase gap between arcs (#17271)

* Set rendering hints on html->image

* ignore width for now and make them larger

* Ns deprecation and some cleanup

* make namespace checker happy

* Simple tests for detecting chart type

* Rename from poc

* Tests for scalar/smartscalar

* cleanup js svg namespace a bit

* Tests of svg engine

* ns sorting after renaming

* Unify our two different js engine usages

settled on the js context. Has typed returns `(.asString ^Value ...)`
instead of perhaps capturing std out?
https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html

Context is a bit more friendly for getting source into it. One
downside is that the invocable bit isn't quite as nice. The old way
would return a java.util.functionFunction but the difference is

(.apply function (object-array args))

vs

(.execute fn-ref (object-array args))

* Don't io/resource the io/resource

* js engine tests

* Ns cleanup in js-svg

type hints in the js-engine ns mean we don't need as many classes from
polyglot here

* Cleanup of text, ns docstrings, alignment

* Fix fill->fill-opacity with parsed doc, not regex

* Make a single helper that loads a static viz bundle context

* Docstrings and make private in js-svg

* Sort imported classes in js-svg

* Make width passed down through rendering aparatus

- svgs are always rendered at 1200 for quality
- slack images of html are rendered at 1200 so that they can be zoomed
  in in the ui but slack automatically scales down
- email sends html and the full svg but includes img width tags so
  that is handled appropriately

* docstring

Co-authored-by: dan sutton <dan@dpsutton.com>
Co-authored-by: Kyle Doherty <5248953+kdoh@users.noreply.github.com>
Co-authored-by: Ariya Hidayat <ariya@metabase.com>
2021-08-17 14:21:17 -04:00
Anton Kulyk
6bdd27c605 Refactor notebook editor's join step (#17445)
* Fix imports order

* Extract JoinClausesContainer

* Refactor JoinClause container element

* Extract JoinTypePicker component

* Refactor JoinStepPicker

* Extract JoinTablePicker

* Extract JoinedTableControlRoot

* Extract label components

* Extract RemoveJoinIcon

* Add prop types

* Turn JoinClause into func component, fix ref usage

* Update notebook's step prop-types shape

* Extract callbacks
2021-08-17 19:04:55 +03:00
Nemanja Glumac
631b9fa8a9 #17450 Repro: New databases with "This is a large database ..." still uses the default sync+scan settings (#17476)
* Add helper function to choose/select a database

* Apply helper function to BigQuery and GA

* Add repro for #17450
2021-08-17 14:57:10 +02:00
pawit-metabase
baed054fdf upgrade to @percy/cypress 3.x (#17485)
* upgrade to @percy/cypress 3.x

@percy/cypress 2.x uses deprecated @percy/agent which includes
an old version of puppeteer. The old version of puppeteer causes
`yarn` command to fail on M1 macOS environment.

Upgrade to @percy/cypress 3.x removes the dependency and thus
solves the issue.

The upgrade was done by running `npx @percy/migrate`.

* remove percy healthcheck task

This no longer exists in 3.x, see
https://github.com/percy/percy-cypress/blob/master/README.md#upgrading

* remove deprecated percy/exec-action

and moved `percy exec` to the correct command

* run 'yarn install' before running percy
2021-08-17 16:56:51 +07:00
Cam Saul
5f6a1a0148 Change clj-kondo linter levels from :warn to :warning so it exits with nonzero status (#17475)
* Enable clj-kondo warnings

* (when (seq ...) ...) instead of (when-not (empty? ...) ...)
2021-08-16 20:01:40 -07:00
Ariya Hidayat
31917c110d Avoid prop shorthand in chart sidebar (#17478) 2021-08-16 17:14:49 -07:00
Nemanja Glumac
34c638f6bf Add "moderation" folder to e2e CI groups (#17481)
* Add "moderation" folder to e2e CI groups

* fix question-moderation tests

Co-authored-by: Dalton Johnson <daltojohnso@users.noreply.github.com>
2021-08-17 01:15:33 +02:00
Jeff Evans
19a2daab78 Update Snowflake JDBC driver version (#17452)
From 3.12.13 -> 3.13.6
2021-08-16 17:35:19 -05:00
Jeff Evans
18f6eb3612 Make DB name in c3p0 name more robust (#17447)
Consult any of these keys when trying to determine the "name" portion of the c3p0 data: :db :dbname :sid :catalog

Update existing `c3p0-datasource-name-test` to more robustly check the different portions of the c3p0 dataSourceName
2021-08-16 16:33:42 -05:00
Nemanja Glumac
306dca7e4a [Dashboard filters coverage] Add initial set of tests for dashboard SQL location filters (#17423) 2021-08-16 22:43:50 +02:00
Ariya Hidayat
0eea666305 Avoid prop shorthand in _internal (#17471) 2021-08-16 11:55:19 -07:00
Nemanja Glumac
260a17efa3 Fix propType warning for RawMaybeLink (#17464) 2021-08-16 20:15:39 +02:00
Dalton
82a146977c add moderation events to question timeline (#17401)
* add moderation events to question timeline

* tweak the height of the DrawerSection header

* replace history modal & control drawer state via redux

* add/fix cy tests

* fix banner unit tests

* prevent leakage of 'null' moderation icon

* rename styled component

* add tests / rmv redundant fn

* remove should('exist') from moderation cy tests

* refactor to make biz logic of a null mod status clearer

* add selector unit test
2021-08-16 09:54:25 -07:00
Luis Paolini
7141db02cd Update 03-metadata-editing.md (#17470) 2021-08-16 13:36:02 -03:00
Luis Paolini
f47e2a8b43 Update Snowflake documentation (#17449)
* Update docs/administration-guide/databases/snowflake.md
We pushed https://github.com/metabase/metabase/issues/10142 but we never upgraded the documentation :(

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-08-16 13:09:40 -03:00
Ariya Hidayat
e49aea2f0c Avoid prop shorthand in the navbar (#17460) 2021-08-16 08:08:41 -07:00
Alexander Polyankin
c27349976e Prevent infinite re-rendering when the scroll bar appears/disappears (#17444) 2021-08-16 17:22:16 +03:00
Nemanja Glumac
9aec494584 Add initial set of tests around SQL dashboard number filters (#17395) 2021-08-16 15:38:27 +02:00
Alexander Polyankin
0407511474 Add vertical legends with Popover (#17433) 2021-08-16 15:29:09 +03:00
Alexander Polyankin
56b0802c7c Add LegendLayout to LineChart (#17467) 2021-08-16 14:41:25 +03:00
Ariya Hidayat
212c2d8600 codecov config: enable carryforward (#17454)
With flags, and potentially not all coverage info will be submitted on
every commit, it seems that carryforward is necessary.

https://docs.codecov.com/docs/carryforward-flags
2021-08-15 21:48:29 -07:00
Dalton
ac6b4ac315 add verification badge to question lists (#17426)
* add verification badge to question lists

* make rightIcon movable via grid/justify-self

* lint fix
2021-08-13 16:26:30 -07:00
Ariya Hidayat
828ece695d Don't use prop shorthands for some home containers (#17451) 2021-08-13 14:03:12 -07:00
Alexander Polyankin
0124b59706 Use LegendCaption directly in LineChart (#17396) 2021-08-13 21:57:54 +03:00
Ariya Hidayat
b3e5e5c8cd Upload front-end code coverage to codecov.io (#17440)
* Tweak Codecov settings to account for front-end coverage
* Scope back-end coverage with the correct codecov flag
* Add enterprise/frontend
2021-08-13 10:37:40 -07:00
Anton Kulyk
4b8a541c83 Polish CollectionBadge for official items (#17408)
* Group Badge's icon props into a single `icon` prop

* Allow overwriting Badge's hover color

* Fix CollectionBadge hover for official items

* Fix CollectionBadge size for official items

* Fix QuestionDataSource badge

* Use iconPropTypes in Badge

* Make CollectionBadge icon code more compact
2021-08-13 20:28:54 +03:00
Anton Kulyk
49e0d4e4cf Increase official collection badge in search results (#17409) 2021-08-13 20:23:37 +03:00
Anton Kulyk
179e229d37 Update homepage official collection display (#17404) 2021-08-13 12:26:48 +03:00
Anton Kulyk
2950365bbf Update collection type input (#17405)
* Add SegmentedControl variants

* Update CollectionAuthorityLevel widget look
2021-08-13 12:26:29 +03:00
Noah Moss
38b1d10631 Add "Send to Slack now" button (#17438) 2021-08-12 23:35:35 -07:00
Ariya Hidayat
0953c37cfa Trigger front-end linter CI if ESLint configs are modified (#17437) 2021-08-12 21:07:56 -07:00
Noah Moss
b11689473c Add hourly option for email scheduling (#17425) 2021-08-12 10:51:41 -07:00
Ariya Hidayat
8baa77fcf7 Do not use prop shortands in the database edit (#17421) 2021-08-12 09:55:47 -07:00
Noah Moss
b19028c3b6 Fix order of cards in dashboard subscriptions (#17419) 2021-08-12 09:28:30 -07:00
Ariya Hidayat
ffebacf2f0 Remove Flex/Box prop shorthand in metabase/components (#17345)
* Remove Flex/Box prop shorthand in metabase/components

* Grid's width is an array (responsive sizes)
2021-08-12 08:12:46 -07:00
Anton Kulyk
8789a427ef Add visual smoke test for notebook editor (#17432)
* Add visual smoke test for notebook editor

* Rename notebook visual test

* Update min height for Percy
2021-08-12 18:11:36 +03:00
Gustavo Saiani
329c53fa53 Improve Dashboard component: separate semantics from styles and extract subcomponents (#17366) 2021-08-12 08:30:26 -03:00
Ariya Hidayat
eb09025c5e Do not use Flex prop shorthands in version notice (#17416) 2021-08-11 17:03:13 -07:00
Howon Lee
a4fded555d #13136 dynamically determining supporting features by database instance (#17319)
Previously the multifunction for supporting features was always implemented as a trivial true function. However, for mongo we need an actual version number, so here we go
2021-08-11 11:12:41 -07:00
Noah Moss
33bc4dde43 XLSX auto-sized columns, frozen header and auto-filters (#17325) 2021-08-11 10:26:35 -07:00
dpsutton
c60dfc5f26 Changing type (#16776)
* Move sync executor to bespoke namespace

* Refingerprint fields on type change

* Check if can connect in refingerprint-field!

* docstring update

* Cleanup tests a bit

* Error handling

* Table field values endpoint on sync.concurrent executor

* ns sort api field

* ns cleanup
2021-08-11 13:06:15 -04:00
Noah Moss
3ec2c8a83c Fix column settings button if column settings side bar is already open (#17355) 2021-08-11 07:30:06 -07:00
dpsutton
4066fee5f9 Namespace for extensions to clojure.test (#17400)
* Namespace for extensions to clojure.test

if you do a subselection of tests, you might not get the `schema=`
defmethods and then your tests won't compile. Ns docstring to keep the
namespace simple and targeted to global effects. we don't want to load
models and do extra work, just install some test utilities that aren't
ever required directly

* Add aliases

clojure.test had been refer :all

* require the effects in metabase.test.util as well

Namespace cleaner got a bit too aggressive

stupid ns

* Poke github actions empty commit
2021-08-11 10:19:12 -04:00
Anton Kulyk
adafc8132d Fix collection sidebar chevrons vertical alignment (#17403) 2021-08-11 16:01:58 +03:00
Anton Kulyk
a5992af000 Refactor CollectionBadge component (#17393)
* Add prop-types to CollectionBadge

* Convert CollectionBadge into functional component

* Fix CollectionBadge's prop drilling

* Fix Badge's import order

* Add prop-types to Badge

* Extract Badge's MaybeLink to styled file

* Extract Badge icon styled component

* Export MaybeLink
2021-08-11 12:40:37 +03:00
Noah Moss
0c4f3dc723 XLSX export formatting (#17226) 2021-08-10 17:46:50 -07:00
Gustavo Saiani
a69a75d66b Add visual regression tests for dashboard page (#17376) 2021-08-10 20:42:28 -03:00
Ariya Hidayat
35209ed4ee Fix babel loader when the cache is not desired (#17398)
https://webpack.js.org/loaders/babel-loader/#options
2021-08-10 16:05:16 -07:00
Dalton
d17e12bf9b add unit tests for (most) metabase-lib/metadata classes (#17367)
* add unit tests for metabase-lib/metadata classes

* fix typo
2021-08-10 10:56:01 -07:00
Alexander Polyankin
d3ec6cddbd Remove TitleLegendHeader (#17374) 2021-08-10 20:42:41 +03:00
Cam Saul
06c0017be0 Whitespace linting (#17348)
* Add the whitespace linter

* Fix whitespace linter errors [except for one file]

* Add a line that will intentionally break stuff to verify the linter is working.

* Ok, remove the line that caused the linter to fail.

* Use latest version of the linter

* Fix missing newline
2021-08-10 10:12:33 -07:00
Cam Saul
c18ff17a44 Java + Spark SQL prep steps should delete target dir on failure (#17360) 2021-08-10 10:10:48 -07:00
dpsutton
feafe08295 Include moderated status on virtual db/table information (#17340) 2021-08-10 12:25:41 -04:00
dpsutton
381d2f72dc Verification in search (#17329)
* Include and bump moderation status in search results

* Include limit 1 and order by for moderation review latests

backend does work to ensure there is an invariant that there is 1
most_recent true entry and all the rest are most_recent false. But if
there's some bug this invariant is violated we don't want to blow up
with multiple rows returned in these queries.

* Verification scoring is enterprise now

* wip moving moderation review to enterprise

still need to delete the old non-moved file

* add moderation icon to search results

* update names of icon props in SavedQuestionHeaderButton

* move moderation cypress tests, add test for search results

* Move moderation review api and test to enterprise

* fix props for getVerifiedIcon call

* add moderation status icon to collections

* add/improve moderation cypress tests

Co-authored-by: Dalton Johnson <daltojohnso@users.noreply.github.com>
2021-08-10 12:01:40 -04:00
Ariya Hidayat
a8a8189e28 Remove unused Slack's client library (JavaScript) (#17384) 2021-08-10 07:25:06 -07:00
Greg Wilson
c7e06d46a2 Missing last letters in troubleshooting guide titles (#17392) 2021-08-10 09:50:29 -04:00
Nemanja Glumac
5b9851b0df Add initial set of tests around SQL dashboard filters for text/category (#17382) 2021-08-10 12:48:56 +02:00
Ariya Hidayat
0a1b0db007 Visual test: consistent baseline with no randomization (#17380) 2021-08-09 13:25:35 -07:00
Ariya Hidayat
bde391e9f2 Percy GitHub Actions: shortcut the process to get the version (#17370)
Since it needs to grab the built JAR anyway, it's faster to obtain the
version.properties from the JAR.

This shaves off approx. 1 minute from Percy CI run.
2021-08-09 13:15:20 -07:00
Noah Moss
054a9e8bcb Include card names in export filenames (#17349) 2021-08-09 13:09:08 -07:00
Ariya Hidayat
7a93245285 Webpack prod build: exclude ESLint loader (#17371)
There's no point of processing files via ESLint loader when building
for production. If there's any linting issue at all, it should be
caught with a different CI run.

This shave off >2 minutes from Uberjar build (front-end step).

Development/hot-reload isn't affected at all.
2021-08-09 13:02:36 -07:00
Nemanja Glumac
38bb142a31 Fix wrong link in dashboard-filters user documentation (#17378) 2021-08-09 17:18:37 +02:00
Nemanja Glumac
0ff90d1a04 #17060 Repro: Duplication of the displayed table columns (#17361) 2021-08-08 02:58:12 +02:00
Nemanja Glumac
2186c69f95 #17211 Repro: No matching dashboard filter found when it clearly has been found (#17364) 2021-08-08 02:57:34 +02:00
Ariya Hidayat
ee68906484 Visual tests for some important URLs post on-boarding (#17358) 2021-08-07 10:35:29 -07:00
Ariya Hidayat
014d3c6ddb Continuously check when Metabase is ready, instead of waiting 3 mins (#17369) 2021-08-06 20:19:05 -07:00
Alexander Lesnenko
b5cc69e099 fix percy bot command (#17362) 2021-08-06 18:36:26 -07:00
Gustavo Saiani
57c7bbe618 Clean up prop destructuring in Dashboard component file (#17338) 2021-08-06 18:48:40 -03:00
Gustavo Saiani
74b02afd80 Remove flow types (#17337) 2021-08-06 16:58:58 -03:00
Dalton
7bc3013f22 use target of 'web' when using webpack-dev-server (#17356) 2021-08-06 12:08:25 -07:00
Luis Paolini
1d2bfe43de Update log-configuration.md (#16652)
Show how to increase Jetty verbosity

* Update docs/operations-guide/log-configuration.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-08-06 15:15:17 -03:00
Greg Wilson
87771b2aff Regularizing titles of troubleshooting guides. (#17296)
- Make all specific problems H2-level headings.
- Create a `doc-toc` div at the top for the table of contents.
  - Don't use `learn-doc` because we may want to style/show this one independently.
- Link to all problem headings.

Note: can't use metadata in a page header because our CI tools splat their own headers into these pages, so anything we add becomes part of the page body.
2021-08-06 08:39:21 -04:00
Nemanja Glumac
c3e8a9c928 #17212 Repro: Not possible to apply dashboard ID filter to a nested QB question (#17343)
* Add sane defaults to the card size in `createQuestionAndDashboard` custom command

* Add repro for #17212
2021-08-06 14:33:18 +02:00
Nemanja Glumac
12dbf0d590 Repro for #17339: collection tree should expand/collapse on parent collection name click (#17344) 2021-08-06 13:37:12 +02:00
Jeff Evans
988ae665cf Invalidate cached pooled connection when DB details change (#17307)
Adding new cache to `metabase.driver.sql-jdbc.connection` that tracks the DB details hash values per DB id

Checking if the non-empty hash value of DB details changed in `db->pooled-connection-spec` in order to invalidate an existing pool

Adding test that redefines the log fn to assert that the pool is invalidated on hash change
2021-08-05 21:14:57 -05:00
Ariya Hidayat
182124007d GitHub Actions: remove the check for Clojure version (#17341)
It's redundant since the job explicitly installs the proper version in
the previous step, and also running that prematurely pulls a bunch of
JARs from Maven Central.

This should shave 20 seconds from the CI runs.
2021-08-05 18:30:25 -07:00
Nemanja Glumac
28f7d87cd5 e2e test for "About Metabase" modal (partial repro for #15656) (#17308)
* Add parial repro for #15656

* Update frontend/test/metabase/scenarios/onboarding/about.cy.spec.js

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>
2021-08-06 02:34:01 +02:00
dpsutton
cf96df32b9 correct typo in driver prestor -> presto (#17334) 2021-08-05 15:27:10 -05:00
Cam Saul
2af2ba952d Bump some more backend dependencies (#17326)
* Bump some more backend dependencies

* Add license info for com.sun.activation/jakarta.activation

* Fix reflection warnings

* Revert bump of MariaDB for now
2021-08-05 11:29:52 -07:00
Ariya Hidayat
ae9f1d8c80 devcontainer: Remove Leiningen and use the latest Clojure (#17327) 2021-08-05 10:23:22 -07:00
Jeff Evans
7285e3d4a2 Fix Presto JDBC connection error (#17293)
Remove the `driver/can-connect?` implementation and move the `select-keys` logic instead to the existing place in `sql-jdbc.conn/connection-details->spec`

Update test to also include the `:let-user-control-scheduling` details entry
2021-08-04 17:05:52 -05:00
Cam Saul
f9600eadf6 Bump Jetty/Bouncycastle/Jackson/Apache Commons dep versions (#17318)
* Bump some backend deps.

* Update i18n/locale to work with new version of LocaleUtils
2021-08-04 14:32:13 -07:00
Cam Saul
ad69111e02 Minor test runner/config fixes (#17323)
* Fix JUnit output not correctly stripping ANSI color codes

* Remove find-tests profiling log message

* 1-arg arity of metabase.test-runner/run

* Fix bug with metabase.test-runner/find-tests with a single test name
2021-08-04 14:19:02 -07:00
Noah Moss
089e02dd6d Change default for currency style to code if symbol not supported (#17301) 2021-08-04 14:06:43 -07:00
Dalton
bfbd259905 improve searchability of metabase-lib class instantiations (#17320) 2021-08-04 13:58:32 -07:00
Jeff Bruemmer
df5a5d0b95 docs - troubleshooting logs (#17304) 2021-08-04 16:56:12 -04:00
Alex Ghiculescu
97b4ee93d8 Fix location of share icon (#15919)
* Fix location of share icon

* Update 12-public-links.md

Differentiate between dashboard and question sharing

Co-authored-by: Luis Paolini <paoliniluis@gmail.com>
2021-08-04 13:07:28 -07:00
Cam Saul
fc7f961195 Bump depstar version to prevent annoying messages about having multiple SLF4J bindings (#17309) 2021-08-04 10:47:38 -07:00
dpsutton
69bb775885 Remove last of leiningen, update comment in shadow and lsp classpath (#17317)
* Remove last of leiningen, comment in shadow and lsp cp [ci skip]

* empty commit to flush [ci skip]
2021-08-04 10:44:58 -07:00
Ariya Hidayat
de2ce4f9cb Fix the styling of the buttons in the notebook (#17313) 2021-08-04 05:57:44 -07:00
dpsutton
84f4509dbe correct moderation review hydration (#17311)
* remove moderation reviews hydration

* Restore hydration of moderation_reviews and handle correctly

nested hydration is (i think) positional. So if you get something
handed to you you must return something in that position. Prevoiusly
was removing nils and then returning a smaller collection of hydrated
items (cards here). But this meant input might look like this

[card1 nil card2] and return [card1 card2] and in the nested hierarchy
things didn't get matched up correctly.

In the real world application it might look like this:

```clojure
{:ordered-cards
 [{:card-id 1}
  {:card-id nil
   :viz-settings {info-for text-card}}
  {:card-id 2}]}
```

And the nil card comes into this function and we return them in a
strange manner things get wonky
2021-08-03 17:19:24 -07:00
Maz Ameli
730cb5918e update strings for 0.40.2 2021-08-03 15:58:03 -07:00
Nemanja Glumac
af99fc023d Update project.clj references (#17294)
* Remove `project.clj` from Percy workflows

* Replace `project.clj` with `deps.edn` in `build-for-test` script

* Update reference to the `project.clj` in the comment
2021-08-03 23:58:24 +02:00
Howon Lee
6331c3b130 Make the field search do limits (whacks #17228) (#17283)
We're playing this whackamole because we added the middleware to universally sorta stomp on any `limit` or `offset` params, and they got stomped on. Which, in turn, led to my PR to make the default not limited. Which, in turn, led to the other issue this PR solves which makes the search things we relied upon to not have a limit, have a limit.
2021-08-03 13:59:58 -07:00
Nemanja Glumac
84a6abd1ad Use jest-dom/extend-expect library globally (#17292)
* Register `@testing-library/jest-dom/extend-expect` globally

* Remove unnecessary imports from unit tests
2021-08-03 21:42:51 +02:00
Luis Paolini
8c344e2457 Remove .git directory in .dockerignore so version can build correctly (#17300) 2021-08-03 12:38:47 -07:00
Cam Saul
c24fc9dd7c Cloverage shouldn't instrument tests/test utils (#17298) 2021-08-03 12:00:53 -07:00
Cam Saul
e1e815f84b 🏎️🏎️🏎️ test runner improvements 🏎️🏎️🏎️ (#17286)
* Add some dox

* Rename test-runner & cloverage -> metabase.test-runner & metabase.cloverage-runner

* Move JUnit-related test runner code to separate namespace

* Bespoke JUnit-output code

* Delete unused .lein-classpath file

* Do JUnit writes in a cached thread pool

* Add failing test to make sure JUnit output works as expected...

* Move bad-test to metabase.bad-test so the FAILING tests actually run

* FASTER TEST LOADING 🏎️

* Test CircleCI :system-out

* Final cleanup (hopefully)

* Sort some namespaces; allow initializing :plugins when namespaces get loaded for now.

* Need those [[tags]] in docstrings

* Fix bad docstring
2021-08-03 11:01:30 -07:00
Nemanja Glumac
9e1491362b Upgrade @cypress/webpack-preprocessor (#17180) 2021-08-03 19:29:19 +02:00
Nemanja Glumac
9e33322ce2 Prepare jest config for FE code coverage (#17182) 2021-08-03 19:28:27 +02:00
Alexander Lesnenko
88b3b536f9 Fix incorrect props are passed to CollectionPermissionModal when used for snippets folders (#17284) 2021-08-03 20:18:12 +03:00
Dalton
b7fa2f34d5 Add the ability to verify/unverify questions (#17030)
* rmv old bucm icons and remove verified fill color

* add moderation action section to sidebar

* add moderation review icon to the saved question header button

* hide moderation section when is not a moderator

* add UI for ModerationReviewBanner

* Backend for moderation-review

- create table moderation_review. Same as before but also has a
  "most_recent" boolean flag for the most recent moderation for easy
  lookup
- POST /moderation-review/ . Status can be "verified" or nil
- must be an admin to post
- No PUT or edit route yet. Not sure if this is even
  necessary. _MAYBE_ to edit the text, but certainly not for the
  status, ids, etc. If there's to be history, let's build some history
- Ensure we never have more than 10 reviews. Adding a new review will
  delete the older ones, mark all old ones as not `most_recent`, and
  add the newest one as `most_recent true`
- Ensure the card actually exists before creating the mod review
- Since admin only at this time, don't need to check moderate
  permission or view permission
- When hydrating ensure reviews are ordered by id desc. Should mimic
  the created_at desc

* fix moderation review banner tooltip offset

* disable verification button when already verified

* rmv iconOnly prop because it seems to do nothing

* update getLatestModerationReview to rely on most_recent boolean

* Return 400 on invalid status to post /moderation-review

the schema was using keywords on the left hand side rather than the
symbols. Required a change to the docstring generator, when it made a
docstring for enums, it would call (sort (:vs enum)) and need to
string em.

* Add ModerationReview model to models.clj and copy infra

* hydrate moderation reviews on cards

* clean up + wire up to BE + ensure mod buttons don't show for normal users

* rmv unused moderation redux logic from QuestionDetailsSidebarPanel

* finish writing unit tests for FE

* ensure getIconForReview returns an object

* enable/disable verify button tooltip when unverified/verified

* add e2e tests

* fix tests

* styling tweaks

* more styling on moderationReviewBanner

* add function for abbreviated timestamp

* increase fontsize of timestamp back to 12

* fix tooltip offset

* ensure custom locale is separate from 'en' and not used for other languages

* Deletion moderation reviews when deleting cards

i had actually thought this was a much larger problem. But it turns
out we almost never delete cards (thanks comment!). And so we won't
really generate a lot of garbage.

I was worried that since we aren't using actual foreign keys but just
`moderated_item_type "card"` and `moderated_item_id 2` we would have
deleted cards with these moderation reviews but that is not the case
as the cards aren't deleted.

* hide verify disabled button when a question is verified

* update test to use queryByTestId

* Hydrate moderation reviews on cards on ordered cards

* Handle mysql's lack of offset functionality

mysql cannot handle just a `offset` clause, it also needs a limit

clause grammar from
https://dev.mysql.com/doc/refman/8.0/en/select.html:

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

select id, name from metabase_field offset 5;         -- errors
select id, name from metabase_field limit 2 offset 5; -- works

Since our numbers are so small here there is no worry and just do the
offset in memory rather than jump through hoops for different dbs.

* Batch hydrate moderation reviews

* Don't let /api/user/:userId failure conceal moderation banner

* fix moderation cy tests

* work around possible bug in toucan hydration

dashboards hydrate ordered cards
(hydrate [:ordered_cards [:card :moderation_reviews] :series])

Ordered_cards are dashboard_cards which have an optional card_id. But
toucan hydration doesn't filter out the nils as they go down. It seems
toucan returns a nil card, and then when hydrating the
moderation_review, passes the collection of all "cards" including the
nil ones into the hydration function for moderation_reviews

This feels like a bug to me

* Cleanup moderation warnings

* Docstring in moderation review

* include hoisted moderated_status on cards in collections api

* Expect unverified in test 🔧

Co-authored-by: dan sutton <dan@dpsutton.com>
Co-authored-by: Maz Ameli <maz@metabase.com>
Co-authored-by: alxnddr <alxnddr@gmail.com>
2021-08-03 09:36:18 -07:00
Dalton
dee19dfbd6 Handle mutation of vizSetting column when syncing columns in a native question (#17279)
* Handle mutation of vizSetting column when syncing columns of a native question

When calling Question's _syncNativeQuerySettings method we need to treat
existing, mutated columns as invalid so that they are filtered out and a
new column takes the existing column's place.

The function we use to find valid columns, findColumnIndexForColumnSetting,
will return true if it finds a matching field_ref OR a matching name, so we
also need to check the addedColumns array we just created in order to remove
any columns from vizSettings that also exist there, since we combine the two
at the end of this method.

* add unit tests for _syncNativeQuerySettings
2021-08-03 09:21:48 -07:00
Nemanja Glumac
c4d777ac6b Update lein references in scripts (#17291)
* Remove `yarn start` script

* Remove `lein docstring-checker` and `lein-bikeshed` scripts

* Update `lein` references in `ci-backend` script
2021-08-03 16:42:04 +02:00
Luis Paolini
d5b89f6636 Fix Elastic Beanstalk deployment in v40 (#17261)
* Intermediate commit

* Add the step to include .platform dir into the bundle
2021-08-03 07:36:27 -03:00
Alexander Lesnenko
b604fb164c fix dev run (#17270) 2021-08-03 00:04:02 +03:00
Gustavo Saiani
9b4c9a22c1 Close collection sidebar on mobile (#17278) 2021-08-02 18:01:36 -03:00
Nemanja Glumac
4a198de03e #17268 Repro: Snippet folder permissions applied to root (#17280) 2021-08-02 22:58:29 +02:00
Nemanja Glumac
f9983424db Update yarn build scripts (#17269) 2021-08-02 22:39:15 +02:00
Gustavo Saiani
49b6954e0e Improve CollectionsList component (#17277) 2021-08-02 17:35:30 -03:00
Jeff Evans
f4050ff1a9 Fixing Presto JDBC issues (#17265)
Updating schema connection property to have proper display name

Updating display name for database to be "Schema"

Fixing `driver/can-connect?` impl in `presto_jdbc.clj` to actually use the correct driver, and dissoc `:engine` before calling the `sql-jdbc.conn` method

Adding test for the `test-database-connection` method, which is what led to the error from the UI
2021-08-02 14:45:25 -05:00
Cam Saul
5f613399de Fix failing tests after #16749 (#17274)
* Revert changes to activity and activity-test namespaces

* Add some sanity-checks to help debug the failing test

* Delete accidental newline
2021-08-02 12:11:18 -07:00
Cam Saul
dfc211e3a4 Add :nrepl alias [ci skip] (#17276) 2021-08-02 11:37:51 -07:00
Ariya Hidayat
847e28b286 Let VS Code recognize decorators (#17258)
https://www.typescriptlang.org/tsconfig#experimentalDecorators
2021-08-02 09:27:10 -07:00
Cam Saul
0eef2252a9 Switch to tools.deps (#16749) 2021-07-30 18:41:24 -07:00
Howon Lee
39e87603ac Default pagination #17200 (#17210)
Change default behavior of pagination to be what i imagined it to be. Really should've taken Dan's question to heart and actually tested that bit...
2021-07-30 18:16:44 -07:00
Jeff Evans
313f097927 Only build currently active drivers (#17262)
Only build currently active drivers

Update `all-drivers` fn so that it only "finds" drivers that have either a `project.clj` or `deps.edn` file (i.e. some build file), and ignores the directory otherwise. This is to deal with cached artifacts hanging around between builds in a shared executor type environment (ex: CircleCI), where even though the checkout won't bring in some driver directory that doesn't exist on the target branch, some other files (such as `pom.xml` or a `target` directory), might still be hanging around
2021-07-30 17:24:33 -05:00
Noah Moss
63d5dbfaa6 Visualization settings query processor middleware (#16972) 2021-07-30 13:41:58 -07:00
Greg Wilson
746e5b9c0e Troubleshooting sync/fingerprint/scan (#17255)
* First draft of sync/fingerprint/scan troubleshooting

* Merging fixes from @flamber.

* Merging Jeff's suggestions.
2021-07-30 15:06:01 -04:00
Dalton
3a7c3987f6 Upgrade babel to 7.x.x and jest to 27.x.x (#17137)
* Update babel dependencies to latest

* Remove some old babel dependencies

The dependencies in this commit include dependencies that have been
renamed, such as babel-cli which is now @babel/cli. It also includes
dependencies that have been replaced, such as babel-preset-stage-0 and
its ilk, which have been replaced with @babel/preset-env.

* Remove babel-register dependency

This is referenced in our webpack.config.js file. I don't think we need
Babel in our Node envionment, but I could be wrong, so leaving this as a
separate commit.

* Remove @babel/standalone and dependent code

We're using @babel/standalone to support the writing of JSX in our
internal-only ScratchApp editor. Unfortunately, this dependency is
large--1.5mb not gzipped--and our current build does not intelligently
split bundles, meaning our users our burdened by the size of this
dependency whenever they must redownload the Metabase JS bundle.

I'm removing it. We should still be able to write JS in the ScratchApp,
but JSX no longer.

* Add @babel/node to dev deps

Needed by a cypress command

* Add browserslist config

Babel's preset-env dep needs this config to determine how to transform
our JavaScript. By default I believe it ends up defaulting to
"defaults."

"defaults" is equivalent to the following rules:
> 0.5%, last 2 versions, Firefox ESR, not dead

A comma between rules represents a UNION operator.

Per
https://www.metabase.com/docs/latest/faq/general/supported-browsers.html
we have deprecated IE 11 so I am including that explicitly in our
browserslist.

* Update babelrc plugins and presets

- Replaced presets with preset-env and preset-react
- Updated the names of some plugins, like transform-decorators-legacy,
  which is now @babel/plugin-proposal-decorators with an explicit
  "legacy: true" passed in the config.
- Removed add-react-displayname because it is included in preset-react
- Removed transform-builtin-extend because it is included in preset-env*
- Removed syntax-trailing-function-commas because it is supported by
  all browsers we support

* note: There is a "loose" config option for handling the extension of builtin
classes. We may need it, but I am not sure.

* Update babel cli args

Replace -q with --quiet because -q no longer exists

* Fix circular dep in auth.js by making it async

Our app unfortunately contains MANY circular dependencies. Some, like
this one, caused problems when the app instantiates because the
"refreshCurrentUser" method is undefined when auth.js is initially run.

While we should in the future avoid having circular deps in the first
place, making them run async by requiring the dep and function run-time
fixes this particular issue.

* Fix circular dependency in metabase/redux/requests.js

The handleActions and createAction methods imported from
"metabase/lib/redux" are actually just methods from the "redux-actions"
dependency... so importing those methods directly from that dep fixes
this circular dependency problem.

* Remove references to global.services and exports in metabase/services

This line breaks the build. Git blame says the line is 5 years old, and
I wouldn't expect such code to be used with how our app now requires
deps.

* Fix MBQLArrayClause problem caused by Array extension

* Explicitly pass args from flatMap to function via anonymous cb

I think the old Array.prototype.flatMap prototype must've had different
args. They are now "currentValue, index, array" so when we passed it
"enumeratePaths" as a callback, the second arg of enumeratePaths gets
set to a number. This breaks the logic of enumeratePaths because it is a
recursive function that depends on that second arg getting initialized
as an empty array by default.

* Remove code that spreads non-iterable value in array

New Babel is stricter about handling this sort of code that doesn't
match the JS spec. You can't spread an undefined value inside of an
iterator.

* Update jest and babel-jest to latest

Updating Babel breaks our unit tests. Updating nothing causes every test
to fail due to a Babel version mismatch. Updating only babel-jest causes
the following error:

TypeError: Jest: a transform must export a `process` function

There may be a way around updating Jest, but updating it does not appear
to be too difficult.

* Set the testEnvironment to jsdom

This was the default testEnvironment in our old version of jest. At some
point the default was changed to node.

* Remove unfinished "pending" unit tests

I'm unfamiliar with this pending function, but the function no longer
exists, causing the tests to fail.

* don't pass async callback to describe

* Update name of runTimersToTime to advanceTimersByTime

* Fix incorrectly nested unit test

* mock SVGElement.prototype.getBBox method

* Don't return values in describe callback

* Move variable declaration to above usage

* Fix prettier error

* Upgrade `documentation` library to the latest version (13.x.x)

This library was the only one left that was still using Babel 6.

* Return an MBQLClause instance after using Array methods

* remove 'not IE 11' from browserslist

* Remove mock that breaks unit test

Co-authored-by: Nemanja <31325167+nemanjaglumac@users.noreply.github.com>
2021-07-30 09:50:10 -07:00
Noah Moss
e10ec3e393 Hide currency symbol option if not supported (#17240) 2021-07-29 17:33:17 -07:00
Noah Moss
042abc928a Move currency list from JS to Clojure (#17243) 2021-07-29 14:13:26 -07:00
Cam Saul
89382bae96 Run Eastwood linter against test namespaces. Remove reflection-warning script (#17193)
* Fix some Eastwood failures

* Fix a lot of Eastwood errors now that it runs against test namespaces [ci skip]

* Run Eastwood against test namespaces [WIP]

* Bump Eastwood version to fix some errors in Eastwood itself

* Fix another lint warning

* Fix test failure

* More test fixes 🔧

* Fix all the warnings!

* Test fix 🔧

* Bump Eastwood GH action timeout to 20 minutes (!)
2021-07-29 11:01:18 -07:00
Jeff Bruemmer
9aefcfb734 docs - update troubleshooting section (#17236) 2021-07-29 12:45:43 -04:00
Cam Saul
a967c2a6e5 Run namespace checker linter on test namespaces (#17239) 2021-07-28 16:38:53 -07:00
Ariya Hidayat
bc9f0d54ba devcontainer: Ensure that Node.js and Yarn are installed (#17237)
https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
2021-07-28 15:02:29 -07:00
Alexander Lesnenko
1a926314c9 Fix autobackport job fails because of branches like release-x.39.4-something (#17241) 2021-07-29 00:16:54 +03:00
Alexander Lesnenko
04799fe8a2 auto cherry pick to release branch on merge into master (#17225)
* auto cherry pick to release branch on merge into master

* rename workflow, label
2021-07-28 23:44:09 +03:00
Anton Kulyk
8002af2208 Display official collection badge on the homepage (#17215) 2021-07-28 09:36:53 -07:00
Anton Kulyk
47dadae096 Fix plural form for CollectionList.styled.js 2021-07-28 09:36:53 -07:00
dpsutton
0dd4b8fcee Include authority_level on collections in collection items (#17204) 2021-07-28 09:36:53 -07:00
Anton Kulyk
3051de19c8 Fix horizontal FormField label 2021-07-28 09:36:53 -07:00
Anton Kulyk
a728bafe82 Allow only admins to edit collection types, hide form field for personal collections (#17170)
* Rename collection's plugin `formFields`

* Add tests for collection type field visibility

* Limit collection types visibility

* Fix cypress tests
2021-07-28 09:36:53 -07:00
Anton Kulyk
0f4597d786 Display official question's badge when it's in regular dashboard (#17167)
* Add icon prop to LegendItem

* Add icon prop to LegendHeader components

* Add headerIcon prop to Visualization

* Add headerIcon prop to DashCard

* Display official badge on questions in regular dashboards

* Add headerIcon prop to Funnel

* Add headerIcon prop to LineAreaBarChart

* Extract hasLegendHeader variable

* Pass headerIcon to visualisations with custom header

* Add E2E tests

* Add Icon prop-types

* Use imported Icon prop-types

* Fix post-rebase issue
2021-07-28 09:36:53 -07:00
Anton Kulyk
d7e0838c97 Add ability to make all children collections official or regular (#17168)
* Add `update_collection_tree_authority_level` field

* Add authority level tree update

* Test authority level children bulk update
2021-07-28 09:36:53 -07:00
Anton Kulyk
32a88aa447 Display official badge throughout the application (#17125)
* Add getCollectionIcon function

* Add isRegularCollection function

* Display official badge in collections sidebar

* Don't dim official badge icon in collections sidebar

* Show root collection icon

* Use `CollectionsList.Icon` for "All personal collections"

* Fix CollectionBadge icon color

* Display official collection badge in search results

* Test official badge displayed correctly in sidebar

* Test official badge is shown throughout the app

* Show official badge icon in SavedQuestionPicker

* Use existing isPersonalCollection utility

* Show official badge icon in QuestionPicker

* Show official badge icon in CollectionPicker

* Minor CollectionIcon refactoring

* Use function declaration for isRegularCollection

* Add editCollection test helper

* Add changeCollectionTypeTo helper

* Remove duplicated assertions

* Add helper to create official collection

* Add testOfficialBadgeInSearch helper
2021-07-28 09:36:53 -07:00
Anton Kulyk
0a6877824d Bootstrap collections plugin, add collection types form (#17071)
* Add badge icon

* Add empty PLUGIN_FORM_WIDGETS

* Add empty PLUGIN_COLLECTIONS

* Extract `getWidgetComponent` from FormWidget

* Allow adding EE-only form widgets

* Add `authority_level` field to collections

* Fix SegmentedControl's `value` prop-type

* Specify icon sizes for SegmentedControl's options

* Add FormCollectionAuthorityLevel form widget

* Add `PLUGIN_COLLECTION_COMPONENTS`

* Add CollectionAuthorityLevelIcon

* Move ToggleMobileSidebarIcon out of PageHeading

* Display official badge on collection page

* Add authority level to collections plugin

* Rename `AUTHORITY_LEVELS` to `EE_AUTHORITY_LEVELS`

* Patch collections plugin with EE authority levels

* Fix authority level value for new collection form

* Add `cy.createCollection` command

* Add `describeWithoutToken` Cypress helper

* Test user can manage collection authority level

* Test collection types available only in EE

* Run prettier

* Keep regular collection opts in AUTHORITY_LEVEL

* Fix test comment

* Translate collection type names

* Avoid aliasing regular authority level
2021-07-28 09:36:53 -07:00
Anton Kulyk
9687939646 Fix POST /api/collection ignores authority_level (#17070) 2021-07-28 09:36:53 -07:00
Greg Wilson
502e860d8c Troubleshooting guide for sandboxing (#17207)
* Outlining items for troubleshooting guide for sandboxing.

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Incorporating minor suggestions

* Incorporating comment from @flamber

* Converting sandboxing troubleshooting guide to prose

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Johannes' fixes

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/sandboxing.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Jeff's edits

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>
Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-07-28 12:20:10 -04:00
Alexander Lesnenko
2cdc8df2b7 Skip Percy job triggered by comment early (#17232) 2021-07-28 16:02:41 +03:00
Greg Wilson
6bcc6b54dd Minor fixes to performance troubleshooting guide (#17221)
* Minor fixes to performance troubleshooting guide

* Update docs/troubleshooting-guide/performance.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Fixing a few small issues with the performance troubleshooting guide.

* Another fix to performance troubleshooting

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>
2021-07-28 08:10:11 -04:00
Cam Saul
490b40fd20 Update auto-generated API documentation [ci skip] (#17227) 2021-07-27 17:18:43 -07:00
Cam Saul
51f92486bd Enable clj-kondo failures on missing docstring; remove bikeshed (#17224)
* Enable clj-kondo failures on missing docstring; remove bikeshed

* Add missing docstrings
2021-07-27 16:13:55 -07:00
Alexander Lesnenko
92451f958a Fix image is rendered as url when there is a click behavior for the column (#17219)
* Fix image is rendered as url when there is a click behavior for the column

* add unit spec repro
2021-07-27 22:55:20 +03:00
Alexander Lesnenko
36be7a88cc Fix people dropdown goes outside of the screen (#17218)
* Fix people dropdown goes outside of the screen

* unskip repro
2021-07-27 22:54:55 +03:00
Alexander Lesnenko
f667c25305 add basic percy setup (#17162) 2021-07-27 22:54:37 +03:00
Greg Wilson
c4ce4bca00 Performance troubleshooting guide (#17174)
* First draft of performance troubleshooting guide.

* Update docs/troubleshooting-guide/performance.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Update docs/troubleshooting-guide/performance.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Update docs/troubleshooting-guide/performance.md

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>

* Incorporating @flamber suggestions

* Updating troubleshooting guide

Co-authored-by: flamber <1447303+flamber@users.noreply.github.com>
2021-07-27 13:28:03 -04:00
Jeff Bruemmer
221f09720b docs - troubleshooting guide: load from h2 (#17209) 2021-07-27 13:12:37 -04:00
Greg Wilson
0e4aaed595 Editing FAQ. (#17153)
* Editing FAQ.

- Minor updates to wording.
- Changed a couple of links to point at /learn articles.
- Regularizing title levels.
- Moved all out-of-page links into page foot to simplify consistency checking.

* Update docs/faq/general/do-we-need-a-data-processing-agreement.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/does-metabase-do-x.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/does-metabase-have-access-to-my-companys-data.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/how-do-i-ask-for-help.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/is-metabase-508-compliant.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/is-metabase-508-compliant.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/is-metabase-508-compliant.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/cant-access-data-i-need.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/i-am-not-getting-email-notifications.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/how-do-i-reset-my-password.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/how-do-i-ask-questions.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/how-do-i-answer-questions-with-joins.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/supported-browsers.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/what-if-i-find-a-bug.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/general/what-languages-can-be-used-with-metabase.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/setup/how-do-i-integrate-with-sso.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/setup/i-am-having-trouble-running-metabase.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/setup/what-is-h2.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/setup/which-databases-does-metabase-support.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/cant-access-data-i-need.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/faq/using-metabase/how-do-i-answer-questions-when-data-is-in-multiple-databases.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-07-27 11:35:04 -04:00
Ariya Hidayat
22138b39df Don't use extend for PaddedTextButton (#17197)
extend is deprecated, see the previous PR #17048
2021-07-26 10:42:48 -07:00
Greg Wilson
3b368fd118 First editing pass through troubleshooting guide (#17154)
* First editing pass through troubleshooting guide

* Update docs/troubleshooting-guide/application-database.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/application-database.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/application-database.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/timezones.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/application-database.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/datawarehouse.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/docker.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Update docs/troubleshooting-guide/index.md

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>

* Moving comma

Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-07-26 12:19:49 -04:00
Nemanja Glumac
3ad4c3b95a #17186 Repro: People search dropdown goes outside of the screen (#17203) 2021-07-26 17:05:02 +02:00
Anton Kulyk
1211ded01d Repro for #15342: The order of join-type causes query fail (#17201) 2021-07-26 16:52:13 +03:00
Nemanja Glumac
996835caf6 #17200 Repro: Only the first 50 user groups are displayed (#17202) 2021-07-26 15:43:28 +02:00
Anton Kulyk
10caf59b5a Refactor FormField component (#17089)
* Improve prop-types, move to the top of the file

* Make FormField a functional component

* Simplify default props assignment

* Remove redundant comparisons

* Add InputContainer component

* Extract ALL_DOT_CHARS regexp for form field id

* Simplify Label

* Extract rootClassNames

* Fix formFieldId

* Fix FormField prop type
2021-07-26 13:54:17 +03:00
Dalton
bc90e06915 add question details sidebar (#16803)
* add question details sidebar (code from bucm)

update some cy tests

rmv moderation-related code

rmv padding on description

merge history button logic into label

lint fix

update some clicks in cy tests

update styles to use styled-components

fix more cy tests

rmv unused component

rmv unused reference

rmv unused prop

remove styling code that is no longer necessary

rmv extraneous space

fix translation

rmv added util class

move styled component to own file

* add revision util tests

* rmv some unneeded question panel styling

* move files into query_builder directory

* rearrange stuff in file

* ClampedDescription unit test

* add QuestionActionButtons unit tests

* add SavedQuestionHeaderButton test

* add QuestionActivityTimeline tests

* tweak/improve props/propTypes

* fix cy test referencing question description

* fix revision history cy test

* Question sidebar visual polish (#16942)

* style tweaks

* restyle Revert button

* add a little breadcrumb spacing

* make LastEditInfoLabel use Badge instead of TextButton

* bring back TextButton

* Revision History => History

* fix activity timeline unit test

* rmv unused styled components

Co-authored-by: Dalton Johnson <daltojohnso@users.noreply.github.com>

* hide 'add a description' button when read only

* update permissions cy tests

* update ClampedDescription unit test

* use size enum instead of boolean

* move export to bottom of file

* move modal magic strings to a constants file

* clobber all qb state when reloading

* Fix reversion cy tests

Co-authored-by: Maz Ameli <maz@metabase.com>
2021-07-23 15:05:04 -07:00
Jeff Evans
80b46b1f75 Implement JDBC based Presto driver (#16194)
Implement JDBC based Presto driver

Adding new Presto JDBC driver using the PrestoDB JDBC driver from `https://github.com/prestodb/presto`

Marking the old Presto driver as being `superseded-by` the new one

Pulling out common Presto code into new presto-common driver (modeled after the relationship between, ex: `googleanalytics` and `google)`

Putting common QP/HoneySQL logic into the new (abstract) :presto-common driver

Updating :presto driver to extend from the new common driver and only adding HTTP/REST API related methods

Adding implementation of Presto JDBC driver, named :presto-jdbc, extending from :presto-common and :sql-jdbc

Using com.facebook.presto/presto-jdbc as underlying JDBC driver dependency (since this is explicitly for Presto clusters, as opposed to Trino)

Adapting code from the existing Presto driver where appropriate

Adding new dependency-satisfied? implementation for :env-var, to allow for a plugin to require an env var be set, and making the Presto JDBC driver depend on that (specifically: `mb-enable-presto-jdbc-driver`)

Adding CircleCI configuration to run against the newer Presto (0.254) Docker image

Adding explicit ordering in a few tests where it was missing

Fixing presto-type->base-type (timestamps were being synced as :type/Time because the regex pattern was wrong)

Add tx/format-name test implementation for :presto-jdbc to lowercase table name

Make modified test Oracle friendly

Fixing bug parsing the `[:zone :time]` case within `metabase.util.date-2.parse/parse-with-formatter`; the offset is nil so it can't be passed directly in this case, so use the `standard-offset` fn (which was moved from `date-2` to `common` to get a standard offset for that zone

Fixing more test failures by adding explicit ordering

Changing sync to check whether the driver supports foreign keys before attempting to sync those (since drivers might throw an exception if attempting to check)

Moving some common test dataset functionality between :presto and :presto-jdbc to a new test.data ns for :presto-common

Adding HoneySQL form for :count-where, since we have to explicitly give a higher precision Decimal in order for Presto to not reduce the precision in results

Put limit within subquery for `expression-using-aggregation-test` (since ordering from subquery is not guaranteed in Presto)

Adding impls for ->prepared-substitution to handle substitutions for native query params

Adding HoneySQL impls for `mod` (to do as "mod(x,y)" and `timestamp` (since it's a function with no parens to invoke) functions

Adding various `sql.qp/date` impls that use the `AT TIME ZONE` operator to account for report tz, and make bucketing tests happy
2021-07-23 17:03:06 -05:00
Nemanja Glumac
5836393347 [Dashboard filters coverage] Add initial set of tests for dashboard text/category filters (#17192) 2021-07-23 22:34:08 +02:00
Nemanja Glumac
2a51e37906 [Dashboard filters coverage] Add initial set of tests for dashboard location filters (#17191) 2021-07-23 21:42:56 +02:00
Nemanja Glumac
7748d094b7 [Dashboard filters coverage] Add initial set of tests for dashboard number filters (#17188)
* Add initial set of tests for dashboard number filters

* Fix `describe` title for date fitlers
2021-07-23 21:17:43 +02:00
Nemanja Glumac
35ccbbead1 [Dashboard filters coverage] Add initial set of tests for dashboard ID filter (#17190) 2021-07-23 21:17:12 +02:00
Jeff Evans
3ddcb2638c Add support for driver deprecation (#17028)
# Backend changes

Introducing new `superseded-by` property to plugin manifest YAML, which will indicate the driver that is to eventually replace this one (and will drive UI/UX behavior).  If a driver declares this property, then it's considered to be deprecated in favor of the specified one.

Adding top level `test_modules` directory (with the same structure as modules) for the sole purpose of module/plugin testing of YAML files, which will not be included with the driver build

Updating `driver-plugin-manifest` to look for the new `test_modules` directory in addition to `modules`, when loading the driver manifest

# Frontend changes

Calculate `supersededBy` and supersedes maps from the "superseded-by" property for each engine

Change the options for the engine field to use a function to dynamically show the legacy driver if allowed by rules (either the new driver is selected, or the legacy driver was already selected for an existing DB, or the driver is not superseded by anything)

Add new `DriverWarning` component to show these warnings based on supersede status

Co-authored-by: Anton Kulyk <kuliks.anton@gmail.com>
2021-07-23 14:03:46 -05:00
Nemanja Glumac
33939b0cf0 [Dashboard filters coverage] Add initial set of tests for dashboard date filters (#17173) 2021-07-23 15:58:57 +02:00
Gustavo Saiani
4d62207377 Improve Collection Sidebar UI for mobile (#17163) 2021-07-23 09:52:12 -03:00
Gustavo Saiani
3d3c63d1c9 Improve Collection Sidebar component (#17114) 2021-07-23 09:15:14 -03:00
Nemanja Glumac
a8d1e94627 Upgrade xlsx library (#17181) 2021-07-23 13:52:41 +02:00
Jeff Evans
940154d9a5 Remove regionid from Snowflake config (#16740)
Remove regionid from plugin YAML file

Add new driver multimethod to `normalize db-details`, and implementing to handle this particular "migration" within Snowflake

Adding hook from database model post-select to invoke the new multi

Adding test
2021-07-22 18:30:10 -05:00
Jeff Evans
eb59ab27a7 Fix serialization: Visualization column settings lost (#17127)
Update visualization_settings.cljc to handle the table.columns submap

Update dump and load to handle :visualization_settings on a Card (basically identically to how they are handled for a DashboardCard)

Updating test to have a card include :visualization_settings and ensure they fields are properly handled

Updating visualization_settings test case to incorporate table.columns as well as :show_mini_bar (under ::column_settings)
2021-07-22 18:04:05 -05:00
Alexander Lesnenko
fc47146132 change iframe-resizer height calculation method to max (#17158) 2021-07-22 23:43:25 +03:00
Kyle Doherty
0fdd82a2f1 add basic static-viz internal route and examples (#17172) 2021-07-22 14:57:30 -04:00
Maz Ameli
cadd71015b fix Radio component with new syntax (#17103) 2021-07-22 11:58:53 -03:00
Ariya Hidayat
7ec6f154a3 Bundle static viz charting code (#17157)
* yarn add @visx/axis@1.8.0 @visx/grid@1.16.0 @visx/group@1.7.0 @visx/scale@1.7.0 @visx/shape@1.8.0

* Import static viz charting code

* Format code with yarn prettier

* Silence linting violations

* Build static-viz bundle
2021-07-22 10:39:39 -04:00
Alexander Polyankin
f0ab4de743 Fix waterfall visualization with ordinal and numeric X-axis (#17150) 2021-07-22 15:19:06 +03:00
Nemanja Glumac
a2dd1cf45e Add and enable cypress-grep library (#16930)
* Add `cypress-grep` library

https://github.com/cypress-io/cypress-grep

* Register `cypress-grep` plugin
2021-07-22 13:23:21 +02:00
Nemanja Glumac
3462edcd66 Remove image diff (#17159)
* Remove `image-diff` library

* Remove `compare-screenshots` script
2021-07-22 00:41:32 +02:00
Gustavo Saiani
1127578af2 Extract component from ParameterFieldWidget (#17091) 2021-07-21 12:28:36 -03:00
Noah Moss
65cfb4ef10 site-url test improvements (#17142) 2021-07-21 08:22:00 -07:00
Anton Kulyk
8d644391ee Fix dashboard card hovering buttons drag behavior (#17130) 2021-07-21 16:14:20 +03:00
Anton Kulyk
100406fd25 Add Metabase Cloud link to admin settings for hosted instances (#17134)
* Add `storeUrl` method to MetabaseSettings

* Use `storeUrl` method

* Add Cloud settings tab

* Add E2E tests for cloud settings page
2021-07-21 15:43:44 +03:00
Nemanja Glumac
ca7be424e5 #17139 Repro: Clicking on cancel edit dashboard without any changes removes the dashboard filter (#17140) 2021-07-21 11:15:28 +02:00
Alexander Polyankin
7ad2d6fddf Do not change route in case collection archiving is cancelled (#17135) 2021-07-21 11:01:05 +03:00
Noah Moss
0691bfbfb7 Don't guess site url from requests to healthcheck endpoint (#17136) 2021-07-20 16:02:54 -07:00
Alexander Lesnenko
b5d4817247 fix stacked buttons on embedded dashboards (#17126) 2021-07-20 20:14:27 +03:00
Anton Kulyk
28aab0f61e Fix can't select card text while editing dashboard (#17124) 2021-07-20 19:32:51 +03:00
Alexander Polyankin
5a848b4421 Do not reload settings on error when explicit Save is used (#17123) 2021-07-20 18:50:52 +03:00
Alexander Polyankin
8b83319dc8 Fix padding for Add a map button (#17120) 2021-07-20 18:34:06 +03:00
Alexander Lesnenko
648996f69a Fix partial commits (#17121) 2021-07-20 16:20:45 +03:00
Ariya Hidayat
2ee56db865 Don't use extend with styled-components anymore (#17048)
It's deprecated and thus removed in v4:
https://styled-components.com/docs/api#deprecated-extend
2021-07-19 15:50:13 -07:00
Nemanja Glumac
5512dd1295 Upgrade Webpack to the v5 (#16113)
* Update Webpack to the latest version (5.37.0)

* Update `webpack-dev-server` to the latest version (3.11.2)

* Install `webpack-cli`

* Replace `CommonsChunkPlugin` with `splitCunks`

* Remove `NamedModulesPlugin`

* Remove `UnusedFilesWebpackPlugin`

* Replace `extract-text-webpack-plugin` with `mini-css-extract-plugin`

* Upgrade `html-webpack-plugin` to the latest version (5.3.1)

* Upgrade `html-webpack-harddisk-plugin` to the latest version (2.0.0)

* Remove `banner-webpack-plugin`

* Replace deprecated `[hash]` in the config

* Add `mode` to the config

* Upgrade `file-loader` to the latest version (6.2.0)

* Don't include polyfills for `path` and `crypto`

* Remove `uglifyjs-webpack-plugin` and use terser instead

* Workaround CLJS_GLOBAL needs top-level `process` object

* yarn add node-polyfill-webpack-plugin

* Use some polyfills

Apparently, the polyfill for crypto is still necessary since the front-end
code isn't migrated yet to the browser's native Crypto API
(https://www.w3.org/TR/WebCryptoAPI/)

See also https://www.npmjs.com/package/node-polyfill-webpack-plugin

* Admin smoke test: fix getting the empty DB path

* Onboarding setup test: fix getting the empty DB path

* Replace file-loader with type: "asset/resource"

See https://webpack.js.org/guides/asset-modules/

* upgrade react-markdown (#16934)

* Use large CI resource since webpack consumes a lot of memory [ci nocache]

https://circleci.com/docs/2.0/configuration-reference/#resourceclass

* Tidy up `NODE_ENV` references

* Remove Webpack `DefinePlugin`

Co-authored-by: Ariya Hidayat <ariya@metabase.com>
Co-authored-by: Dalton Johnson <daltojohnso@users.noreply.github.com>
Co-authored-by: Alexander Lesnenko <alxnddr@users.noreply.github.com>
2021-07-20 00:47:22 +02:00
Nemanja Glumac
856d25c109 Run Cypress jobs in CircleCI as a matrix (#17104) 2021-07-20 00:28:29 +02:00
Nemanja Glumac
b48e0bd3d7 #17043 Repro: With Whitelabel custom name, Metabase name is still shown multiple places in Admin Panel (#17112) 2021-07-19 23:27:06 +02:00
Alexander Polyankin
3927d0c706 Remove Number from semantic types (#17109) 2021-07-19 23:25:09 +03:00
Gustavo Saiani
02d0adcbf5 Improve Collections Header component (#17098) 2021-07-19 16:14:30 -03:00
Nemanja Glumac
fb0eab4d3f [Cypress runner] Run Cypress (#17099)
Related issue: https://github.com/metabase/metabase/issues/17005

* Add `arg` library

* Rewrite the main Cypress runner logic

* Destructure Cypress snapshot results

* Rename Cypress snapshots runner

* Update CircleCI config to reflect `folder` changes

* Update readme for smoke tests

* Run `metabase-db` tests conditionally based on env `QA_DB_ENABLED`
2021-07-19 20:49:52 +02:00
Anton Kulyk
e01d0c7d5b Replace ButtonGroup component with SegmentedControl (#16958)
* Add icons-only mode to SegmentedControl

* Add `fullWidth` mode to SegmentedControl

* Use SegmentedControl at SchedulePicker

* Use SegmentedControl at EmailAttachmentPicker

* Use SegmentedControl at ChartNestedSettingSeries

* Replace ChartSettingButtonGroup with SegmentedControl

* Remove ButtonGroup component

* Don't show labels for some viz settings

* Increase SegmentedControl's click area

* Add `inactiveColor` prop to SegmentedControl

* Fix icons-only SegmentedControl padding
2021-07-19 21:29:26 +03:00
Anton Kulyk
6aaf5c4ff1 Use saturated-yellow instead of warning (#17085) 2021-07-19 21:29:08 +03:00
Anton Kulyk
6a6cdfd737 Fix SearchResult.info page broken (#17086) 2021-07-19 21:28:51 +03:00
Anton Kulyk
ae38449276 Fix missing icons (#17088) 2021-07-19 21:27:52 +03:00
Ariya Hidayat
2448065e92 Separate the (whitelabel) color theme tests (#17106)
This is for easier troubleshooting (rerun from failed, separated
recording) since those tests are quite hard to run smoothly with Circle
CI.

Also, move away from using the API (/api/setting/application-colors)
and just use the color picker from the UI to choose invididual custom color.
2021-07-19 11:24:00 -07:00
Noah Moss
3fd87094ba Link to MB docs from Google Sign-In admin page instead of Google docs (#17075) 2021-07-19 10:22:07 -07:00
dpsutton
64062e8752 offset is a reserved word in mariadb as of 10.6 (#17101)
* offset is a reserved word in mariadb as of 10.6

- https://mariadb.com/kb/en/reserved-words/
- https://github.com/MariaDB/server/commit/299b935320

I think it is related to https://jira.mariadb.org/browse/MDEV-23908
"Implement SELECT ... OFFSET ... FETCH ..."

* Handle new names for utf8 in mariadb

https://mariadb.com/kb/en/unicode/

- utf8: Until MariaDB 10.5, this was a UTF-8 encoding using one to
three bytes per character. Basic Latin letters, numbers and
punctuation use one byte. European and Middle East letters mostly fit
into 2 bytes. Korean, Chinese, and Japanese ideographs use 3-bytes. No
supplementary characters are stored. From MariaDB 10.6, utf8 is an
alias for utf8mb3, but this can changed to ut8mb4 by changing the
default value of the old_mode system variable.

- utf8mb3: UTF-8 encoding using one to three bytes per
character. Basic Latin letters, numbers and punctuation use one
byte. European and Middle East letters mostly fit into 2
bytes. Korean, Chinese, and Japanese ideographs use 3-bytes. No
supplementary characters are stored. Until MariaDB 10.5, this was an
alias for utf8. From MariaDB 10.6, utf8 is by default an alias for
utf8mb3, but this can changed to ut8mb4 by changing the default value
of the old_mode system variable.
2021-07-19 08:52:43 -05:00
Gustavo Saiani
4452329a60 Add propTypes, remove Flow types from ParameterFieldWidget component (#17081) 2021-07-16 13:37:32 -03:00
Anton Kulyk
233f8fdbca Allow displaying info tooltips on FormFields (#17073) 2021-07-16 08:42:33 +03:00
Anton Kulyk
1153473c2c Refactor entity getIcon to return icon props (#17074) 2021-07-16 08:42:24 +03:00
Jeff Evans
4ed4c57d56 Set program name on Oracle connections (#16968)
Update Oracle driver to set the v$session.program property on the connection, which appears in the PROGRAM column of the v$session table

Update tests accordingly
2021-07-15 22:03:27 -05:00
Cam Saul
3311b62119 Fix Card async-metadata running query even when metadata can be deter… (#17053)
* Fix Card async-metadata running query even when metadata can be determined programatically

* Update another test

* Adjust affected repros by waiting for the metadata to load (#17068)

* Wait for the `result_metadata` to load

* Reduce the number of bins for the faster execution

* Update repro for #12568

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
2021-07-15 15:35:55 -07:00
Nemanja Glumac
5de2d22efa [Dashboard filters] Create initial infrastructure and group repros (#17079)
* Extract repro for #15279 into a separate file

* Extract repro for #15689 into a separate file

* Extract repro for #15695 into a separate file

* Extract repro for #15119 into a separate file

* Extract repro for #12614 into a separate file

* Extract repro for #12720 into a separate file

* Extract repro for #6660 into a separate file

* Extract repro for #16103 into a separate file

* Extract repro for #13150 into a separate file

* Move existing tests related to the dashboard filters into a new folder

* Create new CI group `dashboard-filters`
2021-07-15 21:53:42 +02:00
Gustavo Saiani
4da53d5e80 Fix popover footer when is not equalOps (#17076) 2021-07-15 16:19:46 -03:00
Nemanja Glumac
a42fec8e50 Rename CI group filters -> native-filters (#17066)
This group already takes close to 10 minutes to finish.

We need to have an additional extended coverage for dashboard filters and for query builder filters.
It doesn't make sense to keep them all together under the `filters` CI group because that group on its own could take more than half an hour to finish.
2021-07-15 15:04:40 +02:00
Nemanja Glumac
132899db5e Add createNativeQuestionAndDashboard Cypress custom command (#16970)
* Add `createNativeQuestionAndDashboard` Cypress custom command

* Apply custom command to the existing test as an example

* Add sane defaults for the dashboard card size

* Apply custom command to 16181 reproduction
2021-07-15 00:28:49 +02:00
Nemanja Glumac
c43a7828cc Remove db paging (#16990) (#17054)
I thought (and assured dpsutton, lol) that the default behavior of the pagination spliced in was just not paginating, if there wasn't a limit passed in. Unfortunately, it appears that I tested this on the endpoint without pagination spliced in... so the default behavior isn't that way, it paginates if you don't pass in stuff.

So rip it out of the DB endpoint (only) for now and put it back in when we paginate

Authored-by: Howon Lee <hlee.howon@gmail.com>
2021-07-14 23:55:22 +02:00
Nemanja Glumac
673981a06f 🍒 Cherry pick changes from July 9, 2021 from release -> master (#17051)
* Add `addFilterToDashboard` Cypress custom command (#16964)

* Apply custom command to a few tests as an example

* #16918 Repro: Pulse fails when question has date field with "Month of Year" (#16921)
2021-07-14 23:50:52 +02:00
Nemanja Glumac
25373f96a8 docs - fix pulse link [closes #16953] (#16959) (#17055)
Co-authored-by: Jeff Bruemmer <jeff@metabase.com>
2021-07-14 23:36:44 +02:00
Jeff Evans
ee3bdc70de Remove Multi-Release from manifest (#17027)
Undoes #16005, because performance was significantly impacted; see issue #16380
2021-07-14 15:25:47 -05:00
Nemanja Glumac
d4932745a4 Scroll to selected collection and question in the saved question picker (#16957) (#17052)
* Scroll to selected collection and question in the saved question picker

* fixup! Scroll to selected collection and question in the saved question picker

Co-authored-by: Alexander Lesnenko <alxnddr@users.noreply.github.com>
2021-07-14 22:21:49 +02:00
Alexander Lesnenko
99da074b1a minimal hack fix search results being below the data picker (#16998) 2021-07-14 12:06:39 -07:00
Nemanja Glumac
2ebaf71a1a [Cypress runner] Use Cypress Module API to generate Cypress snapshots (#17010) 2021-07-14 20:58:23 +02:00
Nemanja Glumac
005c221e18 [Cypress runner] Get version (#17015) (#17047)
* Extract `readFile` into runner utils

* Extract `getVersion` function into a separate file
2021-07-14 20:21:48 +02:00
Nemanja Glumac
a209702b57 [Cypress runner] Extract print helper functions (#17008) (#17017)
* Extract print helper functions for the Cypress runner

* Re-order Cypress messages to the more appropriate position
2021-07-14 20:01:36 +02:00
Nemanja Glumac
0fea0879f6 [Cypress runner] Set HAS_ENTERPRISE_TOKEN using Configuration API (#17006) (#17016)
* Set `HAS_ENTERPRISE_TOKEN` using Cypress Configuration and Plugins API

* Re-organize webpack preprocessor options
2021-07-14 20:01:14 +02:00
dpsutton
90435d6dfe Smartscalars (#17020)
* Smartscalars

* smartscalar html styling

* Docstring, ns, prevent top-level trs/tru
2021-07-14 11:54:21 -05:00
Anton Kulyk
b2098b6072 Fix error when opening a public question with filters having default parameters (#17034) 2021-07-14 15:55:34 +03:00
Gustavo Saiani
94369c541c Humanize coercion strategy strings (#17029) 2021-07-14 09:01:18 -03:00
Anton Kulyk
8ac3883ceb [P0] Fix filters don't work for public and embedded questions (#17032)
* Enable repro for #17019

* Fix filters don't work for public questions
2021-07-14 14:53:58 +03:00
Anton Kulyk
d38a2ff471 Fix long titles in collections push out the last-edited-by and last-edited-at columns (#16992)
* Handle long collection item titles

* Fix EntityItemMenu's margin-left

* Remove `span` attribute from cols

* Fix "name" column is too close to "type"

* Fix "last edit" columns width

* Hide "last-edit" column at medium breakpoint
2021-07-14 08:53:49 +03:00
Anton Kulyk
f0ac47d34c Fix native question looses visualisation settings if query fails (#17009)
* Add test IDs for visualization buttons

* Add `runNativeQuery` helper to e2e-misc-helpers

* Add repro for #16914

* Don't sync native query columns if it failed

* Fix `table.columns: []` treated as "all hidden"
2021-07-14 08:53:34 +03:00
Ariya Hidayat
980518f2f4 Form: guard against undefined submit function (#17023) 2021-07-13 20:26:26 -07:00
Ariya Hidayat
5a8c8f4d46 When running some TokenField unit tests, shim Element.closest (#17021) 2021-07-13 20:26:13 -07:00
Nemanja Glumac
de5f85971a #17019 Repro: Question filters don't for for embed/public scenarios (#17024) 2021-07-13 21:28:33 +02:00
Ariya Hidayat
7403c196f9 Entities search: guard against undefined data (#16996) 2021-07-13 10:34:03 -07:00
Ariya Hidayat
bd606e7f03 Data selector: avoid toggling popover when it's not ready (#16987) 2021-07-13 10:25:08 -07:00
Anton Kulyk
6db73b0cfa Unskip #16617 (#17004) 2021-07-13 13:11:51 +03:00
Gustavo Saiani
e14d88c448 Improve SettingsUpdatesForm component (#16988) 2021-07-12 21:23:28 -03:00
Ariya Hidayat
4fdf2b85bf When running some Jest unit tests, use a MutationObserver shim (#16985) 2021-07-12 17:07:31 -07:00
Bruno Bergher
3d6dd7762e Remove email quotations which could be deemed controversial. (#16944)
* Remove email quotations which could be deemed controversial. Address part of #11155

* Trigger deploy

Co-authored-by: Bruno Bergher <me@brunobergher.comexport>
2021-07-12 16:32:18 -07:00
Ariya Hidayat
aeedcc078e When running <Logs> unit tests, mock XMLHttpRequest (#16974)
Since Jest runs with JSDom and JSDom doesn't really implement XHR,
provide a mock implementation to avoid a thrown exception.
2021-07-12 16:24:35 -07:00
Jeff Bruemmer
cb63c67a8b Don't offer to save on visualize unless dirty (#16994) 2021-07-12 16:10:43 -04:00
dpsutton
0d43803629 Easy checking for missing library licenses (#16989)
* Easy checking for missing library licenses

* include bin/build-mb readme
2021-07-12 15:05:43 -05:00
Alexander Lesnenko
cde652ba88 Update iframeResizer.js (#16952)
Co-authored-by: Mário Valney <mariovalney@gmail.com>
2021-07-12 09:31:02 -07:00
Anton Kulyk
b96a477f0b Fix console errors for Radio and SegmentedControl (#16950) 2021-07-12 19:21:41 +03:00
Ariya Hidayat
8df69c589a VS Code launch config to facilitate debugging (#16975) 2021-07-12 08:25:51 -07:00
Gustavo Saiani
bc2a3ac00c Test CTA renders for Enterprise and Cloud in Settings › Admin › Updates (#16966) 2021-07-12 11:01:52 -03:00
Anton Kulyk
02fddd8a4f Remove console logs (#16982) 2021-07-12 15:45:51 +03:00
Ariya Hidayat
3c71c5186d Run unit tests with Jest with --silent (#16967)
The console messages (mostly about React warning on deprecated methods)
are useful when debugging a running application but they are atrocious,
extremely noisy, and barely useful when running the unit tests.

In the CI, those console messages drown the more useful PASS/FAIL status
of each individual test.
2021-07-09 21:19:25 -07:00
Nemanja Glumac
1d107a0664 [SQL filters coverage] Add initial set of e2e tests around SQL field filter type of ID (#16926)
* Add test for SQL field filter of the type ID

* Fix spelling

Co-authored-by: Gustavo Saiani <gustavo@poe.ma>
2021-07-10 00:51:46 +02:00
Nemanja Glumac
f6f4f0c794 [SQL filters coverage] Add initial set of e2e tests around SQL field filter type of "None" (#16928)
* Add test for SQL field filter of the type "None"

* Add repro for #13825

* Fix spelling

Co-authored-by: Gustavo Saiani <gustavo@poe.ma>
2021-07-09 23:29:48 +02:00
Ariya Hidayat
f97e2deeff CI GitHub Actions: Cache JARs for Shadow CLJS (#16965)
Some front-end tasks require Shadow CLJS to compile files into
JavaScript, therefore let's cache the JARs which it needs.
2021-07-09 14:25:35 -07:00
dpsutton
c04e9a63f5 Render/scalar (#16955)
* Scalar rendering as text in slack

* Fix tests for pulse

* Tests for slack scalars
2021-07-09 15:29:48 -05:00
Anton Kulyk
250118d264 Refactor CheckBox and StackedCheckBox components (#16913)
* Disable react/prop-types for .info files

* Refactor Checkbox

* Refactor StackedCheckBox

* Add a comment about Checkbox colors

* Remove not used prop

* Don't show outline for focused unchecked checkbox

* Pass custom Checkbox label element

* Refactor EmailAttachmentPicker to use label

* Refactor FieldsPicker to use label

* Refactor FilterOptions to use label

* Refactor DisplayOptionsPane to use label

* Refactor ScratchApp to use label

* Refactor AddSeriesModal to use label

* Add "danger" color to colors

* Refactor DeleteModalWithConfirm to use label

* Add label usage examples for CheckBox

* Add label usage examples for StackedCheckBox

* Add disabled state to CheckBox

* Add disabled state to StackedCheckBox

* Fix label prop-types

* Add space between examples

* Fix StackedCheckBox layout

* Add. StackedCheckBox label

* Fix disabled state for StackedCheckBox

* Migrate FieldsPicker to use label

* Migrate EmailAttachmentPicker to use label

* Add .styled files for checkbox components

* Fix e2e tests

* Fix `uncheckedColor` passed to HTML elements

* Revert eslint overwrite for .info files

* Display focus outline
2021-07-09 14:34:55 +03:00
Nemanja Glumac
3555b7b2d4 Mark "Every field is hidden right now" string for translation (#16915) 2021-07-09 13:11:16 +02:00
Nemanja Glumac
a0af486924 Remove recompose (#16829)
* Replace `pure` with `React.Memo`

* Fix eslint error

* Use `shallowEqual` directly as a utility function

* Remove `recompose` library
2021-07-09 13:10:14 +02:00
Maz Ameli
961caedc99 update remaining strings for 0.40 (#16945) 2021-07-08 17:07:49 -07:00
Alexander Lesnenko
a44054f612 Fix home page our analytics (#16910)
* Fix home page our analytics section not showing collections

* increase limit for root collection children and pinned dashboards that are loaded on the home page
2021-07-09 00:54:34 +03:00
Alexander Lesnenko
e481e5197d Saved question picker bug bash (#16940)
* fix Saved questions string translation

* fix Everything else folder is not showing items in the saved question picker for other languages

* translate query builder header

* Fix saved questions db on the client side

* i18n on "Saved Questions"

Co-authored-by: dan sutton <dan@dpsutton.com>
2021-07-08 23:47:13 +03:00
Bonifacio de Oliveira
8d21e2dae1 fix typos (#16734) 2021-07-08 11:34:17 -07:00
Tim Macdonald
a7257112ca [Fixes #16855] Avoid error when user searches with no data perms (#16925) 2021-07-08 13:31:10 -05:00
Alexander Lesnenko
97da3c5eae Saved question picker fixes (#16904)
* adjust saved question picker layout

* fix saved question picker does not work with collection names that have a colon

* unskip repro

* make saved question picker usable on the mobile device
2021-07-08 19:36:48 +03:00
Gustavo Saiani
b8e92c8a2e Update logic and labels for settings updates preferences in Cloud and Enterprise (#16920) 2021-07-08 11:36:52 -03:00
Ariya Hidayat
a7d10a74a6 GitHub Actions: correct the way yarn is supposed to pull the deps (#16933)
There's no `--lockfile` option, the valid one is `--frozen-lockfile`.

https://classic.yarnpkg.com/en/docs/cli/install/#toc-yarn-install-frozen-lockfile
2021-07-08 07:36:30 -07:00
Dalton
e96cf05b2c don't show error card in prod & make it fullscreen when running cypress (#16908)
* don't show error card in prod & make it fullscreen when running cypress

* fix height styling
2021-07-07 18:13:02 -07:00
Noah Moss
19936cc365 Hardcode fake salt and pw hash for timing attack prevention (#16932) 2021-07-07 17:18:00 -07:00
Ellie Mary
22c44da5d9 docs - sso tutorial auth0 14185 (#14206) 2021-07-07 12:55:26 -04:00
Alexander Lesnenko
58b35cacc6 add autofocus to some of inputs (#16858)
* add autofocus to some of inputs

* add autofocus to the snippet form
2021-07-07 19:51:19 +03:00
Anton Kulyk
2ac51762e9 Fix "Run selected text" removes everything but the selected text from the query (#16917) 2021-07-07 18:40:28 +03:00
Gustavo Saiani
799fe86ca6 Test collection sidebar responsiveness (#16896) 2021-07-07 09:40:55 -03:00
Howon Lee
29af77046d Backwards compatibility for friendly field names (#16860)
We defriendlified but the migration running in the first place is not happening for some users. Investigating but it's better just to be safe on this front
2021-07-06 19:22:58 -07:00
Gustavo Saiani
297fb1b482 Add instructions on running enterprise FE (#16911) 2021-07-06 20:05:37 -03:00
Nemanja Glumac
fb1ab412f8 #16855 Repro: Search does not work for users without data access (#16903) 2021-07-06 23:11:33 +02:00
Howon Lee
b65f466409 Excise 45 day clause from view line graph in audit (#16906) 2021-07-06 13:22:47 -07:00
Alexander Lesnenko
37c50bb2af Fix data picker initial state (#16894)
* Fix data picker not showing saved question picker initially

* fixup! Fix data picker not showing saved question picker initially
2021-07-06 23:10:55 +03:00
Noah Moss
f66d35c081 Consistent request timing for login and password reset endpoints (#16837) 2021-07-06 12:45:06 -07:00
Jeff Bruemmer
9ab0bf9d6a docs - connecting to dbs with ssl certificates (#16341) 2021-07-06 15:01:41 -04:00
Jeff Bruemmer
8d5594d216 docs - update links (#16905) 2021-07-06 14:41:52 -04:00
Nemanja Glumac
a36f0dc596 #16886 Repro: "Run selected text" removes everything but the selected text from the query (#16902) 2021-07-06 20:06:59 +02:00
Nemanja Glumac
67248552bc [SQL filters coverage] Group reproductions (#16898)
* Extract repro for #12228 into a separate file

* Extract repro for #15444 into a separate file

* Extract repro for #15460 into a separate file

* Extract repro for #15700 into a separate file

* Extract repro for #15981 into a separate file

* Extract repro for #16739 into a separate file

* Extract repro for #13961 into a separate file

* Extract repro for #14145 into a separate file

* Extract repro for #12581 into a separate file

* Extract repro for #14302 into a separate file

* Extract repro for #15163 into a separate file

* Extract repro for #11580 into a separate file

* Extract repro for #11480 into a separate file

* Extract repro for #9357 into a separate file
2021-07-06 19:14:01 +02:00
Gustavo Saiani
15c02bb008 Make mobile Collections Sidebar hidden on page load (#16878) 2021-07-06 12:53:02 -03:00
Anton Kulyk
3fc29afef1 Add SegmentedControl component (#16885)
* Add basic segmented control component

* Specify segmented control's selected option color

* Update SegmentedControl's padding

* Use `PropTypes.node` instead of a bunch of types

* Remove `aria-selected` from CSS
2021-07-06 12:00:17 +03:00
Nemanja Glumac
37f9c8edc6 [SQL filters coverage] Extract and apply SQL field filter data (#16893)
* Extract and apply SQL field filter data objects

* Refactor object key `term` -> `value`
2021-07-06 01:12:57 +02:00
Nemanja Glumac
f41e4eb624 Simplify openEntryForm helper function (#16895)
- Simplifies openEntryForm helper function
- Fixes `frontend/test/metabase/scenarios/filters/sql-field-filter-string.cy.spec.js` and `frontend/test/metabase/scenarios/filters/sql-field-filter-number.cy.spec.js` logic.
2021-07-06 00:58:13 +02:00
Nemanja Glumac
9b1d72e04a [SQL filters coverage] Extract and apply date filter helpers (#16892)
* Extract date filter helpers

* Apply date filter helper filters to the `sql-field-filter-date.cy.spec.js`

* Simplify `openDateFilterPicker` function
2021-07-06 00:50:34 +02:00
Nemanja Glumac
9fbd0d25fb [SQL filters coverage] Extract and apply SQL field filter helpers (#16891)
* Extract SQL field filter helpers

* Apply field filter helper filters to the `sql-field-filter-string.cy.spec.js`

* Apply field filter helper filters to the `sql-field-filter-number.cy.spec.js`

* Apply field filter helper filters to the `sql-field-filter-date.cy.spec.js`
2021-07-05 23:49:54 +02:00
Nemanja Glumac
ed264af503 [SQL filters coverage] Extract and apply basic SQL filter helpers (#16887)
* Extract the basic SQL filter helpers

* Apply basic helper filters to the `sql-filters.cy.spec.js`

* Fix typos

* Simplify banner comments

* Apply basic helper filters to the `sql-field-filter-string.cy.spec.js`

* Apply basic helper filters to the `sql-field-filter-number.cy.spec.js`

* Apply basic helper filters to the `sql-field-filter-date.cy.spec.js`
2021-07-05 23:26:55 +02:00
Nemanja Glumac
5dd4e994f0 [Cypress Helpers] Extract functions into separate files (#16884)
* Extract e2e setup helpers

* Extract e2e ui elements helpers

* Extract e2e dashboard helpers

* Extract e2e open table helpers

* Extract e2e database metadata helpers

* Extract e2e qa databases helpers

* Extract e2e ad-hoc question helpers

* Extract e2e enterprise helpers

* Extract e2e mock app settings helpers

* Extract e2e assertion helpers

* Extract e2e data model helpers

* Extract e2e misc helpers

* Extract e2e deprecated helpers

* Remove `getIframeBody` from global helper functions

* Remove `generateUsers` from global helper functions

* Remove `enableSharingQuestion` from global helper functions

* Remove unused functions
2021-07-05 17:26:09 +02:00
Nemanja Glumac
13ea1e0233 [SQL filters coverage] Add initial set of e2e tests around SQL field filter type of Date (#16854)
* Add initial set of e2e tests around sql field filter type of Date

* Expand SQL date filter tests to include required filter flow
2021-07-05 14:06:16 +02:00
Alexander Lesnenko
26f6cfeeb8 Group personal collections in the saved question picker (#16875)
* hide other personal collections folder when no other users

* expand collections on click but disallow to select all personal collections, show all empty collections
2021-07-05 12:22:50 +03:00
Nemanja Glumac
7b1a39d24f [Cypress Helpers] Add filterWidget helper function (#16882)
* Add Cypress helper function `filterWidget`

* Apply `filterWidget` helper to the related specs

* Annotate the function using JSDoc
2021-07-05 10:21:51 +02:00
Ariya Hidayat
32494b193c Ensure the unique key for this Link instance (#16864) 2021-07-02 12:08:40 -07:00
Ariya Hidayat
7fec494244 When used in data picker, Popover's children is actually an array (#16866) 2021-07-02 12:08:21 -07:00
Anton Kulyk
178720b7e7 Extract getInitialCollectionId selector helpers, add unit tests (#16867) 2021-07-02 16:57:00 +03:00
Anton Kulyk
2a34dc5662 Clean up Radio component (#16874) 2021-07-02 16:56:06 +03:00
Nemanja Glumac
3c96f15c92 Move stray folders into existing CI e2e groups (#16868)
* Move `browse` spec to the "Onboarding" directory

* Reorganize `search` specs

- Rename stray "seach" to "search-pagination" and move it to the new "search" directory under "onboarding"
- Rename existing "search" to "search-typeahead" and move it to the new "search" directory under "onboarding"
- Move old "seach" spec to the new "search" directory under "onboarding"
2021-07-02 11:29:26 +02:00
Anton Kulyk
4ea4b2d961 Fix random collection is suggested when saving a new dashboard (#16853)
* Add repro for #16832

* Add `isCollectionPath` URL utility

* Fix getInitialCollectionId uses non-collection IDs

* Handle `location` not starting with a slash
2021-07-02 11:15:43 +03:00
1970 changed files with 146199 additions and 67390 deletions

View File

@@ -1,28 +1,31 @@
{
"plugins": [
"babel-plugin-styled-components",
"transform-flow-strip-types",
"add-react-displayname",
"transform-decorators-legacy",
["transform-builtin-extend", {
"globals": ["Error", "Array"]
}],
"syntax-trailing-function-commas"
"@babel/plugin-transform-flow-strip-types",
"@babel/plugin-proposal-export-default-from",
["@babel/plugin-proposal-decorators", { "legacy": true }]
],
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
],
"presets": ["es2015", "stage-0", "react"],
"env": {
"development": {
"presets": []
},
"extract": {
"plugins": [
["ttag", {
"extract": {
"output": "locales/metabase-frontend.pot"
},
"discover": ["t", "jt"],
"numberedExpressions": true
}]
[
"ttag",
{
"extract": {
"output": "locales/metabase-frontend.pot"
},
"discover": ["t", "jt"],
"numberedExpressions": true
}
]
]
}
}

View File

@@ -5,24 +5,21 @@ version: 2.1
########################################################################################################################
executors:
# Our brand new builder
clojure-and-node:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
# CircleCI base (Lein 2.9.5) + Node + Headless browsers + Clojure CLI - big one
# CircleCI base Node + Headless browsers + Clojure CLI - big one
# Maildev runs by default with all Cypress tests
clojure-and-node-and-browsers:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:lein-2.9.5-node-browsers
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: maildev/maildev
- image: metabase/qa-databases:postgres-sample-12
- image: metabase/qa-databases:mongo-sample-4.0
- image: metabase/qa-databases:mysql-sample-8
java-8:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:openjdk-8-lein-2.9.5-buster
- image: metabase/ci:circleci-java-8-clj-1.10.3.929-07-27-2021-node-browsers
# Java 11 tests also test Metabase with the at-rest encryption enabled. See
# https://metabase.com/docs/latest/operations-guide/encrypting-database-details-at-rest.html for an explanation of
@@ -30,19 +27,19 @@ executors:
java-11:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_ENCRYPTION_SECRET_KEY: Orw0AAyzkO/kPTLJRxiyKoBHXa/d6ZcO+p+gpZO/wSQ=
java-16:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:openjdk-16-lein-2.9.5-buster
- image: metabase/ci:circleci-java-16-clj-1.10.3.929-07-27-2021-node-browsers
postgres-9-6:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
@@ -58,7 +55,7 @@ executors:
postgres-latest:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
@@ -75,7 +72,7 @@ executors:
mysql-5-7:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
@@ -88,7 +85,7 @@ executors:
mysql-latest:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
@@ -101,7 +98,7 @@ executors:
mariadb-10-2:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
@@ -114,7 +111,7 @@ executors:
mariadb-latest:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
@@ -128,16 +125,22 @@ executors:
# MYSQL_USER: root
# MYSQL_ALLOW_EMPTY_PASSWORD: yes
mongo:
mongo-4-0:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: circleci/mongo:4.0
presto:
mongo-latest:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: circleci/mongo:latest
presto-186:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: metabase/presto-mb-ci:0.186
environment:
JAVA_TOOL_OPTIONS: "-Xmx2g"
@@ -145,22 +148,41 @@ executors:
# OOM sometimes with the default medium size.
resource_class: large
presto-jdbc-env:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: metabase/presto-mb-ci:latest # version 0.254
environment:
JAVA_TOOL_OPTIONS: "-Xmx2g"
MB_PRESTO_JDBC_TEST_CATALOG: test_data
MB_PRESTO_JDBC_TEST_HOST: localhost
MB_PRESTO_JDBC_TEST_PORT: 8443
MB_PRESTO_JDBC_TEST_SSL: true
MB_PRESTO_JDBC_TEST_USER: metabase
MB_PRESTO_JDBC_TEST_PASSWORD: metabase
MB_ENABLE_PRESTO_JDBC_DRIVER: true
MB_PRESTO_JDBC_TEST_ADDITIONAL_OPTIONS: >
SSLTrustStorePath=/tmp/cacerts-with-presto-ssl.jks&SSLTrustStorePassword=changeit
# (see above)
resource_class: large
sparksql:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: metabase/spark:2.1.1
vertica:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: sumitchawla/vertica
sqlserver:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
environment:
MB_SQLSERVER_TEST_HOST: localhost
MB_SQLSERVER_TEST_PASSWORD: 'P@ssw0rd'
@@ -174,7 +196,7 @@ executors:
druid:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: metabase/ci:lein-2.9.5-clojure-1.10.3.814
- image: metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers
- image: metabase/druid:0.20.2
environment:
CLUSTER_SIZE: nano-quickstart
@@ -182,26 +204,6 @@ executors:
# OOM all the time with the default medium size.
resource_class: large
fe-mongo-4:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:lein-2.9.5-node-browsers
- image: metabase/qa-databases:mongo-sample-4.0
fe-postgres-12:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:lein-2.9.5-node-browsers
- image: metabase/qa-databases:postgres-sample-12
fe-mysql-8:
working_directory: /home/circleci/metabase/metabase/
docker:
- image: circleci/clojure:lein-2.9.5-node-browsers
- image: metabase/qa-databases:mysql-sample-8
########################################################################################################################
# MAP FRAGMENTS AND CACHE KEYS #
########################################################################################################################
@@ -209,7 +211,8 @@ executors:
# `default_parameters` isn't a key that CircleCI uses, but this form lets us reuse parameter definitions
default_parameters: &Params
edition:
type: string
type: enum
enum: ["oss", "ee"]
default: "oss"
# .BACKEND-CHECKSUMS, .FRONTEND-CHECKSUMS, and .MODULE-CHECKSUMS are created during the checkout step; see that step
@@ -226,23 +229,25 @@ default_parameters: &Params
# uncontrollably since old deps would continue to accumulate. Restoring big caches is really slow in Circle. It's
# actually faster to recreate the deps cache from scratch whenever we need to which keeps the size down.
cache-key-backend-deps: &CacheKeyBackendDeps
key: v1-{{ checksum ".CACHE-PREFIX" }}-be-deps-{{ checksum "project.clj" }}-{{ checksum ".SCRIPTS-DEPS-CHECKSUMS" }}
# TODO -- this should actually include the Java source files and the Spark SQL AOT source files as well since we now
# compile those as part of this step. FIXME
key: v5-{{ checksum ".CACHE-PREFIX" }}-be-deps-{{ checksum "deps.edn" }}-{{ checksum ".SCRIPTS-DEPS-CHECKSUMS" }}
cache-key-frontend-deps: &CacheKeyFrontendDeps
key: v1-{{ checksum ".CACHE-PREFIX" }}-fe-deps-{{ checksum "yarn.lock" }}
key: v5-{{ checksum ".CACHE-PREFIX" }}-fe-deps-{{ checksum "yarn.lock" }}
# Key used for implementation of run-on-change -- this is the cache key that contains the .SUCCESS dummy file
# By default the key ALWAYS includes the name of the test job itself ($CIRCLE_STAGE) so you don't need to add that yourself.
cache-key-run-on-change: &CacheKeyRunOnChange
key: v1-{{ checksum ".CACHE-PREFIX" }}-run-on-change-{{ .Environment.CIRCLE_STAGE }}-<< parameters.checksum >>
key: v5-{{ checksum ".CACHE-PREFIX" }}-run-on-change-{{ .Environment.CIRCLE_STAGE }}-<< parameters.checksum >>
# Key for the local maven installation of metabase-core (used by build-uberjar-drivers)
cache-key-metabase-core: &CacheKeyMetabaseCore
key: v1-{{ checksum ".CACHE-PREFIX" }}-metabase-core-{{ checksum ".BACKEND-CHECKSUMS" }}
key: v5-{{ checksum ".CACHE-PREFIX" }}-metabase-core-{{ checksum ".BACKEND-CHECKSUMS" }}
# Key for the drivers built by build-uberjar-drivers
cache-key-drivers: &CacheKeyDrivers
key: v1-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}-{{ checksum ".BACKEND-CHECKSUMS" }}-<< parameters.edition >>
key: v5-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}-{{ checksum ".BACKEND-CHECKSUMS" }}-<< parameters.edition >>
# This is also used by the uberjar-build-drivers step; this is a unique situation because the build-drivers script has
# logic to determine whether to rebuild drivers or not that is quite a bit more sophisticated that the run-on-change
@@ -250,17 +255,17 @@ cache-key-drivers: &CacheKeyDrivers
# redshift driver.
cache-keys-drivers-with-fallback-keys: &CacheKeyDrivers_WithFallbackKeys
keys:
- v1-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}-{{ checksum ".BACKEND-CHECKSUMS" }}
- v1-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}
- v1-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-
- v5-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}-{{ checksum ".BACKEND-CHECKSUMS" }}
- v5-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-{{ checksum ".MODULES-CHECKSUMS" }}
- v5-{{ checksum ".CACHE-PREFIX" }}-drivers-<< parameters.edition >>-
# Key for frontend client built by uberjar-build-frontend step
cache-key-frontend: &CacheKeyFrontend
key: v1-{{ checksum ".CACHE-PREFIX" }}-frontend-<< parameters.edition >>-{{ checksum ".FRONTEND-CHECKSUMS" }}
key: v5-{{ checksum ".CACHE-PREFIX" }}-frontend-<< parameters.edition >>-{{ checksum ".FRONTEND-CHECKSUMS" }}
# Key for uberjar built by build-uberjar
cache-key-uberjar: &CacheKeyUberjar
key: v1-{{ checksum ".CACHE-PREFIX" }}-uberjar-<< parameters.edition >>-{{ checksum ".BACKEND-CHECKSUMS" }}-{{ checksum ".FRONTEND-CHECKSUMS" }}
key: v5-{{ checksum ".CACHE-PREFIX" }}-uberjar-<< parameters.edition >>-{{ checksum ".BACKEND-CHECKSUMS" }}-{{ checksum ".FRONTEND-CHECKSUMS" }}
########################################################################################################################
@@ -396,12 +401,12 @@ commands:
fi
echo "Created checksums for $(cat << parameters.filename >> | wc -l) files"
run-lein-command:
run-clojure-command:
parameters:
before-steps:
type: steps
default: []
lein-command:
clojure-args:
type: string
after-steps:
type: steps
@@ -411,9 +416,9 @@ commands:
- restore-be-deps-cache
- steps: << parameters.before-steps >>
- run:
name: lein << parameters.lein-command >>
name: clojure << parameters.clojure-args >>:<< parameters.edition >>:<< parameters.edition >>-dev
command: |
lein with-profile +ci,+<< parameters.edition >> << parameters.lein-command >>
clojure << parameters.clojure-args >>:<< parameters.edition >>:<< parameters.edition >>-dev
no_output_timeout: 15m
- steps: << parameters.after-steps >>
- store_test_results:
@@ -487,6 +492,15 @@ commands:
wget --output-document=plugins/<< parameters.dest >> ${<< parameters.source >>}
no_output_timeout: 15m
run-command:
parameters:
command:
type: string
steps:
- run:
name: Run command
command: << parameters.command >>
jobs:
########################################################################################################################
@@ -494,7 +508,7 @@ jobs:
########################################################################################################################
checkout:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- checkout
# .BACKEND-CHECKSUMS is every Clojure source file as well as dependency files like deps.edn and plugin manifests
@@ -536,6 +550,9 @@ jobs:
else
echo '' > .CACHE-PREFIX
fi
- run-yarn-command:
command-name: Create static visualization js bundle
command: build-static-viz
- persist_to_workspace:
root: /home/circleci/
paths:
@@ -543,7 +560,7 @@ jobs:
check-migrations:
executor:
clojure-and-node
clojure-and-node-and-browsers
steps:
- attach-workspace
- create-checksum-file:
@@ -566,35 +583,51 @@ jobs:
########################################################################################################################
be-deps:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
parameters:
<<: *Params
steps:
- attach-workspace
# This step is pretty slow, even with the cache, so only run it if project.clj has changed
# TODO -- we should cache the build script deps as well, and driver deps?
# This step is pretty slow, even with the cache, so only run it if deps.edn has changed
- run-on-change:
checksum: '{{ checksum "project.clj" }}-{{ checksum ".SCRIPTS-DEPS-CHECKSUMS" }}'
checksum: 'v5-{{ checksum "deps.edn" }}-{{ checksum ".SCRIPTS-DEPS-CHECKSUMS" }}'
steps:
- restore-be-deps-cache
- run: lein with-profile +include-all-drivers,+cloverage,+junit,+dev,+<< parameters.edition >> deps
- run: |
cd /home/circleci/metabase/metabase/bin/build-mb && clojure -P
- run:
name: Compile Java source file(s)
command: clojure -X:deps prep
- run:
name: Compile driver AOT namespaces
command: cd modules/drivers && clojure -X:deps prep
- run:
name: Fetch dependencies
command: clojure -P -X:dev:ci:ee:ee-dev:drivers:drivers-dev
- run:
name: Fetch dependencies (./bin/build/build-mb)
command: cd /home/circleci/metabase/metabase/bin/build-mb && clojure -P -M:test
# Not sure why this is needed since you would think build-mb would fetch this stuff as well. It doesn't
# seem to fetch everything tho. :shrug:
- run:
name: Fetch dependencies (./bin/build/build-drivers)
command: cd /home/circleci/metabase/metabase/bin/build-drivers && clojure -P -M:test
- save_cache:
name: Cache backend dependencies
<<: *CacheKeyBackendDeps
paths:
- /home/circleci/.m2
- /home/circleci/.gitlibs
- /home/circleci/metabase/metabase/java/target/classes
- /home/circleci/metabase/metabase/modules/drivers/sparksql/target/classes
lein:
clojure:
parameters:
e:
type: executor
default: clojure-and-node
default: clojure-and-node-and-browsers
before-steps:
type: steps
default: []
lein-command:
clojure-args:
type: string
after-steps:
type: steps
@@ -612,22 +645,22 @@ jobs:
- run-on-change:
checksum: '{{ checksum ".BACKEND-CHECKSUMS" }}'
steps:
- run-lein-command:
- run-clojure-command:
before-steps: << parameters.before-steps >>
lein-command: << parameters.lein-command >>
clojure-args: << parameters.clojure-args >>
after-steps: << parameters.after-steps >>
edition: << parameters.edition >>
- unless:
condition: << parameters.skip-when-no-change >>
steps:
- run-lein-command:
- run-clojure-command:
before-steps: << parameters.before-steps >>
lein-command: << parameters.lein-command >>
clojure-args: << parameters.clojure-args >>
after-steps: << parameters.after-steps >>
edition: << parameters.edition >>
be-linter-reflection-warnings:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- attach-workspace
- run-on-change:
@@ -643,7 +676,7 @@ jobs:
parameters:
e:
type: executor
default: clojure-and-node
default: clojure-and-node-and-browsers
driver:
type: string
timeout:
@@ -652,6 +685,9 @@ jobs:
before-steps:
type: steps
default: []
after-steps:
type: steps
default: []
description:
type: string
default: ""
@@ -671,13 +707,14 @@ jobs:
name: Test << parameters.driver >> driver << parameters.description >>
environment:
DRIVERS: << parameters.driver >>
command: << parameters.extra-env >> lein with-profile +ci,+junit,+ee test
command: << parameters.extra-env >> clojure -X:dev:ci:ee:ee-dev:drivers:drivers-dev:test
no_output_timeout: << parameters.timeout >>
- store_test_results:
path: /home/circleci/metabase/metabase/target/junit
- steps: << parameters.after-steps >>
test-build-scripts:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- attach-workspace
- run-on-change:
@@ -721,7 +758,7 @@ jobs:
########################################################################################################################
fe-deps:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- attach-workspace
# This step is *really* slow, so we can skip it if yarn.lock hasn't changed since last time we ran it
@@ -731,7 +768,7 @@ jobs:
- restore-fe-deps-cache
- run:
name: Run yarn to install deps
command: yarn;
command: rm -rf node_modules/ && yarn --frozen-lockfile;
no_output_timeout: 15m
- save_cache:
name: Cache frontend dependencies
@@ -743,7 +780,7 @@ jobs:
- /home/circleci/.cache/Cypress
shared-tests-cljs:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- run-yarn-command:
command-name: Run Cljs tests for shared/ code
@@ -753,7 +790,7 @@ jobs:
# Unlike the other build-uberjar steps, this step should be run once overall and the results can be shared between
# OSS and EE uberjars.
build-uberjar-drivers:
executor: clojure-and-node
executor: clojure-and-node-and-browsers
parameters:
<<: *Params
steps:
@@ -787,25 +824,14 @@ jobs:
name: Cache the built drivers
<<: *CacheKeyDrivers
paths:
- /home/circleci/metabase/metabase/modules/drivers/bigquery/target
- /home/circleci/metabase/metabase/modules/drivers/druid/target
- /home/circleci/metabase/metabase/modules/drivers/google/target
- /home/circleci/metabase/metabase/modules/drivers/googleanalytics/target
- /home/circleci/metabase/metabase/modules/drivers/mongo/target
- /home/circleci/metabase/metabase/modules/drivers/oracle/target
- /home/circleci/metabase/metabase/modules/drivers/presto/target
- /home/circleci/metabase/metabase/modules/drivers/redshift/target
- /home/circleci/metabase/metabase/modules/drivers/snowflake/target
- /home/circleci/metabase/metabase/modules/drivers/sparksql/target
- /home/circleci/metabase/metabase/modules/drivers/sqlite/target
- /home/circleci/metabase/metabase/modules/drivers/sqlserver/target
- /home/circleci/metabase/metabase/modules/drivers/vertica/target
- /home/circleci/metabase/metabase/resources/modules
# Build the frontend client. parameters.edition determines whether we build the OSS or EE version.
build-uberjar-frontend:
parameters:
<<: *Params
executor: clojure-and-node
executor: clojure-and-node-and-browsers
resource_class: large
steps:
- attach-workspace
- run-on-change:
@@ -829,7 +855,7 @@ jobs:
build-uberjar:
parameters:
<<: *Params
executor: clojure-and-node
executor: clojure-and-node-and-browsers
steps:
- attach-workspace
- run-on-change:
@@ -857,7 +883,7 @@ jobs:
# INTERACTIVE=false will tell the clojure build scripts not to do interactive retries etc.
INTERACTIVE: "false"
MB_EDITION: << parameters.edition >>
command: ./bin/build version drivers uberjar
command: ./bin/build version uberjar
no_output_timeout: 15m
- store_artifacts:
path: /home/circleci/metabase/metabase/target/uberjar/metabase.jar
@@ -880,9 +906,15 @@ jobs:
source-folder:
type: string
default: ""
folder:
type: string
default: ""
test-files:
type: string
default: ""
qa-db:
type: boolean
default: false
before-steps:
type: steps
default: []
@@ -891,6 +923,7 @@ jobs:
environment:
MB_EDITION: << parameters.edition >>
CYPRESS_GROUP: << parameters.cypress-group >>
QA_DB_ENABLED: << parameters.qa-db >>
DISPLAY: ""
steps:
- attach-workspace
@@ -904,8 +937,9 @@ jobs:
name: Restore cached uberjar built in previous step
<<: *CacheKeyUberjar
- steps: << parameters.before-steps >>
# Make both `test-files` and `source-folder` parameters optional. Translates to: if `parameter` => run associated flag (`--spec` and `--folder`, respectively)
command: |
run test-cypress-no-build <<# parameters.test-files >> --spec << parameters.test-files >> <</ parameters.test-files >> --folder << parameters.source-folder >>
run test-cypress-no-build <<# parameters.test-files >> --spec << parameters.test-files >> <</ parameters.test-files >> <<# parameters.source-folder >> --folder << parameters.source-folder >> <</ parameters.source-folder >>
after-steps:
- store_artifacts:
path: /home/circleci/metabase/metabase/cypress
@@ -937,42 +971,44 @@ workflows:
requires:
- checkout
- lein:
- clojure:
name: be-tests-<< matrix.edition >>
requires:
- be-deps
e: java-8
lein-command: with-profile +junit test
clojure-args: -X:dev:ci:test
skip-when-no-change: true
<<: *Matrix
- lein:
- clojure:
name: be-tests-java-11-<< matrix.edition >>
requires:
- be-deps
e: java-11
lein-command: with-profile +junit test
clojure-args: -X:dev:ci:test
skip-when-no-change: true
<<: *Matrix
- lein:
- clojure:
name: be-tests-java-16-<< matrix.edition >>
requires:
- be-deps
e: java-16
lein-command: with-profile +junit test
clojure-args: -X:dev:ci:test
skip-when-no-change: true
<<: *Matrix
- lein:
- clojure:
name: be-linter-cloverage
requires:
- be-deps
lein-command: cloverage --codecov
# TODO FIXME
clojure-args: -X:dev:ee:ee-dev:test:cloverage
after-steps:
- run:
name: Upload code coverage to codecov.io
command: bash <(curl -s https://codecov.io/bash)
command: bash <(curl -s https://codecov.io/bash) -F back-end
skip-when-no-change: true
- test-driver:
@@ -981,6 +1017,12 @@ workflows:
- be-tests-ee
driver: bigquery
- test-driver:
name: be-tests-bigquery-cloud-sdk-ee
requires:
- be-tests-ee
driver: bigquery-cloud-sdk
- test-driver:
name: be-tests-druid-ee
requires:
@@ -996,9 +1038,18 @@ workflows:
- test-driver:
name: be-tests-mongo-ee
description: "(Mongo 4.0)"
requires:
- be-tests-ee
e: mongo
e: mongo-4-0
driver: mongo
- test-driver:
name: be-tests-mongo-latest-ee
description: "(Mongo latest)"
requires:
- be-tests-ee
e: mongo-latest
driver: mongo
- test-driver:
@@ -1085,12 +1136,45 @@ workflows:
name: be-tests-presto-ee
requires:
- be-tests-ee
e: presto
e: presto-186
before-steps:
- wait-for-port:
port: 8080
driver: presto
- test-driver:
name: be-tests-presto-jdbc-ee
requires:
- be-tests-ee
e: presto-jdbc-env # specific env for running Presto JDBC tests (newer Presto version, SSL, etc.)
before-steps:
- wait-for-port:
port: 8443
- run:
name: Create temp cacerts file based on bundled JDK one
command: cp $JAVA_HOME/lib/security/cacerts /tmp/cacerts-with-presto-ssl.jks
- run:
name: Capture Presto server self signed CA
command: |
while [[ ! -s /tmp/presto-ssl-ca.pem ]];
do echo "Waiting to capture SSL CA" \
&& openssl s_client -connect localhost:8443 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/presto-ssl-ca.pem \
&& sleep 1; done
- run:
name: Convert Presto CA from PEM to DER
command: openssl x509 -outform der -in /tmp/presto-ssl-ca.pem -out /tmp/presto-ssl-ca.der
- run:
name: Import Presto CA into temp cacerts file
command: |
sudo keytool -noprompt -import -alias presto -keystore /tmp/cacerts-with-presto-ssl.jks \
-storepass changeit -file /tmp/presto-ssl-ca.der -trustcacerts
after-steps:
- run:
name: Capture max memory usage
command: cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes
when: always
driver: presto-jdbc
- test-driver:
name: be-tests-redshift-ee
requires:
@@ -1173,144 +1257,27 @@ workflows:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-smoketest-<< matrix.edition >>
folder: ["admin", "binning", "collections", "dashboard", "dashboard-filters", "dashboard-filters-sql", "moderation", "native", "native-filters", "onboarding", "permissions", "question", "sharing", "smoketest", "visualizations"]
name: e2e-tests-<< matrix.folder >>-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "smoketest-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/smoketest
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-admin-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "admin-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/admin
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-collections-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "collections-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/collections
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-dashboard-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "dashboard-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/dashboard
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-filters-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "filters-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/filters
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-onboarding-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "onboarding-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/onboarding
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-native-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "native-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/native
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-question-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "question-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/question
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-binning-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "binning-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/binning
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-sharing-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "sharing-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/sharing
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: e2e-tests-visualizations-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "visualizations-<< matrix.edition >>"
source-folder: frontend/test/metabase/scenarios/visualizations
- fe-tests-cypress:
name: e2e-tests-mongo-4-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
e: fe-mongo-4
cypress-group: "mongo"
source-folder: frontend/test/metabase-db/mongo
before-steps:
- wait-for-port:
port: 27017
<<: *Matrix
- fe-tests-cypress:
name: e2e-tests-postgres-12-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
e: fe-postgres-12
cypress-group: "postgres"
source-folder: frontend/test/metabase-db/postgres
before-steps:
- wait-for-port:
port: 5432
<<: *Matrix
- fe-tests-cypress:
name: e2e-tests-mysql-8-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
e: fe-mysql-8
cypress-group: "mysql"
source-folder: frontend/test/metabase-db/mysql
cypress-group: "<< matrix.folder >>-<< matrix.edition >>"
source-folder: << matrix.folder >>
qa-db: true
before-steps:
- wait-for-port:
port: 3306
<<: *Matrix
- wait-for-port:
port: 5432
- wait-for-port:
port: 27017
- fe-tests-cypress:
matrix:
parameters:
edition: ["ee", "oss"]
name: percy-visual-tests-<< matrix.edition >>
requires:
- build-uberjar-<< matrix.edition >>
cypress-group: "percy-visual-<< matrix.edition >>"
test-files: "./frontend/test/metabase-visual/**/*.cy.spec.js"

View File

@@ -2,4 +2,10 @@ FROM mcr.microsoft.com/vscode/devcontainers/java:11
RUN apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com\
&& apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends leiningen
&& apt-get -y install --no-install-recommends yarn
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash
RUN apt-get update && apt-get -y install --no-install-recommends nodejs
RUN curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh \
&& bash ./linux-install-1.10.3.933.sh

View File

@@ -1,49 +1,78 @@
((nil . ((indent-tabs-mode . nil) ; always use spaces for tabs
(require-final-newline . t))) ; add final newline on save
(js2-mode . ((js2-mode-show-parse-errors . nil) ; these settings will let flycheck do everything through eslint,
(js2-mode-show-strict-warnings . nil))) ; because js2-mode can't handle flowtype
(clojure-mode . ((eval . (progn
;; Specify which arg is the docstring for certain macros
;; (Add more as needed)
(put 'defendpoint 'clojure-doc-string-elt 3)
(put 'defendpoint-async 'clojure-doc-string-elt 3)
(put 'api/defendpoint 'clojure-doc-string-elt 3)
(put 'api/defendpoint-async 'clojure-doc-string-elt 3)
(put 'defsetting 'clojure-doc-string-elt 2)
(put 'setting/defsetting 'clojure-doc-string-elt 2)
(put 's/defn 'clojure-doc-string-elt 2)
(put 'p.types/defprotocol+ 'clojure-doc-string-elt 2)
((nil
;; always use spaces for tabs
(indent-tabs-mode . nil)
;; add final newline on save
(require-final-newline . t)
;; prefer keeping source width about ~118, GitHub seems to cut off stuff at either 119 or 120 and it's nicer
;; to look at code in GH when you don't have to scroll back and forth
(fill-column . 118)
;; tell find-things-fast to always use this directory as project root regardless of presence of other
;; deps.edn files
(ftf-project-finders . (ftf-get-top-git-dir)))
;; Define custom indentation for functions inside metabase.
;; This list isn't complete; add more forms as we come across them.
(define-clojure-indent
(db/insert-many! 1)
(let-404)
(macros/case 0)
(match 1)
(mbql.match/match 1)
(mt/test-drivers 1)
(mt/query 1)
(mbql.match/match-one 1)
(mbql.match/replace 1)
(mbql.match/replace-in 2)
(impl/test-migrations 2)
(l/matche '(1 (:defn)))
(l/matcha '(1 (:defn)))
(p/defprotocol+ '(1 (:defn)))
(p.types/defprotocol+ '(1 (:defn)))
(p.types/def-abstract-type '(1 (:defn)))
(p.types/deftype+ '(2 nil nil (:defn)))
(p/def-map-type '(2 nil nil (:defn)))
(p.types/defrecord+ '(2 nil nil (:defn)))
(qp.streaming/streaming-response 1)
(prop/for-all 1)
(tools.macro/macrolet '(1 (:defn))))))
(clojure-indent-style . always-align)
;; if you're using clj-refactor (highly recommended!)
(cljr-favor-prefix-notation . nil)
;; prefer keeping source width about ~118, GitHub seems to cut off stuff at either 119 or 120 and
;; it's nicer to look at code in GH when you don't have to scroll back and forth
(fill-column . 118)
(clojure-docstring-fill-column . 118)
(cider-preferred-build-tool . lein))))
(js2-mode
;; these settings will let flycheck do everything through eslint,
(js2-mode-show-parse-errors . nil)
;; because js2-mode can't handle flowtype
(js2-mode-show-strict-warnings . nil))
(clojure-mode
;; Specify which arg is the docstring for certain macros
;; (Add more as needed)
(eval . (put 'defendpoint 'clojure-doc-string-elt 3))
(eval . (put 'defendpoint-async 'clojure-doc-string-elt 3))
(eval . (put 'define-premium-feature 'clojure-doc-string-elt 2))
(eval . (put 'api/defendpoint 'clojure-doc-string-elt 3))
(eval . (put 'api/defendpoint-async 'clojure-doc-string-elt 3))
(eval . (put 'defsetting 'clojure-doc-string-elt 2))
(eval . (put 'setting/defsetting 'clojure-doc-string-elt 2))
(eval . (put 's/defn 'clojure-doc-string-elt 2))
(eval . (put 'p.types/defprotocol+ 'clojure-doc-string-elt 2))
;; Define custom indentation for functions inside metabase.
;; This list isn't complete; add more forms as we come across them.
;;
;; `put-clojure-indent' is a safe-local-eval-function, so use a bunch of calls to that
;; instead of one call to `define-clojure-indent'
(eval . (put-clojure-indent 'c/step 1))
(eval . (put-clojure-indent 'db/insert-many! 1))
(eval . (put-clojure-indent 'impl/test-migrations 2))
(eval . (put-clojure-indent 'let-404 0))
(eval . (put-clojure-indent 'macros/case 0))
(eval . (put-clojure-indent 'match 1))
(eval . (put-clojure-indent 'mbql.match/match 1))
(eval . (put-clojure-indent 'mbql.match/match-one 1))
(eval . (put-clojure-indent 'mbql.match/replace 1))
(eval . (put-clojure-indent 'mbql.match/replace-in 2))
(eval . (put-clojure-indent 'mt/dataset 1))
(eval . (put-clojure-indent 'mt/query 1))
(eval . (put-clojure-indent 'mt/test-drivers 1))
(eval . (put-clojure-indent 'prop/for-all 1))
(eval . (put-clojure-indent 'qp.streaming/streaming-response 1))
;; these ones have to be done with `define-clojure-indent' for now because of upstream bug
;; https://github.com/clojure-emacs/clojure-mode/issues/600 once that's resolved we should use `put-clojure-indent'
;; instead. Please don't add new entries unless they don't work with `put-clojure-indent'
(eval . (define-clojure-indent
(l/matcha '(1 (:defn)))
(l/matche '(1 (:defn)))
(p.types/def-abstract-type '(1 (:defn)))
(p.types/defprotocol+ '(1 (:defn)))
(p.types/defrecord+ '(2 nil nil (:defn)))
(p.types/deftype+ '(2 nil nil (:defn)))
(p/def-map-type '(2 nil nil (:defn)))
(p/defprotocol+ '(1 (:defn)))
(tools.macro/macrolet '(1 ((:defn)) :form))))
(cider-clojure-cli-aliases . "dev:drivers:drivers-dev:ee:ee-dev:user")
(clojure-indent-style . always-align)
(cljr-favor-prefix-notation . nil)
(clojure-docstring-fill-column . 118)
(cider-preferred-build-tool . clojure-cli))
("shared"
(clojure-mode
(cider-default-cljs-repl . shadow-select)
(cider-shadow-default-options . "node-repl")
(cider-preferred-build-tool . shadow-cljs)))
("bin"
(clojure-mode
(cider-clojure-cli-aliases . "dev"))))

View File

@@ -1,12 +1,25 @@
.babel_cache/*
.babel_cache
docs/*
OSX/*
target/*
**node_modules
.circleci
.cpcache
.devcontainer
.github
.husky
.lsp
.shadow-cljs
.github
.vscode
hooks/*
test/*
test_config/*
test_modules/*
test_resources/*
node_modules
**metabase.jar
*.db
.dockerignore
Dockerfile
.dockerignore

View File

@@ -21,13 +21,13 @@
"react/no-unescaped-entities": 2,
"react/jsx-no-target-blank": 2,
"react/jsx-key": 2,
"react/forbid-component-props": [2, { "forbid": ["w", "h"] }],
"prefer-const": [1, { "destructuring": "all" }],
"no-useless-escape": 0,
"no-only-tests/no-only-tests": "error",
"complexity": ["error", { "max": 54 }]
},
"globals": {
"pending": false,
"before": true,
"cy": true,
"Cypress": true
@@ -58,5 +58,25 @@
"ecmaFeatures": {
"legacyDecorators": true
}
}
},
"overrides": [
{
"extends": ["plugin:@typescript-eslint/recommended"],
"files": ["*.ts", "*.tsx"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-use-before-define": [
"error",
{ "functions": false }
]
}
}
]
}

View File

@@ -5,7 +5,6 @@
### Tests
- [ ] Run the frontend and Cypress end-to-end tests with `yarn lint && yarn test`)
- [ ] If there are changes to the backend codebase, run the backend tests with `lein test && lein lint && ./bin/reflection-linter`
- [ ] If there are changes to the backend codebase, run the backend tests with `clojure -X:dev:test`
- [ ] Sign the [Contributor License Agreement](https://docs.google.com/a/metabase.com/forms/d/1oV38o7b9ONFSwuzwmERRMi9SYrhYeOrkbmNaq9pOJ_E/viewform)
(unless it's a tiny documentation change).

3
.github/scripts/README.md vendored Normal file
View File

@@ -0,0 +1,3 @@
# GitHub Action Test Scripts
Scripts related to running integration tests (ex: through GitHub actions)

View File

@@ -0,0 +1,68 @@
#! /usr/bin/env bash
# runs one or more Metabase test(s) against a Kerberized Presto instance
set -eo pipefail
# Need Java commands on $PATH, which apparently is not yet the case
export PATH="$PATH:$JAVA_HOME/bin"
# ensure java commmand is available
which java
# install clojure version needed for Metabase
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh
chmod +x linux-install-1.10.3.933.sh
./linux-install-1.10.3.933.sh
RESOURCES_DIR=/app/source/resources
# ensure the expected files are in place, in the resources dir
if [ ! -f "$RESOURCES_DIR/ssl_keystore.jks" ]; then
echo "$RESOURCES_DIR/ssl_keystore.jks does not exist; cannot run test" >&2
exit 11
fi
if [ ! -f "$RESOURCES_DIR/krb5.conf" ]; then
echo "$RESOURCES_DIR/krb5.conf does not exist; cannot run test" >&2
exit 12
fi
if [ ! -f "$RESOURCES_DIR/client.keytab" ]; then
echo "$RESOURCES_DIR/client.keytab does not exist; cannot run test" >&2
exit 13
fi
# Copy the JDK cacerts file to our resources
cp $JAVA_HOME/lib/security/cacerts $RESOURCES_DIR/cacerts-with-presto-ca.jks
# Capture the Presto server self signed CA in PEM format
openssl s_client -showcerts -connect presto-kerberos:7778 </dev/null \
| openssl x509 -outform PEM >$RESOURCES_DIR/presto-ssl-root-ca.pem
# Convert the Presto server self signed CA to DER format
openssl x509 -outform der -in $RESOURCES_DIR/presto-ssl-root-ca.pem -out $RESOURCES_DIR/presto-ssl-root-ca.der
# Add Presto's self signed CA to the truststore
keytool -noprompt -import -alias presto-kerberos -keystore $RESOURCES_DIR/cacerts-with-presto-ca.jks \
-storepass changeit -file $RESOURCES_DIR/presto-ssl-root-ca.der -trustcacerts
ADDITIONAL_OPTS="SSLKeyStorePath=$RESOURCES_DIR/ssl_keystore.jks&SSLKeyStorePassword=presto\
&SSLTrustStorePath=$RESOURCES_DIR/cacerts-with-presto-ca.jks&SSLTrustStorePassword=changeit"
# Prepare dependencies
source "./bin/prep.sh"
prep_deps
# Set up the environment variables pointing to all of this, and run some tests
DRIVERS=presto-jdbc \
MB_ENABLE_PRESTO_JDBC_DRIVER=true \
MB_PRESTO_JDBC_TEST_HOST=presto-kerberos \
MB_PRESTO_JDBC_TEST_PORT=7778 \
MB_PRESTO_JDBC_TEST_SSL=true \
MB_PRESTO_JDBC_TEST_KERBEROS=true \
MB_PRESTO_JDBC_TEST_USER=bob@EXAMPLE.COM \
MB_PRESTO_JDBC_TEST_KERBEROS_PRINCIPAL=bob@EXAMPLE.COM \
MB_PRESTO_JDBC_TEST_KERBEROS_REMOTE_SERVICE_NAME=HTTP \
MB_PRESTO_JDBC_TEST_KERBEROS_KEYTAB_PATH=$RESOURCES_DIR/client.keytab \
MB_PRESTO_JDBC_TEST_KERBEROS_CONFIG_PATH=$RESOURCES_DIR/krb5.conf \
MB_PRESTO_JDBC_TEST_ADDITIONAL_OPTIONS=$ADDITIONAL_OPTS \
clojure -X:dev:test:drivers:drivers-dev :only metabase.driver.presto-jdbc-test

131
.github/workflows/auto-backport.yml vendored Normal file
View File

@@ -0,0 +1,131 @@
# Creates a pull request with the latest release branch as a target with a cherry-picked commit if an associated pull request has `backport` label
name: AutoBackport
on:
push:
branches:
- master
jobs:
pr_info:
name: Check if the commit should be backported
runs-on: ubuntu-latest
outputs:
title: ${{ fromJson(steps.collect_pr_info.outputs.result).title }}
number: ${{ fromJson(steps.collect_pr_info.outputs.result).pullRequestNumber }}
author: ${{ fromJson(steps.collect_pr_info.outputs.result).author }}
should_backport: ${{ fromJson(steps.collect_pr_info.outputs.result).hasBackportLabel }}
steps:
- uses: actions/github-script@v4
id: collect_pr_info
with:
script: |
const commitMessage = context.payload.commits[0].message;
const pullRequestNumbers = Array.from(commitMessage.matchAll(/\(#(.*?)\)/g))
if (pullRequestNumbers.length === 0) {
return;
}
if (pullRequestNumbers > 1) {
throw "Multiple PRs are associated with this commit";
}
const pullRequestNumber = pullRequestNumbers[0][1];
const { data } = await github.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullRequestNumber
});
const hasBackportLabel = data.labels.some((label) => label.name === 'backport');
const { title, user } = data
console.log(`PR #${pullRequestNumber}: "${title}" hasBackportLabel=${hasBackportLabel}`)
return {
author: user.login,
pullRequestNumber,
title: data.title,
hasBackportLabel
}
get_latest_release_branch:
name: Get latest release branch
runs-on: ubuntu-latest
outputs:
branch_name: ${{ steps.get_branch_name.outputs.result }}
steps:
- uses: actions/github-script@v4
id: get_branch_name
with:
result-encoding: string
script: |
const releaseBranches = await github.git.listMatchingRefs({
owner: context.repo.owner,
repo: context.repo.repo,
ref: "heads/release-x.",
});
const getVersionFromBranch = branch => {
const match = branch.match(/release-x\.(.*?)\.x/);
return match && parseInt(match[1])
};
const latestReleaseBranch = releaseBranches.data
.filter(branch => getVersionFromBranch(branch.ref) !== null)
.reduce((prev, current) => getVersionFromBranch(prev.ref) > getVersionFromBranch(current.ref) ? prev : current);
const latestReleaseBranchName = latestReleaseBranch.ref.replace(/^refs\/heads\//, "");
console.log(`Latest release branch: ${latestReleaseBranchName}`)
return latestReleaseBranchName;
create_backport_pull_request:
runs-on: ubuntu-latest
name: Create a backport PR with the commit
needs: [pr_info, get_latest_release_branch]
if: ${{ needs.pr_info.outputs.should_backport == 'true' }}
env:
TARGET_BRANCH: ${{ needs.get_latest_release_branch.outputs.branch_name }}
ORIGINAL_PULL_REQUEST_NUMBER: ${{ needs.pr_info.outputs.number }}
ORIGINAL_TITLE: ${{ needs.pr_info.outputs.title }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
name: Checkout
with:
fetch-depth: 0
- run: |
git config --global user.email "metabase-github-automation@metabase.com"
git config --global user.name "$GITHUB_ACTOR"
BACKPORT_BRANCH="backport-$GITHUB_SHA"
git fetch --all
git checkout -b "${BACKPORT_BRANCH}" origin/"${TARGET_BRANCH}"
git cherry-pick "${GITHUB_SHA}"
git push -u origin "${BACKPORT_BRANCH}"
hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "auto-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
#${ORIGINAL_PULL_REQUEST_NUMBER}"
notify_when_failed:
runs-on: ubuntu-latest
name: Notify about failure
needs: [pr_info, create_backport_pull_request]
if: ${{ failure() }}
steps:
- uses: actions/github-script@v4
with:
script: |
const { GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID } = process.env;
const runUrl = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`
github.issues.createComment({
issue_number: ${{ needs.pr_info.outputs.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${{ needs.pr_info.outputs.author }} could not automatically create a backport PR 😩 [[Logs]](${runUrl})`
})

View File

@@ -4,13 +4,9 @@ on:
pull_request:
push:
branches:
- master
- 'release**'
- 'feature**'
tags:
- '**'
paths:
- '**.clj'
- '**.clj*'
- '**.edn'
- '**.java'
- '**/metabase-plugin.yaml'
@@ -26,53 +22,31 @@ jobs:
- name: Run clj-kondo
run: docker run -v $PWD:/work --rm cljkondo/clj-kondo clj-kondo --config /work/lint-config.edn --lint /work/src /work/enterprise/backend/src /work/backend/mbql/src /work/shared/src
be-linter-bikeshed:
runs-on: ubuntu-20.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Prepare JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-bikeshed-${{ hashFiles('**/project.clj') }}
- run: lein with-profile +ci bikeshed
be-linter-eastwood:
runs-on: ubuntu-20.04
timeout-minutes: 10
timeout-minutes: 20
steps:
- uses: actions/checkout@v2
- name: Prepare JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-eastwood-${{ hashFiles('**/project.clj') }}
- run: lein with-profile +ci eastwood
be-linter-docstring-checker:
runs-on: ubuntu-20.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Prepare JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-docstring-checker-${{ hashFiles('**/project.clj') }}
- run: lein with-profile +ci docstring-checker
path: |
~/.m2
~/.gitlibs
key: ${{ runner.os }}-eastwood-${{ hashFiles('**/deps.edn') }}
- name: Compile Java & AOT Sources
run: |
source ./bin/prep.sh && prep_deps
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:eastwood
name: Run Eastwood linter
be-linter-namespace-decls:
runs-on: ubuntu-20.04
@@ -83,26 +57,19 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 11
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-namespace-decls-${{ hashFiles('**/project.clj') }}
- run: lein with-profile +ci check-namespace-decls
be-linter-reflection-warnings:
runs-on: ubuntu-20.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Prepare JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-reflection-warnings-${{ hashFiles('**/project.clj') }}
- run: ./bin/reflection-linter
name: Run reflection warnings checker
path: |
~/.m2
~/.gitlibs
key: ${{ runner.os }}-namespace-decls-${{ hashFiles('**/deps.edn') }}
- name: Compile Java & AOT Sources
run: |
source ./bin/prep.sh && prep_deps
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:namespace-checker
name: Check ns forms

131
.github/workflows/backport.yml vendored Normal file
View File

@@ -0,0 +1,131 @@
# Cherry-picks commits from current branch to a specified one in a command "@metabase-bot backport release-x.40.x"
name: Backport
on:
issue_comment:
types: [created]
jobs:
create_pull_request:
name: Creates a pull request
if: contains(github.event.comment.body, '@metabase-bot backport')
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v4
id: branch_info
with:
script: |
// Example: @metabase-bot backport release-x.40.x
const [_botName, _command, targetBranch] = context.payload.comment.body.split(" ");
console.log(`Target branch is ${targetBranch}`);
const { data: originalPullRequest } = await github.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.issue.number,
});
const { data: commits } = await github.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.issue.number,
});
const targetRef = await github.git.getRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${targetBranch}`,
});
const backportBranch = `backport-${originalPullRequest.head.ref}`
try {
await github.git.getRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${backportBranch}`,
});
} catch(e) {
if (e.status === 404) {
await github.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/heads/${backportBranch}`,
sha: targetRef.data.object.sha,
});
}
}
return {
backportBranch,
targetBranch,
originalPullRequest,
startSha: commits[0].sha,
endSha: commits[commits.length - 1].sha
}
- uses: actions/checkout@v2
name: Cherry-pick commits and create PR
with:
fetch-depth: 0
- run: |
git config --global user.email "metabase-github-automation@metabase.com"
git config --global user.name "$GITHUB_ACTOR"
git fetch --all
git checkout "${BACKPORT_BRANCH}"
git reset --hard origin/${TARGET_BRANCH}
if [[ -z $(git ls-remote --heads origin ${ORIGINAL_HEAD_REF}) ]]; then
echo "PR has been merged, searching for a squashed commit in the base branch"
echo "searching for a commit in a ${ORIGINAL_BASE_REF} that contains pull request number ${ORIGINAL_PULL_REQUEST_NUMBER}"
SQUASHED_COMMIT=$(env -i git log ${ORIGINAL_BASE_REF} --grep="(#${ORIGINAL_PULL_REQUEST_NUMBER})" --format="%H")
echo "found commit ${SQUASHED_COMMIT}"
git cherry-pick ${SQUASHED_COMMIT}
else
echo "PR has not been merged, copying all commits"
git cherry-pick ${ORIGINAL_BASE_SHA}..${ORIGINAL_HEAD_SHA}
fi
git push origin "${BACKPORT_BRANCH}" --force-with-lease
if [[ $(hub pr list -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -s "open") ]]; then
echo "PR already exists"
else
hub pull-request -b "${TARGET_BRANCH}" -h "${BACKPORT_BRANCH}" -l "auto-backported" -a "${GITHUB_ACTOR}" -F- <<<"🤖 backported \"${ORIGINAL_TITLE}\"
#${ORIGINAL_PULL_REQUEST_NUMBER}"
echo "New PR has been created"
fi
env:
ORIGINAL_TITLE: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.title }}
ORIGINAL_BASE_REF: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.base.ref }}
ORIGINAL_BASE_SHA: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.base.sha }}
ORIGINAL_HEAD_REF: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.head.ref }}
ORIGINAL_HEAD_SHA: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.head.sha }}
ORIGINAL_PULL_REQUEST_NUMBER: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.number }}
TARGET_BRANCH: ${{ fromJson(steps.branch_info.outputs.result).targetBranch }}
BACKPORT_BRANCH: ${{ fromJson(steps.branch_info.outputs.result).backportBranch }}
START_SHA: ${{ fromJson(steps.branch_info.outputs.result).startSha }}
END_SHA: ${{ fromJson(steps.branch_info.outputs.result).endSha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
notify_when_failed:
runs-on: ubuntu-latest
name: Notify about failure
needs: create_pull_request
if: ${{ failure() }}
steps:
- uses: actions/github-script@v4
with:
script: |
const { GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID} = process.env;
const runUrl = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`
const author = context.payload.comment.user.login;
github.issues.createComment({
issue_number: context.payload.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${author} could not automatically a backport PR 😩 [[Logs]](${runUrl})`
})

View File

@@ -23,4 +23,4 @@ jobs:
run: while ! curl -s localhost:3000/api/health; do sleep 1; done
timeout-minutes: 1
- name: Check API health
run: curl -s localhost:3000/api/health
run: curl -s localhost:3000/api/health

View File

@@ -4,12 +4,6 @@ on:
pull_request:
push:
branches:
- master
- 'release**'
- 'feature**'
- 'fix**'
- 'ci**'
tags:
- '**'
paths:
- 'frontend/**'
@@ -18,6 +12,7 @@ on:
- 'docs/**'
- '**/package.json'
- '**/yarn.lock'
- '**/.eslintrc'
- '.github/workflows/**'
jobs:
@@ -49,6 +44,11 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-cljs-${{ hashFiles('**/shadow-cljs.edn') }}
- name: Get yarn cache
uses: actions/cache@v2
with:
@@ -78,21 +78,31 @@ jobs:
fe-tests-unit:
runs-on: ubuntu-20.04
timeout-minutes: 10
timeout-minutes: 12
steps:
- uses: actions/checkout@v2
- name: Prepare Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-cljs-${{ hashFiles('**/shadow-cljs.edn') }}
- name: Get yarn cache
uses: actions/cache@v2
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- run: yarn install --frozen-lockfile --prefer-offline
- run: yarn run test-unit
- run: yarn run test-unit --coverage --silent
name: Run frontend unit tests
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v2
with:
files: ./coverage/lcov.info
flags: front-end
fe-tests-timezones:
runs-on: ubuntu-20.04
@@ -103,6 +113,11 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-cljs-${{ hashFiles('**/shadow-cljs.edn') }}
- name: Get yarn cache
uses: actions/cache@v2
with:

View File

@@ -4,13 +4,9 @@ on:
pull_request:
push:
branches:
- master
- 'release**'
- 'feature**'
tags:
- '**'
paths:
- '**.clj'
- '**.clj*'
- '**.js'
- '**.jsx'
- '.github/workflows/**'
@@ -38,8 +34,8 @@ jobs:
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.1.708.sh &&
sudo bash ./linux-install-1.10.1.708.sh
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- run: ./bin/i18n/update-translation-template
name: Check i18n tags/make sure template can be built

View File

@@ -0,0 +1,144 @@
# Triggers Percy job by "@metabase-bot run visual tests" comment in a PR
name: PercyIssueComment
on:
issue_comment:
types: [created]
jobs:
pr_info:
if: github.event.comment.body == '@metabase-bot run visual tests'
runs-on: ubuntu-20.04
outputs:
pull_request_number: ${{ fromJson(steps.fetch_pr.outputs.data).head.number }}
branch_name: ${{ fromJson(steps.fetch_pr.outputs.data).head.ref }}
commit_sha: ${{ fromJson(steps.fetch_pr.outputs.data).head.sha }}
steps:
- name: Fetch issue
uses: octokit/request-action@v2.x
id: fetch_issue
with:
route: GET ${{ github.event.issue.url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch PR
uses: octokit/request-action@v2.x
id: fetch_pr
with:
route: GET ${{ fromJson(steps.fetch_issue.outputs.data).pull_request.url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build:
runs-on: ubuntu-20.04
needs: pr_info
timeout-minutes: 60
strategy:
matrix:
edition: [oss]
env:
MB_EDITION: ${{ matrix.edition }}
INTERACTIVE: false
steps:
- uses: actions/checkout@v2
with:
ref: ${{ needs.pr_info.outputs.branch_name }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Prepare JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Check versions
run: |
echo "Node.js `node --version`"
echo "yarn `yarn --version`"
java -version
- name: Get yarn cache
uses: actions/cache@v2
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/deps.edn') }}
- run: yarn install --frozen-lockfile --prefer-offline
- run: ./bin/build
- name: Mark with the commit hash
run: git rev-parse --short HEAD > COMMIT-ID
- name: Calculate SHA256 checksum
run: sha256sum ./target/uberjar/metabase.jar > SHA256.sum
- name: Upload JARs as artifact
uses: actions/upload-artifact@v2
with:
name: metabase-${{ matrix.edition }}-uberjar
path: |
./target/uberjar/metabase.jar
./COMMIT-ID
./SHA256.sum
percy:
timeout-minutes: 30
needs: [build, pr_info]
runs-on: ubuntu-20.04
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
ref: ${{ needs.pr_info.outputs.branch_name }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Prepare JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Check versions
run: |
echo "Node.js `node --version`"
echo "yarn `yarn --version`"
java -version
- name: Get yarn cache
uses: actions/cache@v2
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- run: yarn install --frozen-lockfile --prefer-offline
- uses: actions/download-artifact@v2
name: Retrieve uberjar artifact
with:
name: metabase-oss-uberjar
- name: Get the version info
run: |
jar xf target/uberjar/metabase.jar version.properties
mv version.properties resources/
- name: Percy Test
run: yarn run test-visual-no-build
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
PERCY_COMMIT: ${{ needs.pr_info.outputs.commit_sha }}
PERCY_BRANCH: ${{ needs.pr_info.outputs.branch_name }}
PERCY_PULL_REQUEST: ${{ needs.pr_info.outputs.pull_request_number }}

115
.github/workflows/percy.yml vendored Normal file
View File

@@ -0,0 +1,115 @@
# Triggers Percy job on push to master and release branches to create baseline screenshots
name: Percy
on:
push:
branches:
- master
- "release-**"
paths-ignore:
- "docs/**"
- "**.md"
- "**unit.spec.js"
- "frontend/test/**"
- "!frontend/test/metabase-visual/**"
jobs:
build:
runs-on: ubuntu-20.04
timeout-minutes: 60
strategy:
matrix:
edition: [oss]
env:
MB_EDITION: ${{ matrix.edition }}
INTERACTIVE: false
steps:
- uses: actions/checkout@v2
- name: Prepare Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Prepare JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Check versions
run: |
echo "Node.js `node --version`"
echo "yarn `yarn --version`"
java -version
- name: Get yarn cache
uses: actions/cache@v2
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/deps.edn') }}
- run: yarn install --frozen-lockfile --prefer-offline
- run: ./bin/build
- name: Mark with the commit hash
run: git rev-parse --short HEAD > COMMIT-ID
- name: Calculate SHA256 checksum
run: sha256sum ./target/uberjar/metabase.jar > SHA256.sum
- name: Upload JARs as artifact
uses: actions/upload-artifact@v2
with:
name: metabase-${{ matrix.edition }}-uberjar
path: |
./target/uberjar/metabase.jar
./COMMIT-ID
./SHA256.sum
percy:
runs-on: ubuntu-20.04
timeout-minutes: 30
needs: build
steps:
- uses: actions/checkout@v2
- name: Prepare Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Prepare JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Check versions
run: |
echo "Node.js `node --version`"
echo "yarn `yarn --version`"
java -version
- name: Get yarn cache
uses: actions/cache@v2
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- run: yarn install --frozen-lockfile --prefer-offline
- uses: actions/download-artifact@v2
name: Retrieve uberjar artifact
with:
name: metabase-oss-uberjar
- name: Get the version info
run: |
jar xf target/uberjar/metabase.jar version.properties
mv version.properties resources/
- name: Percy Test
run: yarn run test-visual-no-build
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}

View File

@@ -0,0 +1,70 @@
name: Kerberized Presto Integration Test
on:
pull_request:
push:
branches:
- master
- 'release**'
- 'feature**'
tags:
- '**'
paths:
- '**/presto_jdbc/**'
- '**/presto_jdbc.clj'
jobs:
run-presto-kerberos-test:
runs-on: ubuntu-20.04
timeout-minutes: 40
steps:
- name: Install babashka
run: >
mkdir -p /tmp/babashka-install \
&& cd /tmp/babashka-install \
&& curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install \
&& chmod +x install \
&& sudo ./install \
&& cd -
- name: Checkout Metabase repository
uses: actions/checkout@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check out Presto Kerberos Docker Compose
uses: actions/checkout@v2
with:
repository: metabase/presto-kerberos-docker
ref: add-test_data-catalog
token: ${{ secrets.GITHUB_TOKEN }}
path: presto-kerberos-docker
- name: Bring up Presto+Kerberos cluster
run: cd presto-kerberos-docker && docker-compose up -d && cd ..
- name: Run Presto test query from command line (sanity check)
run: cd presto-kerberos-docker && ./test.sh && cd ..
# Since we are managing the Docker containers from the GitHub action container, we need to copy all the
# relevant resources now, into the resources dir for later consumption by the app
- name: Copy Presto SSL keystore to resources
run: docker cp presto-kerberos:/tmp/ssl_keystore.jks resources
- name: Copy krb5.conf file to resources
run: docker cp presto-kerberos:/etc/krb5.conf resources
- name: Copy client.keytab file to resources
run: docker cp presto-kerberos:/home/presto/client.keytab resources
- name: Checkout mba
uses: actions/checkout@v2
with:
repository: metabase/mba
ref: master
token: ${{ secrets.GITHUB_TOKEN }}
path: mba-src
- name: ls mba
run: ls -latr mba-src
- name: Symlink mba
run: cd mba-src && sudo ln -s $(pwd)/src/main.clj /usr/local/bin/mba && chmod +x /usr/local/bin/mba && cd ..
- name: Ensure mba
run: which mba
- name: Run Metabase via MBA
run: /home/runner/work/metabase/metabase/mba-src/src/main.clj --mb . --data-db postgres-data -n example.com up
- name: Run test script in MBA instance
run: >
mba --mb . --data-db postgres-data -n example.com \
run .github/scripts/run-presto-kerberos-integration-test.sh

View File

@@ -3,9 +3,6 @@ name: Uberjar
on:
push:
branches:
- master
- 'release-**'
tags:
- '**'
paths-ignore:
- 'docs/**'
@@ -35,15 +32,13 @@ jobs:
java-version: 8
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.1.708.sh &&
sudo bash ./linux-install-1.10.1.708.sh
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Check versions
run: |
echo "Node.js `node --version`"
echo "yarn `yarn --version`"
java -version
echo "Clojure `clojure -e "(println (clojure-version))"`"
lein --version
- name: Get yarn cache
uses: actions/cache@v2
@@ -53,12 +48,13 @@ jobs:
- name: Get M2 cache
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/project.clj') }}-${{ hashFiles('**/deps.edn') }}
path: |
~/.m2
~/.gitlibs
key: ${{ runner.os }}-m2-${{ hashFiles('**/deps.edn') }}
- run: yarn install --lockfile
- run: lein with-profile +include-all-drivers,+cloverage,+junit,+${{ matrix.edition }} deps
- run: ./bin/build
- run: yarn install --frozen-lockfile --prefer-offline
- run: MB_EDITION=${{ matrix.edition }} ./bin/build
- name: Mark with the commit hash
run: git rev-parse --short HEAD > COMMIT-ID
@@ -81,7 +77,7 @@ jobs:
strategy:
matrix:
edition: [ee, oss]
java-version: [8, 11, 16]
java-version: [8, 11, 17]
steps:
- name: Prepare JRE (Java Run-time Environment)
uses: actions/setup-java@v1
@@ -96,9 +92,9 @@ jobs:
name: metabase-${{ matrix.edition }}-uberjar
- name: Launch uberjar
run: |
java -jar ./target/uberjar/metabase.jar &
sleep 180
run: java -jar ./target/uberjar/metabase.jar &
- name: Wait for Metabase to start
run: while ! curl -s localhost:3000/api/health; do sleep 1; done
timeout-minutes: 5
- name: Check API health

41
.github/workflows/whitespace.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Whitespace
on:
pull_request:
push:
branches:
- '**'
paths:
- '**.yaml'
- '**.yml'
- '**.clj'
- '**.edn'
- '**.el'
- '**.html'
- '**.json'
- '**.js*'
- '**.sh'
jobs:
whitespace-linter:
runs-on: ubuntu-20.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- name: Prepare JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.3.933.sh &&
sudo bash ./linux-install-1.10.3.933.sh
- name: Get M2 cache
uses: actions/cache@v2
with:
path: |
~/.m2
~/.gitlibs
key: ${{ runner.os }}-whitespace-linter-${{ hashFiles('**/deps.edn') }}
- run: clojure -T:whitespace-linter lint
name: Run Whitespace Linter

View File

@@ -4,10 +4,6 @@ on:
pull_request:
push:
branches:
- master
- 'release**'
- 'feature**'
tags:
- '**'
paths:
- '**.yml'

3
.gitignore vendored
View File

@@ -50,6 +50,8 @@
/resources/frontend_client/index.html
/resources/frontend_client/public.html
/resources/i18n/*.edn
/resources/license-backend-third-party.txt
/resources/license-frontend-third-party.txt
/resources/namespaces.edn
/resources/sample-dataset.db.trace.db
/resources/version.properties
@@ -78,6 +80,7 @@ dev/src/dev/nocommit/
**/cypress_sample_dataset.json
/frontend/src/cljs
.shadow-cljs
.clj-kondo/cache/
# lsp: ignore all but the config file
.lsp/*

View File

@@ -1 +0,0 @@
lein_tasks

View File

@@ -1,4 +1,4 @@
{:keep-require-at-start? true
:show-docs-arity-on-same-line? true
:project-specs [{:project-path "project.clj"
:classpath-cmd ["lein" "with-profile" "+ee" "classpath"]}]}
:project-specs [{:project-path "deps.edn"
:classpath-cmd ["clojure" "-A:dev:ee:ee-dev:drivers:drivers-dev" "-Spath"]}]}

7
.percy.yml Normal file
View File

@@ -0,0 +1,7 @@
version: 2
snapshot:
widths:
- 1280
min-height: 800
discovery:
disable-cache: true

22
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug with Firefox",
"request": "launch",
"type": "firefox",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"name": "Debug with Chrome",
"request": "launch",
"type": "pwa-chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
]
}

View File

@@ -1,66 +1,15 @@
###################
# STAGE 1.1: builder frontend
# STAGE 1: builder
###################
FROM metabase/ci:java-11-lein-2.9.6-clj-1.10.3.822-04-22-2021 as frontend
FROM metabase/ci:circleci-java-11-clj-1.10.3.929-07-27-2021-node-browsers as builder
ARG MB_EDITION=oss
WORKDIR /app/source
WORKDIR /home/circleci
COPY . .
RUN NODE_ENV=production MB_EDITION=$MB_EDITION yarn --frozen-lockfile && yarn build && bin/i18n/build-translation-resources
###################
# STAGE 1.2: backend deps
###################
FROM metabase/ci:java-11-lein-2.9.6-clj-1.10.3.822-04-22-2021 as backend
WORKDIR /app/source
# backend dependencies
COPY project.clj .
RUN lein deps :tree
###################
# STAGE 1.3: drivers
###################
FROM metabase/ci:java-11-lein-2.9.6-clj-1.10.3.822-04-22-2021 as drivers
ARG MB_EDITION=oss
WORKDIR /app/source
COPY --from=backend /root/.m2/repository/. /root/.m2/repository/.
# add the rest of the source
COPY . .
# build the app
RUN INTERACTIVE=false MB_EDITION=$MB_EDITION sh bin/build-drivers.sh
###################
# STAGE 1.4: main builder
###################
FROM metabase/ci:java-11-lein-2.9.6-clj-1.10.3.822-04-22-2021 as builder
ARG MB_EDITION=oss
WORKDIR /app/source
# try to reuse caching as much as possible
COPY --from=frontend /root/.m2/repository/. /root/.m2/repository/.
COPY --from=frontend /app/source/. .
COPY --from=backend /root/.m2/repository/. /root/.m2/repository/.
COPY --from=backend /app/source/. .
COPY --from=drivers /root/.m2/repository/. /root/.m2/repository/.
COPY --from=drivers /app/source/. .
# build the app
RUN INTERACTIVE=false MB_EDITION=$MB_EDITION bin/build version uberjar
COPY --chown=circleci . .
RUN INTERACTIVE=false CI=true MB_EDITION=$MB_EDITION bin/build
# ###################
# # STAGE 2: runner
@@ -83,7 +32,7 @@ RUN apk upgrade && apk add --update-cache --no-cache bash ttf-dejavu fontconfig
mkdir -p /plugins && chmod a+rwx /plugins
# add Metabase script and uberjar
COPY --from=builder /app/source/target/uberjar/metabase.jar /app/
COPY --from=builder /home/circleci/target/uberjar/metabase.jar /app/
COPY bin/docker/run_metabase.sh /app/
# expose our default runtime port

View File

@@ -23,58 +23,47 @@
// first, we need to stop the main Metabase task so we can access the DB
NSLog(@"Stopping Metabase task in order to reset password...");
[[AppDelegate instance] stopMetabaseTask];
self.task = [[NSTask alloc] init];
// time travelers from the future: this is hardcoded since I'm the only one who works on this. I give you permission to fix it - Cam
#define DEBUG_RUN_LEIN_TASK 0
#if DEBUG_RUN_LEIN_TASK
self.task.environment = @{@"MB_DB_FILE": DBPath()};
self.task.currentDirectoryPath = @"/Users/cam/metabase";
self.task.launchPath = @"/usr/local/bin/lein";
self.task.arguments = @[@"run", @"reset-password", emailAddress];
NSLog(@"Launching ResetPasswordTask\nMB_DB_FILE='%@' lein run reset-password %@", DBPath(), emailAddress);
#else
self.task.environment = @{@"MB_DB_FILE": DBPath()};
self.task.launchPath = JREPath();
self.task.arguments = @[@"-Djava.awt.headless=true", // this prevents the extra java icon from popping up in the dock when running
@"-Xverify:none", // disable bytecode verification for faster launch speed, not really needed here since JAR is packaged as part of signed .app
@"-jar", UberjarPath(),
@"reset-password", emailAddress];
NSLog(@"Launching ResetPasswordTask\nMB_DB_FILE='%@' %@ -jar %@ reset-password %@", DBPath(), JREPath(), UberjarPath(), emailAddress);
#endif
self.task.environment = @{@"MB_DB_FILE": DBPath()};
self.task.launchPath = JREPath();
self.task.arguments = @[@"-Djava.awt.headless=true", // this prevents the extra java icon from popping up in the dock when running
@"-Xverify:none", // disable bytecode verification for faster launch speed, not really needed here since JAR is packaged as part of signed .app
@"-jar", UberjarPath(),
@"reset-password", emailAddress];
NSLog(@"Launching ResetPasswordTask\nMB_DB_FILE='%@' %@ -jar %@ reset-password %@", DBPath(), JREPath(), UberjarPath(), emailAddress);
__weak ResetPasswordTask *weakSelf = self;
self.task.terminationHandler = ^(NSTask *task) {
NSLog(@"ResetPasswordTask terminated with status: %d", task.terminationStatus);
[weakSelf terminate];
dispatch_async(dispatch_get_main_queue(), ^{
if (!task.terminationStatus && weakSelf.output.length >= 38) { // should be of format <user-id>_<36-char-uuid>, e.g. "1_b20466b9-1f5b-488d-8ab6-5039107482f8"
successBlock(weakSelf.output);
} else {
errorBlock(weakSelf.output.length ? weakSelf.output : @"An unknown error has occured.");
}
// now restart the main Metabase task
NSLog(@"Reset password complete, restarting Metabase task...");
[[AppDelegate instance] startMetabaseTask];
});
};
[self.task launch];
});
}
- (void)readHandleDidRead:(NSString *)message {
NSLog(@"[PasswordResetTask] %@", message);
/// output comes back like "STATUS [[[message]]]"
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(?:(?:OK)||(?:FAIL))\\s+\\[\\[\\[(.+)\\]\\]\\]\\s*$" options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionAllowCommentsAndWhitespace error:NULL];
if (![regex numberOfMatchesInString:message options:0 range:NSMakeRange(0, message.length)]) return;
NSString *result = [regex stringByReplacingMatchesInString:message options:0 range:NSMakeRange(0, message.length) withTemplate:@"$1"];
if (result) {
self.output = result;

View File

@@ -22,7 +22,7 @@
:upload upload/upload!))
(defn- do-step! [step-name]
(let [thunk (or (get steps* (keyword step-name))
(let [thunk (or (get steps* (u/parse-as-keyword step-name))
(throw (ex-info (format "Invalid step name: %s" step-name)
{:found (set (keys steps*))})))]
(println (colorize/magenta (format "Running step %s..." step-name)))

View File

@@ -1,73 +0,0 @@
(ns metabase.junit
"Formatter for JUnit test output for CI."
(:require [clojure.pprint :as pp]
[clojure.string :as str]
[medley.core :as m]
[metabase.util :as u]
[pjstadig.print :as p]
[test-report-junit-xml.core :as junit-xml]
[test_report_junit_xml.shaded.clojure.data.xml :as xml]))
(defn- escape-unprintable-characters
[s]
(str/join (for [c s]
(if (and (Character/isISOControl c)
(not (Character/isWhitespace c)))
(format "&#%d;" (int c))
c))))
(defn- decolorize-and-escape
"Remove ANSI color escape sequences, then encode things as character entities as needed"
[s]
(-> s u/decolorize escape-unprintable-characters))
(defn- event-description [{:keys [file line context message]}]
(str
(format "%s:%d" file line)
(when (seq context)
(str "\n" (str/join " " (reverse context))))
(when message
(str "\n" message))))
(defn- print-expected [expected actual]
(p/rprint "expected: ")
(pp/pprint expected)
(p/rprint " actual: ")
(pp/pprint actual)
(p/clear))
(defn- result-output [{:keys [expected actual diffs message], :as event}]
(let [s (with-out-str
(println (event-description event))
;; this code is adapted from `pjstadig.util`
(p/with-pretty-writer
(fn []
(if (seq diffs)
(doseq [[actual [a b]] diffs]
(print-expected expected actual)
(p/rprint " diff:")
(if a
(do (p/rprint " - ")
(pp/pprint a)
(p/rprint " + "))
(p/rprint " + "))
(when b
(pp/pprint b))
(p/clear))
(print-expected expected actual)))))]
(decolorize-and-escape s)))
(defmulti format-result
{:arglists '([event])}
:type)
(defmethod format-result :default
[event]
(-> (#'junit-xml/format-result event)
(m/update-existing-in [:attrs :message] decolorize-and-escape)
(m/update-existing :content (comp xml/cdata decolorize-and-escape))))
(defmethod format-result :fail
[event]
{:tag :failure
:content (xml/cdata (result-output event))})

View File

@@ -2,8 +2,18 @@
set -euo pipefail
# switch to project root directory if we're not already there
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/clear-outdated-cpcaches.sh"
clear_outdated_cpcaches
source "./bin/prep.sh"
prep_deps
cd bin/build-mb
clojure -M -m build $@

View File

@@ -5,12 +5,22 @@ set -eo pipefail
driver="$1"
if [ ! "$driver" ]; then
echo "Usage: ./bin/build-driver.sh [driver]"
echo "Usage: ./bin/build-driver.sh <driver> [edition]"
exit -1
fi
# switch to project root directory if we're not already there
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/clear-outdated-cpcaches.sh"
clear_outdated_cpcaches
source "./bin/prep.sh"
prep_deps
cd bin/build-drivers
clojure -M -m build-driver "$driver"
clojure -M -m build-driver $@

View File

@@ -2,8 +2,18 @@
set -euo pipefail
# switch to project root directory if we're not already there
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/clear-outdated-cpcaches.sh"
clear_outdated_cpcaches
source "./bin/prep.sh"
prep_deps
cd bin/build-drivers
clojure -M -m build-drivers $@

View File

@@ -7,7 +7,7 @@ There are three main entrypoints. Shell script wrappers are provided for conveni
### `build-drivers`
Builds *all* drivers as needed. If drivers were recently built and no relevant source code changed, skips rebuild.
Builds *all* drivers as needed.
```
cd bin/build-drivers

View File

@@ -1,17 +1,29 @@
{:paths ["src"]
:deps
{common/common {:local/root "../common"}
cheshire/cheshire {:mvn/version "5.8.1"}
commons-codec/commons-codec {:mvn/version "1.14"}
hiccup/hiccup {:mvn/version "1.0.5"}
io.forward/yaml {:mvn/version "1.0.9"} ; don't upgrade to 1.0.10 -- doesn't work on Java 8 (!)
leiningen/leiningen {:mvn/version "2.9.5"} ; for parsing Leiningen projects
org.flatland/ordered {:mvn/version "1.5.9"} ; used by io.forward/yaml -- need the newer version
stencil/stencil {:mvn/version "0.5.0"}}
{common/common {:local/root "../common"}
com.github.seancorfield/depstar {:mvn/version "2.1.278"}
cheshire/cheshire {:mvn/version "5.8.1"}
commons-codec/commons-codec {:mvn/version "1.14"}
hiccup/hiccup {:mvn/version "1.0.5"}
io.forward/yaml {:mvn/version "1.0.9"} ; Don't upgrade yet, new version doesn't support Java 8 (see https://github.com/owainlewis/yaml/issues/37)
io.github.clojure/tools.build {:git/tag "v0.1.6", :git/sha "5636e61"}
org.clojure/tools.deps.alpha {:mvn/version "0.12.985"}
org.flatland/ordered {:mvn/version "1.5.9"} ; used by io.forward/yaml -- need the newer version
stencil/stencil {:mvn/version "0.5.0"}
;; local source
metabase/metabase-core {:local/root "../.."}
metabase/driver-modules {:local/root "../../modules/drivers"}}
:jvm-opts
["-XX:-OmitStackTraceInFastThrow"]
:aliases
{:test {:extra-paths ["test"]
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "209b64504cb3bd3b99ecfec7937b358a879f55c1"}}
:main-opts ["-m" "cognitect.test-runner"]}}}
{:dev
{:extra-paths ["test"]}
:test
{:extra-paths ["test"]
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "209b64504cb3bd3b99ecfec7937b358a879f55c1"}}
:main-opts ["-m" "cognitect.test-runner"]}}}

View File

@@ -7,4 +7,4 @@
(u/exit-when-finished-nonzero-on-exception
(when-not (seq driver)
(throw (ex-info "Usage: clojure -m build-driver <driver> [edition]" {})))
(build-driver/build-driver! (keyword driver) (or (keyword edition) :oss))))
(build-driver/build-driver! (u/parse-as-keyword driver) (or (u/parse-as-keyword edition) :oss))))

View File

@@ -2,12 +2,20 @@
"Entrypoint for `bin/build-drivers.sh`. Builds all drivers, if needed."
(:require [build-drivers.build-driver :as build-driver]
[clojure.java.io :as io]
[metabuild-common.core :as u]))
[metabuild-common.core :as u])
(:import java.io.File))
(defn- all-drivers []
(->> (.listFiles (io/file (u/filename u/project-root-directory "modules" "drivers")))
(filter #(.isDirectory %)) ;; watch for errant DS_Store files on os_x
(map (comp keyword #(.getName %)))))
(filter (fn [^File d] ;
(and
;; watch for errant DS_Store files on os_x
(.isDirectory d)
;; ignore stuff like .cpcache
(not (.isHidden d))
;; only consider a directory to be a driver if it contains a lein or deps build file
(.exists (io/file d "deps.edn")))))
(map (comp keyword #(.getName ^File %)))))
(defn build-drivers! [edition]
(let [edition (or edition :oss)]
@@ -19,4 +27,4 @@
(defn -main [& [edition]]
(u/exit-when-finished-nonzero-on-exception
(build-drivers! (keyword edition))))
(build-drivers! (u/parse-as-keyword edition))))

View File

@@ -1,168 +1,35 @@
(ns build-drivers.build-driver
"Logic for building a single driver."
(:require [build-drivers.checksum :as checksum]
[build-drivers.common :as c]
[build-drivers.install-driver-locally :as install-locally]
[build-drivers.metabase :as metabase]
[build-drivers.plugin-manifest :as manifest]
[build-drivers.strip-and-compress :as strip-and-compress]
(:require [build-drivers.common :as c]
[build-drivers.compile-source-files :as compile-source-files]
[build-drivers.copy-source-files :as copy-source-files]
[build-drivers.create-uberjar :as create-uberjar]
[build-drivers.verify :as verify]
[clojure.string :as str]
[colorize.core :as colorize]
[environ.core :as env]
[metabuild-common.core :as u]))
(defn- copy-driver!
"Copy the driver JAR from its `target/` directory to `resources/modules`/."
[driver]
(u/step (format "Copy %s driver uberjar from %s -> %s"
driver
(u/assert-file-exists (c/driver-jar-build-path driver))
(c/driver-jar-destination-path driver))
(u/delete-file-if-exists! (c/driver-jar-destination-path driver))
(u/create-directory-unless-exists! c/driver-jar-destination-directory)
(u/copy-file! (c/driver-jar-build-path driver)
(c/driver-jar-destination-path driver))))
(defn- clean-driver-artifacts!
"Delete built JARs of `driver`."
[driver]
(u/step (format "Delete %s driver artifacts" driver)
(u/delete-file-if-exists! (c/driver-target-directory driver))
(defn clean! [driver]
(u/step "Clean"
(u/delete-file-if-exists! (c/compiled-source-target-dir driver))
(u/delete-file-if-exists! (c/driver-jar-destination-path driver))))
(defn- clean-parents!
"Delete built JARs and local Maven installations of the parent drivers of `driver`."
[driver]
(u/step (format "Clean %s parent driver artifacts" driver)
(doseq [parent (manifest/parent-drivers driver)]
(clean-driver-artifacts! parent)
(install-locally/clean! parent)
(clean-parents! parent))))
(defn- clean-all!
"Delete all artifacts relating to building `driver`, including the driver JAR itself and installed
`metabase-core`/Metabase uberjar and any parent driver artifacts."
[driver]
(u/step "Clean all"
(clean-driver-artifacts! driver)
(clean-parents! driver)
(metabase/clean-metabase!)))
(declare build-driver!)
(defn- build-parents!
"Build and install to the local Maven repo any parent drivers of `driver` (e.g. `:google` is a parent of `:bigquery`).
The driver must be built as an uberjar so we can remove duplicate classes during the `strip-and-compress` stage; it
must be installed as a library so we can use it as a `:provided` dependency when building the child driver."
[driver edition]
(u/step (format "Build %s parent drivers" driver)
(when-let [parents (not-empty (manifest/parent-drivers driver))]
(doseq [parent parents]
(build-parents! parent edition)
(install-locally/install-locally! parent edition)
(build-driver! parent edition))
(u/announce "%s parents built successfully." driver))))
(defn- build-uberjar! [driver edition]
(u/step (format "Build %s uberjar (%s edition)" driver edition)
(u/delete-file-if-exists! (c/driver-target-directory driver))
(u/sh {:dir (c/driver-project-dir driver)} "lein" "clean")
(u/sh {:dir (c/driver-project-dir driver)
:env {"LEIN_SNAPSHOTS_IN_RELEASE" "true"
"HOME" (env/env :user-home)
"PATH" (env/env :path)
"JAVA_HOME" (env/env :java-home)}}
"lein" "with-profile" (format "+%s" (name edition)) "uberjar")
(strip-and-compress/strip-and-compress-uberjar! driver)
(u/announce "%s uberjar (%s edition) built successfully." driver edition)))
(defn- build-and-verify!
"Build `driver` and verify the built JAR. This function ignores any existing artifacts and will always rebuild."
[driver edition]
{:pre [(#{:oss :ee} edition)]}
(u/step (str/join " " [(colorize/green "Build")
(colorize/yellow driver)
(colorize/green "driver")
(colorize/yellow (format "(%s edition)" edition))])
(clean-driver-artifacts! driver)
(u/step (format "Build %s driver (%s edition) prerequisites if needed" driver edition)
(metabase/build-metabase!)
(build-parents! driver edition))
(build-uberjar! driver edition)
(copy-driver! driver)
(verify/verify-driver driver)
(u/step (format "Save checksum for %s driver (%s edition) to %s"
driver edition (c/driver-checksum-filename driver))
(let [filename (c/driver-checksum-filename driver)
checksum (checksum/driver-checksum driver edition)]
(spit filename checksum)
(u/announce "Wrote checksum %s to file %s" (pr-str checksum) filename)))))
(defn- driver-checksum-matches?
"Check whether the saved checksum for the driver from the last build is the same as the current one. If so, we don't
need to build again. This checksum is based on driver sources as well as the checksums for Metabase sources and
parent drivers."
[driver edition]
(u/step (format "Determine whether %s driver (%s edition) source files have changed since last build" driver edition)
(let [existing-checksum (checksum/existing-driver-checksum driver)]
(cond
(not existing-checksum)
(do
(u/announce "No previous checksum. Need to rebuild driver")
false)
(= existing-checksum (checksum/driver-checksum driver edition))
(do
(u/announce "Checksum is the same. Do not need to rebuild driver.")
true)
:else
(do
(u/announce "Checksum is different. Need to rebuild driver.")
false)))))
(defn build-driver!
"Build `driver`, if needed."
[driver edition]
{:pre [(#{:oss :ee nil} edition)]}
(let [edition (or edition :oss)]
(u/step (str/join " " [(colorize/green "Build")
(colorize/yellow driver)
(colorize/green "driver")
(colorize/yellow (format "(%s edition)" edition))
(colorize/green "if needed")])
;; When we build a driver, we save a checksum of driver source code + metabase source code + parent drivers
;; alongside the built driver JAR. The next time this script is called, we recalculate that checksum -- if the
;; current checksum matches the saved one associated with the built driver JAR, we do not need to rebuild the
;; driver. If anything relevant has changed, we have to rebuild the driver.
(if (driver-checksum-matches? driver edition)
;; even if we're not rebuilding the driver, copy the artifact from `modules/drivers/<driver>/target/uberjar/`
;; to `resources/modules` so we can be sure we have the most up-to-date version there.
(try
(copy-driver! driver)
(verify/verify-driver driver)
;; if verification fails, delete all the existing artifacts and just rebuild the driver from scratch.
(catch Throwable e
(u/error "Error verifying existing driver:\n%s" (pr-str e))
(u/announce "Deleting existing driver artifacts and rebuilding.")
(clean-driver-artifacts! driver)
(build-driver! driver edition)))
;; if checksum does not match, build and verify the driver
(try
(build-and-verify! driver edition)
;; if building fails, clean everything, including metabase-core, the metabase uberjar, and parent
;; dependencies, *then* retry.
(catch Throwable e
(u/announce "Cleaning ALL and retrying...")
(clean-all! driver)
(try
(build-and-verify! driver edition)
;; if building the driver failed again, even after cleaning, delete anything that was built and then
;; give up.
(catch Throwable e
(u/safe-println (colorize/red (format "Failed to build %s driver." driver)))
(clean-driver-artifacts! driver)
(throw e))))))
;; if we make it this far, we've built the driver successfully.
(u/announce "Success."))))
;; 1-arity that takes just a map is mean for use directly with clojure -X
([{:keys [driver edition], :as options}]
(build-driver! driver edition (dissoc options :driver :edition)))
([driver edition]
(build-driver! driver edition nil))
([driver edition {:keys [project-dir target-dir], :as options}]
(let [edition (or edition :oss)
start-time-ms (System/currentTimeMillis)]
(binding [c/*driver-project-dir* (or project-dir
c/*driver-project-dir*)
c/*target-directory* (or target-dir
c/*target-directory*)]
(u/step (format "Build driver %s (edition = %s, options = %s)" driver edition (pr-str options))
(clean! driver)
(copy-source-files/copy-source-files! driver edition)
(compile-source-files/compile-clojure-source-files! driver edition)
(create-uberjar/create-uberjar! driver edition)
(u/announce "Built %s driver in %d ms." driver (- (System/currentTimeMillis) start-time-ms))
(verify/verify-driver driver))))))

View File

@@ -1,82 +0,0 @@
(ns build-drivers.checksum
"Shared code for calculating and reading hex-encoded MD5 checksums for relevant files."
(:require [build-drivers.common :as c]
[build-drivers.plugin-manifest :as manifest]
[clojure.java.io :as io]
[clojure.string :as str]
[colorize.core :as colorize]
[metabuild-common.core :as u])
(:import org.apache.commons.codec.digest.DigestUtils))
(defn checksum-from-file
"Read a saved MD5 hash checksum from a file."
[filename]
(u/step (format "Read saved checksum from %s" filename)
(let [file (io/file filename)]
(if-not (.exists file)
(u/announce "%s does not exist" filename)
(or (when-let [[checksum-line] (not-empty (str/split-lines (slurp file)))]
(when-let [[_ checksum-hex] (re-matches #"(^(?:\w+-)?[0-9a-f]{32}).*$" checksum-line)]
(u/safe-println (format "Saved checksum is %s" (colorize/cyan checksum-hex)))
checksum-hex))
(u/error (format "Checksum file %s exists, but does not contain a valid checksum" filename)))))))
;;; -------------------------------------------- Metabase source checksum --------------------------------------------
(defn- metabase-source-paths []
(sort
(cons
(u/filename u/project-root-directory "project.clj")
(mapcat (fn [dir]
(try
(u/find-files dir (fn [s]
(or (str/ends-with? s ".clj")
(str/ends-with? s ".cljc"))))
(catch Throwable _
[])))
[(u/filename u/project-root-directory "src")
(u/filename u/project-root-directory "enterprise" "backend" "src")
(u/filename u/project-root-directory "shared" "src")]))))
(defn metabase-source-checksum
"Checksum of Metabase backend source files and `project.clj`."
^String []
(let [paths (metabase-source-paths)]
(u/step (format "Calculate checksum for %d Metabase source files" (count paths))
(let [checksum (DigestUtils/md5Hex (str/join (map slurp paths)))]
(u/safe-println (format "Current checksum of Metabase files is %s" (colorize/cyan checksum)))
checksum))))
;;; ---------------------------------------------- Driver source files -----------------------------------------------
(defn existing-driver-checksum
"Checksum from the relevant sources from last time we built `driver`."
[driver]
(checksum-from-file (c/driver-checksum-filename driver)))
(defn- driver-source-paths
"Returns sequence of the source filenames for `driver`."
[driver]
(u/find-files (c/driver-project-dir driver)
(fn [path]
(or (and (str/ends-with? path ".clj")
(not (str/starts-with? path (u/filename (c/driver-project-dir driver) "test"))))
(str/ends-with? path ".yaml")))))
(defn driver-checksum
"The driver checksum is based on a checksum of all the driver source files (`.clj` files and the plugin manifest YAML
file) combined with the checksums for `metabase-core` *and* the parent drivers. After building a driver, we save
this checksum. Next time the script is ran, we recalculate the checksum to determine whether anything relevant has
changed -- if it has, and the current checksum doesn't match the saved one, we need to rebuild the driver."
^String [driver edition]
(let [source-paths (driver-source-paths driver)]
(u/step (format "Calculate checksum for %d files: %s ..." (count source-paths) (first source-paths))
(let [checksum (str
(c/edition-checksum-prefix driver edition)
(DigestUtils/md5Hex (str/join (concat [(metabase-source-checksum)]
(map #(driver-checksum % edition)
(manifest/parent-drivers driver))
(map slurp (driver-source-paths driver))))))]
(u/safe-println (format "Current checksum of %s driver (%s edition) is %s" driver edition (colorize/cyan checksum)))
checksum))))

View File

@@ -1,77 +1,46 @@
(ns build-drivers.common
"Shared constants and functions related to source and artifact paths used throughout this code."
(:require [environ.core :as env]
[leiningen.core.project :as lein.project]
(:require [clojure.java.io :as io]
[clojure.tools.deps.alpha :as deps]
[metabuild-common.core :as u]))
(def ^String maven-repository-path
(u/filename (env/env :user-home) ".m2" "repository"))
(def ^:dynamic *driver-project-dir* nil)
;;; -------------------------------------------------- Driver Paths --------------------------------------------------
(def ^:dynamic *target-directory* nil)
(defn driver-project-dir
"e.g. \"/home/cam/metabase/modules/drivers/redshift\""
[driver]
(u/filename u/project-root-directory "modules" "drivers" (name driver)))
^String [driver]
(or *driver-project-dir*
(u/filename u/project-root-directory "modules" "drivers" (name driver))))
(defn driver-jar-name
"e.g. \"redshift.metabase-driver.jar\""
[driver]
^String [driver]
(format "%s.metabase-driver.jar" (name driver)))
(defn driver-target-directory
[driver]
(u/filename (driver-project-dir driver) "target"))
(defn driver-jar-build-path
"e.g. \"/home/cam/metabase/modules/drivers/redshift/target/uberjar/redshift.metabase-driver.jar\""
[driver]
(u/filename (driver-target-directory driver) "uberjar" (driver-jar-name driver)))
(def ^String driver-jar-destination-directory
(u/filename u/project-root-directory "resources" "modules"))
(defn driver-jar-destination-directory ^String []
(or *target-directory*
(u/filename u/project-root-directory "resources" "modules")))
(defn driver-jar-destination-path
"e.g. \"/home/cam/metabase/resources/modules/redshift.metabase-driver.jar\""
^String [driver]
(u/filename driver-jar-destination-directory (driver-jar-name driver)))
(u/filename (driver-jar-destination-directory) (driver-jar-name driver)))
(defn- lein-project-map
"Read the `project.clj` file for `driver` and return it as a map."
[driver & profiles]
(let [project-filename (u/assert-file-exists (u/filename (driver-project-dir driver) "project.clj"))]
(lein.project/read project-filename profiles)))
(defn compiled-source-target-dir [driver]
(u/filename (driver-project-dir driver) "target" "jar"))
(defn has-edition-profile?
"Whether `driver` has a separate profile for `edition`, e.g. `:ee`. This means this version of the driver is different
from other versions of the driver (e.g. :ee Oracle ships with the non-free Oracle JDBC driver, :oss does not)."
[driver edition]
(let [has-profile? (boolean
(contains? (:profiles (lein-project-map driver)) edition))]
(u/safe-println (format "%s %s have a separate %s profile" driver (if has-profile? "DOES" "DOES NOT") edition))
has-profile?))
(defn driver-edn-filename [driver]
(u/filename (driver-project-dir driver) "deps.edn"))
(defn edition-checksum-prefix
"Prefix to add to checksums of driver for `edition` -- normally this is `nil`, but if the driver has a specific
profile for `edition` (e.g. Oracle has a different profile for `:ee` builds) this is a prefix to make the checksum
different from the normal one."
[driver edition]
(when (has-edition-profile? driver edition)
(format "%s-" (name edition))))
(defn- ->absolute [driver path]
(if (u/absolute? path)
path
(u/filename (driver-project-dir driver) path)))
(defn driver-checksum-filename
"e.g. \"/home/cam/metabase/modules/drivers/redshift/target/checksum.md5\""
[driver]
(u/filename (driver-project-dir driver) "target" "checksum.md5"))
(defn driver-plugin-manifest-filename
"e.g. \"/home/cam/metabase/modules/drivers/bigquery/resources/plugin-manifest.yaml\""
[driver]
(u/filename (driver-project-dir driver) "resources" "metabase-plugin.yaml"))
;;; ------------------------------------------ Metabase Local Install Paths ------------------------------------------
(def ^String metabase-uberjar-path
"e.g. \"home/cam/metabase/target/uberjar/metabase.jar\""
(u/filename u/project-root-directory "target" "uberjar" "metabase.jar"))
(defn driver-edn [driver edition]
(let [edn (deps/merge-edns ((juxt :root-edn :project-edn) (deps/find-edn-maps (driver-edn-filename driver))))
combined (deps/combine-aliases edn #{edition})]
(-> (deps/tool edn combined)
;; make sure :paths are absolute
(update :paths (partial mapv (partial ->absolute driver))))))

View File

@@ -0,0 +1,54 @@
(ns build-drivers.compile-source-files
(:require [build-drivers.common :as c]
[clojure.java.io :as io]
[clojure.tools.namespace.dependency :as ns.deps]
[clojure.tools.namespace.find :as ns.find]
[clojure.tools.namespace.parse :as ns.parse]
[metabuild-common.core :as u]))
(defn driver-source-paths [driver edition]
(let [dirs (:paths (c/driver-edn driver edition))]
(assert (every? u/absolute? dirs)
(format "All dirs should be absolute, got: %s" (pr-str dirs)))
dirs))
(defn- dependencies-graph
"Return a `clojure.tools.namespace` dependency graph of namespaces named by `ns-symbol`."
[ns-decls]
(reduce
(fn [graph ns-decl]
(let [ns-symbol (ns.parse/name-from-ns-decl ns-decl)]
(reduce
(fn [graph dep]
(ns.deps/depend graph ns-symbol dep))
graph
(ns.parse/deps-from-ns-decl ns-decl))))
(ns.deps/graph)
ns-decls))
;; topologically sort the namespaces so we don't end up with weird compilation issues.
(defn source-path-namespaces [source-paths]
(let [ns-decls (mapcat
(comp ns.find/find-ns-decls-in-dir io/file)
source-paths)
ns-symbols (set (map ns.parse/name-from-ns-decl ns-decls))]
(->> (dependencies-graph ns-decls)
ns.deps/topo-sort
(filterv ns-symbols))))
(defn compile-clojure-source-files! [driver edition]
(u/step "Compile clojure source files"
(let [start-time-ms (System/currentTimeMillis)
source-paths (driver-source-paths driver edition)
target-dir (c/compiled-source-target-dir driver)
namespaces (source-path-namespaces source-paths)]
(u/announce "Compiling Clojure source files in %s to %s" (pr-str source-paths) target-dir)
(u/create-directory-unless-exists! target-dir)
(u/announce "Compiling namespaces %s" (pr-str namespaces))
(binding [*compile-path* target-dir]
(doseq [a-namespace namespaces]
(#'clojure.core/serialized-require a-namespace)
(compile a-namespace)))
(u/announce "Compiled %d namespace(s) in %d ms."
(count namespaces)
(- (System/currentTimeMillis) start-time-ms)))))

View File

@@ -0,0 +1,18 @@
(ns build-drivers.copy-source-files
(:require [build-drivers.common :as c]
[clojure.tools.build.api :as build]
[metabuild-common.core :as u]))
(defn copy-source-files! [driver edition]
(u/step (format "Copy %s source files" driver)
(let [start-time-ms (System/currentTimeMillis)
dirs (:paths (c/driver-edn driver edition))]
(assert (every? u/absolute? dirs)
(format "All dirs should be absolute, got: %s" (pr-str dirs)))
(u/announce "Copying files in %s" (pr-str dirs))
(build/copy-dir
{:src-dirs dirs
:target-dir (c/compiled-source-target-dir driver)})
(u/announce "Copied files in %d directories in %d ms."
(count dirs)
(- (System/currentTimeMillis) start-time-ms)))))

View File

@@ -0,0 +1,79 @@
(ns build-drivers.create-uberjar
(:require [build-drivers.common :as c]
[clojure.java.io :as io]
[clojure.tools.deps.alpha :as deps]
[clojure.tools.deps.alpha.util.dir :as deps.dir]
[colorize.core :as colorize]
[hf.depstar.api :as depstar]
[metabuild-common.core :as u]))
(defn driver-basis [driver edition]
(let [edn (c/driver-edn driver edition)]
(binding [deps.dir/*the-dir* (io/file (c/driver-project-dir driver))]
(deps/calc-basis edn))))
(defonce metabase-core-edn
(deps/merge-edns
((juxt :root-edn :project-edn)
(deps/find-edn-maps (u/filename u/project-root-directory "deps.edn")))))
(defonce metabase-core-basis
(binding [deps.dir/*the-dir* (io/file u/project-root-directory)]
(deps/calc-basis metabase-core-edn)))
(defonce metabase-core-provided-libs
(set (keys (:libs metabase-core-basis))))
(defn- driver-parents [driver edition]
(when-let [parents (not-empty (:metabase.driver/parents (c/driver-edn driver edition)))]
(u/announce "Driver has parent drivers %s" (pr-str parents))
parents))
(defn- parent-provided-libs [driver edition]
(into {} (for [parent (driver-parents driver edition)
lib (keys (:libs (driver-basis parent edition)))]
[lib parent])))
(defn- provided-libs
"Return a map of lib -> provider, where lib is a symbol like `com.h2database/h2` and provider is either
`metabase-core` or the parent driver that provided that lib."
[driver edition]
(into (parent-provided-libs driver edition)
(map (fn [lib]
[lib 'metabase-core]))
metabase-core-provided-libs))
(defn remove-provided-libs [basis driver edition]
(let [provided-lib->provider (into {}
(filter (fn [[lib]]
(get-in basis [:libs lib])))
(provided-libs driver edition))]
;; log which libs we're including and excluding.
(doseq [lib (sort (keys (:libs basis)))]
(u/announce (if-let [provider (get provided-lib->provider lib)]
(format "SKIP %%45s (provided by %s)" provider)
"INCLUDE %s")
(colorize/yellow lib)))
;; now remove the provide libs from `:classpath`, `:classpath-roots`, and `:libs`
(let [provided-libs-set (into #{} (keys provided-lib->provider))
provided-paths-set (into #{} (mapcat #(get-in basis [:libs % :paths])) provided-libs-set)]
(-> basis
(update :classpath-roots #(vec (remove provided-paths-set %)))
(update :libs #(into {} (remove (fn [[lib]] (provided-libs-set lib))) %))
(update :classpath #(into {} (remove (fn [[path]] (provided-paths-set path))) %))))))
(defn- uberjar-basis [driver edition]
(u/step "Determine which dependencies to include"
(-> (driver-basis driver edition)
(remove-provided-libs driver edition)
;; remove unneeded keys so Depstar doesn't try to do anything clever and resolve them
(dissoc :deps :aliases :mvn/repos))))
(defn create-uberjar! [driver edition]
(u/step (format "Write %s %s uberjar -> %s" driver edition (c/driver-jar-destination-path driver))
(let [start-time-ms (System/currentTimeMillis)]
(depstar/uber
{:class-dir (c/compiled-source-target-dir driver)
:uber-file (c/driver-jar-destination-path driver)
:basis (uberjar-basis driver edition)})
(u/announce "Created uberjar in %d ms." (- (System/currentTimeMillis) start-time-ms)))))

View File

@@ -1,49 +0,0 @@
(ns build-drivers.install-driver-locally
"Logic related to installing a driver as a library in the local Maven repository so it can be used as a dependency
when building descandant drivers. Right now this is only used for `:google`, which is used by `:bigquery` and
`:googleanalytics`."
(:require [build-drivers.checksum :as checksum]
[build-drivers.common :as c]
[colorize.core :as colorize]
[metabuild-common.core :as u]))
(defn- local-install-path [driver]
(u/filename c/maven-repository-path "metabase" (format "%s-driver" (name driver))))
(defn- local-install-checksum-filename [driver edition]
(u/filename (local-install-path driver) (str (c/edition-checksum-prefix driver edition) "checksum.md5")))
(defn clean!
"Delete local Maven installation of the library version of `driver`."
[driver]
(u/step (format "Deleting existing Maven installation of %s driver" driver)
(u/delete-file-if-exists! (local-install-path driver))))
(defn- local-install-checksum-matches?
"After installing the library version of `driver`, we save a checksum based on its sources; next time we call
`install-locally!`, we can recalculate the checksum; if the saved one matches the current one, we do not need to
reinstall."
[driver edition]
(u/step "Determine whether %s driver source files have changed since last local install"
(let [existing-checksum (checksum/checksum-from-file (local-install-checksum-filename driver edition))
current-checksum (checksum/driver-checksum driver edition)
same? (= existing-checksum current-checksum)]
(u/announce (if same?
"Checksum is the same. Do not need to rebuild driver."
"Checksum is different. Need to rebuild driver."))
same?)))
(defn install-locally!
"Install `driver` as a library in the local Maven repository IF NEEDED so descendant drivers can use it as a
`:provided` dependency when building. E.g. before building `:bigquery` we need to install `:google` as a library
locally."
[driver edition]
{:pre [(keyword? driver)]}
(u/step (str (colorize/green "Install ") (colorize/yellow driver) (colorize/green " driver to local Maven repo if needed"))
(if (local-install-checksum-matches? driver edition)
(u/announce "Already installed locally.")
(u/step (str (colorize/green "Install ") (colorize/yellow driver) (colorize/green " driver to local Maven repo"))
(u/sh {:dir (c/driver-project-dir driver)} "lein" "clean")
(u/sh {:dir (c/driver-project-dir driver)} "lein" "install-for-building-drivers")
(u/step (format "Save checksum to %s" driver (local-install-checksum-filename driver edition))
(spit (local-install-checksum-filename driver edition) (checksum/driver-checksum driver edition)))))))

View File

@@ -1,88 +0,0 @@
(ns build-drivers.metabase
"Code for installing the main Metabase project as a library (`metabase-core`) in the local Maven repository, and for
building a Metabase uberjar. Both are needed when building drivers."
(:require [build-drivers
[checksum :as checksum]
[common :as c]]
[metabuild-common.core :as u]))
(def ^String ^:private uberjar-checksum-path
(str c/metabase-uberjar-path ".md5"))
(def ^String ^:private metabase-core-install-path
(u/filename c/maven-repository-path "metabase-core"))
(def ^String ^:private metabase-core-checksum-path
(u/filename metabase-core-install-path "checksum.md5"))
(defn metabase-core-checksum-matches? []
(u/step "Determine whether Metabase source files checksum has changed since last install of metabase-core"
(let [existing-checksum (checksum/checksum-from-file metabase-core-checksum-path)
current-checksum (checksum/metabase-source-checksum)
same? (= existing-checksum current-checksum)]
(u/announce (if same?
"Checksum is the same. Do not need to reinstall metabase-core locally."
"Checksum is different. Need to reinstall metabase-core locally."))
same?)))
(defn- delete-metabase-core-install! []
(u/step "Delete local installation of metabase-core"
(u/delete-file-if-exists! metabase-core-install-path)))
(defn- install-metabase-core! []
(u/step "Install metabase-core locally if needed"
(if (metabase-core-checksum-matches?)
(u/announce "Up-to-date metabase-core already installed to local Maven repo")
(do
(delete-metabase-core-install!)
(u/sh {:dir u/project-root-directory} "lein" "clean")
(u/sh {:dir u/project-root-directory} "lein" "install-for-building-drivers")
(u/step "Save checksum for local installation of metabase-core"
(spit metabase-core-checksum-path (checksum/metabase-source-checksum)))
(u/announce "metabase-core dep installed to local Maven repo successfully.")))))
(defn uberjar-checksum-matches?
"After installing/building Metabase we save a MD5 hex checksum of Metabase backend source files (including
`project.clj`). The next time we run `build-metabase!`, if the checksums have changed we know we need to
rebuild/reinstall."
[]
(u/step "Determine whether Metabase source files checksum has changed since last build of uberjar"
(let [existing-checksum (checksum/checksum-from-file uberjar-checksum-path)
current-checksum (checksum/metabase-source-checksum)
same? (= existing-checksum current-checksum)]
(u/announce (if same?
"Checksum is the same. Do not need to rebuild Metabase uberjar."
"Checksum is different. Need to rebuild Metabase uberjar."))
same?)))
(defn- delete-metabase-uberjar! []
(u/step "Delete exist metabase uberjar"
(u/delete-file-if-exists! (u/filename u/project-root-directory "target"))))
(defn- build-metabase-uberjar! []
(u/step "Build Metabase uberjar if needed"
(if (uberjar-checksum-matches?)
(u/announce "Update-to-date Metabase uberjar already built")
(do
(delete-metabase-uberjar!)
(u/sh {:dir u/project-root-directory} "lein" "clean")
(u/sh {:dir u/project-root-directory} "lein" "uberjar")
(u/step "Save checksum for Metabase uberar"
(spit uberjar-checksum-path (checksum/metabase-source-checksum)))
(u/announce "Metabase uberjar built successfully")))))
(defn clean-metabase!
"Delete local Maven repository installation of the `metabase-core` library and delete the built Metabase uberjar."
[]
(u/step "Clean local Metabase deps"
(delete-metabase-core-install!)
(delete-metabase-uberjar!)))
(defn build-metabase!
"Install `metabase-core` as a library in the local Maven repo, and build the Metabase uberjar IF NEEDED. We need to do
both because `metabase-core` is used as a dependency for drivers, and the Metabase uberjar is checked to make sure
we don't ship duplicate classes in the driver JAR (as part of the `strip-and-compress` stage.)"
[]
(u/step "Build metabase-core and install locally"
(install-metabase-core!)
(build-metabase-uberjar!)))

View File

@@ -1,55 +0,0 @@
(ns build-drivers.plugin-manifest
"Code for reading the YAML plugin manifest for a driver. "
(:require [build-drivers.common :as c]
[metabuild-common.core :as u]
[yaml.core :as yaml]))
(defn- plugin-manifest
"Read `driver` plugin manifest and return a map."
[driver]
{:post [(map? %)]}
(yaml/from-file (u/assert-file-exists (c/driver-plugin-manifest-filename driver))))
(defn- driver-declarations [manifest]
;; driver plugin manifest can have a single `:driver`, or multiple drivers, e.g. Spark SQL which also has the
;; `:hive-like` abstract driver
(let [{driver-declaration :driver} manifest]
(if (map? driver-declaration)
[driver-declaration]
driver-declaration)))
(defn- declared-drivers
"Sequence of all drivers declared in a plugin `manifest`. Usually only one driver, except for Spark SQL which declares
both `:hive-like` and `:sparksql`."
[manifest]
(map (comp keyword :name) (driver-declarations manifest)))
(def ^:private metabase-core-drivers
"Drivers that ship as part of the core Metabase project (as opposed to a plugin) and thus do not need to be built."
#{:sql
:sql-jdbc
:mysql
:h2
:postgres})
(defn parent-drivers
"Get the parent drivers of a driver for purposes of building a driver. Excludes drivers that ship as part of
`metabase-core`, since we don't need to worry about building those.
e.g.
(parent-drivers :googleanalytics) ;-> (:google)"
[driver]
(let [manifest (plugin-manifest driver)
declared (declared-drivers manifest)]
(or (not-empty
(for [{parent-declaration :parent} (driver-declarations manifest)
:let [parents (if (string? parent-declaration)
[parent-declaration]
parent-declaration)]
parent parents
:let [parent (keyword parent)]
:when (and (not (contains? (set declared) parent))
(not (contains? metabase-core-drivers parent)))]
parent))
(u/announce "%s does not have any parents" driver))))

View File

@@ -1,65 +0,0 @@
(ns build-drivers.strip-and-compress
(:require [build-drivers.common :as c]
[build-drivers.plugin-manifest :as manifest]
[metabuild-common.core :as u])
(:import java.io.FileOutputStream
[java.util.zip ZipEntry ZipFile ZipOutputStream]
org.apache.commons.io.IOUtils))
(def ^:private files-to-always-include
"Files to always include regardless of whether they are present in blacklist JAR."
#{"metabase-plugin.yaml"})
(defn- jar-contents
"Get a set of all files in a JAR that we should strip out from the driver JAR -- either the Metabase uberjar itself or
a parent driver JAR."
[^String jar-path]
(with-open [zip-file (ZipFile. jar-path)]
(set
(for [^ZipEntry zip-entry (enumeration-seq (.entries zip-file))
:let [filename (str zip-entry)]
:when (not (files-to-always-include filename))]
filename))))
(defn- strip-classes! [^String driver-jar-path ^String blacklist-jar-path]
(u/step (format "Remove classes from %s that are present in %s and recompress" driver-jar-path blacklist-jar-path)
(let [jar-contents (jar-contents blacklist-jar-path)
temp-driver-jar-path "/tmp/driver.jar"
wrote (atom 0)
skipped (atom 0)]
(u/delete-file-if-exists! temp-driver-jar-path)
(with-open [source-zip (ZipFile. (u/assert-file-exists driver-jar-path))
os (doto (ZipOutputStream. (FileOutputStream. temp-driver-jar-path))
(.setMethod ZipOutputStream/DEFLATED)
(.setLevel 9))]
(doseq [^ZipEntry entry (enumeration-seq (.entries source-zip))]
(if (jar-contents (str entry))
(swap! skipped inc)
(with-open [is (.getInputStream source-zip entry)]
(.putNextEntry os (ZipEntry. (.getName entry)))
(IOUtils/copy is os)
(.closeEntry os)
(swap! wrote inc)))))
(u/announce (format "Done. wrote: %d skipped: %d" @wrote @skipped))
(u/safe-println (format "Original size: %s" (u/format-bytes (u/file-size driver-jar-path))))
(u/safe-println (format "Stripped/extra-compressed size: %s" (u/format-bytes (u/file-size temp-driver-jar-path))))
(u/step "replace the original source JAR with the stripped one"
(u/delete-file-if-exists! driver-jar-path)
(u/copy-file! temp-driver-jar-path driver-jar-path)))))
(defn strip-and-compress-uberjar!
"Remove any classes in compiled `driver` that are also present in the Metabase uberjar or parent drivers. The classes
will be available at runtime, and we don't want to make things unpredictable by including them more than once in
different drivers.
This is only needed because `lein uberjar` does not seem to reliably exclude classes from `:provided` Clojure
dependencies like `metabase-core` and the parent drivers."
[driver]
(u/step (str (format "Strip out any classes in %s driver JAR found in core Metabase uberjar or parent JARs" driver)
" and recompress with higher compression ratio")
(let [driver-jar-path (u/assert-file-exists (c/driver-jar-build-path driver))]
(u/step "strip out any classes also found in the core Metabase uberjar"
(strip-classes! driver-jar-path (u/assert-file-exists c/metabase-uberjar-path)))
(u/step "remove any classes also found in any of the parent JARs"
(doseq [parent (manifest/parent-drivers driver)]
(strip-classes! driver-jar-path (u/assert-file-exists (c/driver-jar-build-path parent))))))))

View File

@@ -19,6 +19,16 @@
(u/announce "Driver init class file found.")
(throw (ex-info (format "Driver verification failed: init class file %s not found" driver-init-class-filename) {}))))))
(defn- verify-does-not-have-clojure-core [driver]
(let [jar-filename (c/driver-jar-destination-path driver)]
(u/step (format "Check %s does not contain Clojure core classes" jar-filename)
(doseq [file ["clojure/spec/alpha__init.class"
"clojure/core__init.class"
"clojure/core.clj"]]
(when (jar-contains-file? jar-filename file)
(throw (ex-info (format "Driver verification failed: driver contains compiled Clojure core file %s" file)
{:file file})))))))
(defn- verify-has-plugin-manifest [driver]
(let [jar-filename (c/driver-jar-destination-path driver)]
(u/step (format "Check %s contains metabase-plugin.yaml" jar-filename)
@@ -34,4 +44,5 @@
(u/assert-file-exists (c/driver-jar-destination-path driver))
(verify-has-init-class driver)
(verify-has-plugin-manifest driver)
(verify-does-not-have-clojure-core driver)
(u/announce (format "%s driver verification successful." driver))))

View File

@@ -7,4 +7,4 @@
(u/exit-when-finished-nonzero-on-exception
(when-not (seq driver)
(throw (ex-info "Usage: clojure -m verify-driver <driver>" {})))
(verify/verify-driver (keyword driver))))
(verify/verify-driver (u/parse-as-keyword driver))))

View File

@@ -15,19 +15,11 @@
(build-driver/build-driver! :oracle :oss)
(is (.exists (java.io.File. (jar-path))))
(testing "JAR should not contain the JDBC driver classes"
(is (not (jar-contains-jdbc-classes?))))
(testing "Wouldn't need to rebuild :oss version of the driver"
(is (#'build-driver/driver-checksum-matches? :oracle :oss)))
(testing "WOULD need to build :ee version of the driver"
(is (not (#'build-driver/driver-checksum-matches? :oracle :ee))))))
(is (not (jar-contains-jdbc-classes?))))))
(deftest build-ee-driver-test
(testing "We should be able to build an EE driver"
(build-driver/build-driver! :oracle :ee)
(is (.exists (java.io.File. (jar-path))))
(testing "JAR *should* contain the JDBC driver classes"
(is (jar-contains-jdbc-classes?)))
(testing "Wouldn't need to rebuild :ee version of the driver"
(is (#'build-driver/driver-checksum-matches? :oracle :ee)))
(testing "WOULD need to build :oss version of the driver"
(is (not (#'build-driver/driver-checksum-matches? :oracle :oss))))))
(is (jar-contains-jdbc-classes?)))))

View File

@@ -1,11 +0,0 @@
(ns build-drivers.checksum-test
(:require [build-drivers.checksum :as checksum]
[clojure.test :refer :all]))
(deftest driver-checksum-test
(testing "OSS/EE checksums should be the same for drivers that don't have different oss/ee profiles"
(is (= (checksum/driver-checksum :sqlite :oss)
(checksum/driver-checksum :sqlite :ee))))
(testing "OSS/EE checksums should be different for drivers that have different oss/ee profiles"
(is (not= (checksum/driver-checksum :oracle :oss)
(checksum/driver-checksum :oracle :ee)))))

View File

@@ -1,15 +0,0 @@
(ns build-drivers.common-test
(:require [build-drivers.common :as c]
[clojure.test :refer :all]))
(deftest has-edition-profile?-test
(testing :ee
(is (= true
(c/has-edition-profile? :oracle :ee)))
(is (= false
(c/has-edition-profile? :sqlite :ee))))
(testing :oss
(is (= false
(c/has-edition-profile? :oracle :oss)))
(is (= false
(c/has-edition-profile? :sqlite :oss)))))

View File

@@ -1,16 +0,0 @@
(ns build-drivers.install-driver-locally-test
(:require [build-drivers.install-driver-locally :as install-driver-locally]
[clojure.string :as str]
[clojure.test :refer :all]))
(deftest local-install-checksum-filename-test
(is (str/ends-with?
(#'install-driver-locally/local-install-checksum-filename :oracle :ee)
".m2/repository/metabase/oracle-driver/ee-checksum.md5"))
(is (str/ends-with?
(#'install-driver-locally/local-install-checksum-filename :oracle :oss)
".m2/repository/metabase/oracle-driver/checksum.md5"))
(doseq [edition [:oss :ee]]
(is (str/ends-with?
(#'install-driver-locally/local-install-checksum-filename :sqlite edition)
".m2/repository/metabase/sqlite-driver/checksum.md5"))))

View File

@@ -7,7 +7,7 @@ VERSION_PROPERTY_NAME="src_hash"
source-hash() {
# hash all the files that might change a backend-only uberjar build (for integration tests)
(
find src project.clj resources/sample-dataset.db.mv.db -type f -print0 | xargs -0 shasum ;
find src deps.edn resources/sample-dataset.db.mv.db -type f -print0 | xargs -0 shasum ;
find resources -type f \( -iname \*.clj -o -iname \*.edn -o -iname \*.yaml -o -iname \*.properties -o -iname \*.html \) -not -name "version.properties" -print0 | xargs -0 shasum ;
) | shasum | awk '{ print $1 }'
}

28
bin/build-mb/README.md Normal file
View File

@@ -0,0 +1,28 @@
## Build Metabase Tooling
This project is to build the Metabase jar. It can be called standalone and is also called from the release project when creating releases.
## License Information
We create license information for all of our dependencies, both frontend and backend, and package them in our jar.
Tests will run in CI that we have license information for all dependencies. If you see these failing, an easy way to get a report of dependencies without license information can be obtained by running
```shell
build-mb % clojure -X build/list-without-license
$ "lein" "with-profile" "-dev,+ee,+include-all-drivers" "classpath"
All dependencies have licenses
```
If there are dependencies with missing license information you will see output like
```shell
build-mb % clojure -X build/list-without-license
$ "lein" "with-profile" "-dev,+ee,+include-all-drivers" "classpath"
Missing License: /Users/dan/.m2/repository/org/eclipse/jetty/jetty-webapp/9.3.19.v20170502/jetty-webapp-9.3.19.v20170502.jar
Missing License: /Users/dan/.m2/repository/org/fusesource/leveldbjni/leveldbjni-all/1.8/leveldbjni-all-1.8.jar
Missing License: /Users/dan/.m2/repository/org/opensaml/opensaml-security-impl/3.4.5/opensaml-security-impl-3.4.5.jar
Missing License: /Users/dan/.m2/repository/colorize/colorize/0.1.1/colorize-0.1.1.jar
```
You can check the overrides file (resources/overrides.edn) and add the license information there, or perhaps improve the license discovery mechanism in the code.

View File

@@ -5,10 +5,17 @@
"com.google.guava" {:resource "apache2_0.txt"},
"com.fasterxml.jackson.dataformat" {:resource "apache2_0.txt"},
"com.onelogin" {:resource "MIT.txt"},
"com.vladsch.flexmark" {:resource "BSD.txt"},
"xalan" {:resource "apache2_0.txt"}
"org.apache.hadoop" {:resource "apache2_0.txt"}
"org.ow2.asm" {:resource "BSD.txt"}
"org.eclipse.jetty" {:resource "apache2_0.txt"}}
"org.eclipse.jetty" {:resource "apache2_0.txt"}
;; see if we can remove these if/when https://github.com/googleapis/java-core/issues/488 is done
"com.google.cloud" {:resource "apache2_0.txt"}
"com.google.auth" {:resource "apache2_0.txt"}
"com.google.code.gson" {:resource "apache2_0.txt"}
"com.google.protobuf" {:resource "apache2_0.txt"}
"com.google.http-client" {:resource "apache2_0.txt"}}
"com.google.http-client" {"google-http-client" {:resource "apache2_0.txt"}
"google-http-client-jackson2" {:resource "apache2_0.txt"}}
@@ -34,6 +41,7 @@
"org.slf4j" {"slf4j-api" {:resource "MIT.txt"}},
"amalloy" {"ring-gzip-middleware" {:resource "MIT.txt"}},
"jakarta.activation" {"jakarta.activation-api" {:resource "EDL.txt"}},
"com.sun.activation" {"jakarta.activation" {:resource "EDL.txt"}}
"net.jcip" {"jcip-annotations" {:resource "CC_2_5.txt"}},
"hiccup" {"hiccup" {:resource "EPL.txt"}},
"jakarta.xml.bind" {"jakarta.xml.bind-api" {:resource "EDL.txt"}},
@@ -41,7 +49,8 @@
{"java-support" {:resource "apache2_0.txt"}},
"io.dropwizard.metrics" {"metrics-core" {:resource "apache2_0.txt"}},
"stencil" {"stencil" {:resource "EPL.txt"}},
"org.antlr" {"antlr-runtime" {:resource "BSD.txt"}},
"org.antlr" {"antlr-runtime" {:resource "BSD.txt"}
"antlr4-runtime" {:resource "BSD.txt"}},
"de.rototor.pdfbox" {"graphics2d" {:resource "apache2_0.txt"}},
"colorize" {"colorize" {:resource "EPL.txt"}},
"org.liquibase" {"liquibase-core" {:resource "apache2_0.txt"}},

View File

@@ -28,66 +28,63 @@
(u/announce "CI run: enforce the lockfile")
(u/sh {:dir u/project-root-directory} "yarn" "--frozen-lockfile"))
(u/sh {:dir u/project-root-directory} "yarn")))
;; TODO -- I don't know why it doesn't work if we try to combine the two steps below by calling `yarn build`,
;; which does the same thing.
(u/step "Build frontend (ClojureScript)"
(u/step "Build frontend"
(u/sh {:dir u/project-root-directory
:env {"PATH" (env/env :path)
"HOME" (env/env :user-home)
"NODE_ENV" "production"
"WEBPACK_BUNDLE" "production"
"MB_EDITION" mb-edition}}
"./node_modules/.bin/shadow-cljs" "release" "app"))
(u/step "Run 'webpack' with NODE_ENV=production to assemble and minify frontend assets"
"yarn" "build"))
(u/step "Build static viz"
(u/sh {:dir u/project-root-directory
:env {"PATH" (env/env :path)
"HOME" (env/env :user-home)
"NODE_ENV" "production"
"WEBPACK_BUNDLE" "production"
"MB_EDITION" mb-edition}}
"./node_modules/.bin/webpack" "--bail"))
"yarn" "build-static-viz"))
(u/announce "Frontend built successfully."))))
(defn- build-licenses!
[edition]
{:pre [(#{:oss :ee} edition)]}
(u/step "Generate backend license information from jar files"
(let [[classpath] (u/sh {:dir u/project-root-directory
:quiet? true}
"clojure" (str "-A" edition) "-Spath")
output-filename (u/filename u/project-root-directory
"resources"
"license-backend-third-party.txt")
{:keys [without-license]} (license/generate {:classpath classpath
:backfill (edn/read-string
(slurp (io/resource "overrides.edn")))
:output-filename output-filename
:report? false})]
(when (seq without-license)
(run! (comp (partial u/error "Missing License: %s") first)
without-license))
(u/announce "License information generated at %s" output-filename)))
(u/step "Run `yarn licenses generate-disclaimer`"
(let [license-text (str/join \newline
(u/sh {:dir u/project-root-directory
:quiet? true}
"yarn" "licenses" "generate-disclaimer"))]
(spit (u/filename u/project-root-directory
"resources"
"license-frontend-third-party.txt") license-text))))
(def uberjar-filename (u/filename u/project-root-directory "target" "uberjar" "metabase.jar"))
(defn- build-uberjar! [edition]
{:pre [(#{:oss :ee} edition)]}
(u/delete-file-if-exists! uberjar-filename)
(u/step (format "Build uberjar with profile %s" edition)
(u/sh {:dir u/project-root-directory} "lein" "clean")
(u/sh {:dir u/project-root-directory} "lein" "with-profile" (str \+ (name edition)) "uberjar")
;; TODO -- we (probably) don't need to shell out in order to do this anymore, we should be able to do all this
;; stuff directly in Clojure land by including this other `build` namespace directly (once we dedupe the names)
(u/sh {:dir u/project-root-directory} "clojure" "-T:build" "uberjar" :edition edition)
(u/assert-file-exists uberjar-filename)
(u/announce "Uberjar built successfully.")))
(defn- build-backend-licenses-file! [edition]
{:pre [(#{:oss :ee} edition)]}
(let [classpath-and-logs (u/sh {:dir u/project-root-directory
:quiet? true}
"lein"
"with-profile" (str \- "dev"
(str \, \+ (name edition))
\,"+include-all-drivers")
"classpath")
classpath (last
classpath-and-logs)
output-filename (u/filename u/project-root-directory "license-backend-third-party")
{:keys [with-license
without-license]} (license/generate {:classpath classpath
:backfill (edn/read-string
(slurp (io/resource "overrides.edn")))
:output-filename output-filename
:report? false})]
(when (seq without-license)
(run! (comp (partial u/error "Missing License: %s") first)
without-license))
(u/announce "License information generated at %s" output-filename)))
(defn- build-frontend-licenses-file!
[]
(let [license-text (str/join \newline
(u/sh {:dir u/project-root-directory
:quiet? true}
"yarn" "licenses" "generate-disclaimer"))]
(spit (u/filename u/project-root-directory "license-frontend-third-party") license-text)))
(def all-steps
(ordered-map/ordered-map
:version (fn [{:keys [edition version]}]
@@ -96,12 +93,10 @@
(i18n/create-all-artifacts!))
:frontend (fn [{:keys [edition]}]
(build-frontend! edition))
:licenses (fn [{:keys [edition]}]
(build-licenses! edition))
:drivers (fn [{:keys [edition]}]
(build-drivers/build-drivers! edition))
:backend-licenses (fn [{:keys [edition]}]
(build-backend-licenses-file! edition))
:frontend-licenses (fn [{:keys []}]
(build-frontend-licenses-file!))
:uberjar (fn [{:keys [edition]}]
(build-uberjar! edition))))
@@ -121,7 +116,7 @@
version
(str/join ", " (map name steps)))
(doseq [step-name steps
:let [step-fn (or (get all-steps (keyword step-name))
:let [step-fn (or (get all-steps (u/parse-as-keyword step-name))
(throw (ex-info (format "Invalid step: %s" step-name)
{:step step-name
:valid-steps (keys all-steps)})))]]
@@ -133,3 +128,20 @@
(build! (merge {:edition (edition-from-env-var)}
(when-let [steps (not-empty steps)]
{:steps steps})))))
;; useful to call from command line `cd bin/build-mb && clojure -X build/list-without-license`
(defn list-without-license [{:keys []}]
(let [[classpath] (u/sh {:dir u/project-root-directory
:quiet? true}
"clojure" "-A:ee" "-Spath")
classpath-entries (license/jar-entries classpath)
{:keys [without-license]} (license/process*
{:classpath-entries classpath-entries
:backfill (edn/read-string
(slurp (io/resource "overrides.edn")))})]
(if (seq without-license)
(run! (comp (partial u/error "Missing License: %s") first)
without-license)
(u/announce "All dependencies have licenses"))
(shutdown-agents)
(System/exit (if (seq without-license) 1 0))))

View File

@@ -185,10 +185,17 @@
{:with-license (categorized true)
:without-license (categorized false)}))
(defn jar-entries
"Returns a seq of jar entries on the classpath"
[classpath]
(->> (str/split classpath (re-pattern classpath-separator))
(filter jar-file?)))
(defn generate
"Process a classpath, creating a file of all license information, writing to `:output-filename`. Backfill is a clojure
data structure or a filename of an edn file of a clojure datastructure providing for backfilling license information
if it is not discernable from the jar. Should be of the form (note keys are strings not symbols)
"Process a classpath, creating a file of all license information, writing to `:output-filename`. `classpath-entries`
should be a seq of classpath roots. Split a classpath on the classpath separator. Backfill is a clojure data
structure or a filename of an edn file of a clojure datastructure providing for backfilling license information if
it is not discernable from the jar. Should be of the form (note keys are strings not symbols)
{\"group\" {\"artifact\" \"license text\"}
\"group\" {\"artifact\" {:resource \"filename-of-license\"}}
@@ -210,25 +217,22 @@
:without-license [ [jar-filename {:coords {:group :artifact :version} :error <text>}] ... ]}"
[{:keys [classpath backfill output-filename report?] :or {report? true}}]
(let [backfill (if (string? backfill)
(edn/read-string (slurp backfill))
(edn/read-string (slurp (io/resource backfill)))
(or backfill {}))
entries (->> (str/split classpath (re-pattern classpath-separator))
(filter jar-file?))]
(let [{:keys [with-license without-license] :as license-info}
(process* {:classpath-entries entries
:backfill backfill})]
entries (jar-entries classpath)
{:keys [with-license without-license] :as license-info}
(process* {:classpath-entries entries
:backfill backfill})]
(when (seq with-license)
(with-open [os (io/writer output-filename)]
(run! #(write-license os %) with-license)))
(when report?
(when (seq without-license)
(run! #(report-missing *err* %) without-license))
(when (seq with-license)
(with-open [os (io/writer output-filename)]
(run! #(write-license os %) with-license)))
(when report?
(when (seq without-license)
(run! #(report-missing *err* %) without-license))
(when (seq with-license)
(println "License information for" (count with-license) "libraries written to "
output-filename)
;; we call this from the build script. if we switch to the shell we can reenable this and figure out the
;; best defaults. Want to make sure we never kill our build script
#_(System/exit (if (seq without-license) 1 0))))
license-info)))
;; clj -X build.licenses/generate :classpath \"$(cd ../.. && lein with-profile -dev,+ee,+include-all-drivers classpath | tail -n1)\" :backfill "\"resources/overrides.edn\"" :output-filename "\"backend-licenses-ee.txt\""
(println "License information for" (count with-license) "libraries written to "
output-filename)
;; we call this from the build script. if we switch to the shell we can reenable this and figure out the
;; best defaults. Want to make sure we never kill our build script
#_(System/exit (if (seq without-license) 1 0))))
license-info))

View File

@@ -207,26 +207,26 @@
(deftest all-deps-have-licenses
(testing "All deps on the classpath have licenses"
(loop-until-success #(u/sh {:dir u/project-root-directory} "lein" "with-profile" "+include-all-drivers,+oss,+ee" "deps") 3 "download deps")
(doseq [edition [:oss :ee]]
(let [classpath (u/sh {:dir u/project-root-directory
:quiet? true}
"lein"
"with-profile" (str \- "dev"
(str \, \+ (name edition))
\,"+include-all-drivers")
"classpath")
classpath-entries (->> (str/split (last classpath) (re-pattern lic/classpath-separator))
(filter lic/jar-file?))]
(let [results (lic/process* {:classpath-entries classpath-entries
:backfill (edn/read-string
(slurp (io/resource "overrides.edn")))})]
(is (nil? (:without-license results)) "Some deps don't have identifiable licenses")
(is (= (set classpath-entries)
(into #{} (->> results :with-license (map first))))))
(is (some? (:without-license
(lic/process* {:classpath-entries classpath-entries
:backfill {}}))))))))
(loop-until-success #(u/sh {:dir u/project-root-directory} "clojure" "-A:ee" "-P") 3 "download deps")
(let [edition :ee
classpath (u/sh {:dir u/project-root-directory
:quiet? true}
"clojure"
"-A:ee"
"-Spath")
classpath-entries (->> (str/split (last classpath) (re-pattern lic/classpath-separator))
(filter lic/jar-file?))]
(let [results (lic/process* {:classpath-entries classpath-entries
:backfill (edn/read-string
(slurp (io/resource "overrides.edn")))})]
(is (nil? (:without-license results))
(str "Deps without license information:\n"
(str/join "\n" (map first (:without-license results)))))
(is (= (set classpath-entries)
(into #{} (->> results :with-license (map first))))))
(is (some? (:without-license
(lic/process* {:classpath-entries classpath-entries
:backfill {}})))))))
(comment
(run-tests)
(binding [clojure.test/*test-out* *out*] (run-tests))

View File

@@ -1,9 +1,7 @@
#! /usr/bin/env bash
set -eou pipefail
you_need_to_upgrade() {
echo "Clojure CLI must be at least version 1.10.1.708. Your version is $version."
echo "Clojure CLI must be at least version 1.10.3.905. Your version is $version."
echo "See https://www.clojure.org/guides/getting_started for upgrade instructions."
exit -3
}
@@ -24,8 +22,8 @@ check_clojure_cli() {
elif [ "$minor_version" -eq "10" ]; then
if [ "$patch_version" -lt "1" ]; then
you_need_to_upgrade
elif [ "$patch_version" -eq "1" ]; then
if [ "$build_version" -lt "708" ]; then
elif [ "$patch_version" -eq "3" ]; then
if [ "$build_version" -lt "905" ]; then
you_need_to_upgrade
fi
fi

51
bin/clear-outdated-cpcaches.sh Executable file
View File

@@ -0,0 +1,51 @@
#! /usr/bin/env bash
set -euo pipefail
script_directory=`dirname "${BASH_SOURCE[0]}"`
# This function will clear all the .cpcache directories if any deps.edn file is newer than any of them.
clear_outdated_cpcaches() {
echo "Clearing outdated .cpcache directories if needed..."
# switch to project root directory if we're not already there
cd "$script_directory/.."
project_root=`pwd`
cpcaches=`find bin java modules -type d -name .cpcache`
if [ -d .cpcache ]; then
cpcaches=".cpcache $cpcaches"
fi
if [ -z "$cpcaches" ]; then
echo "No .cpcache directories found; nothing to do"
return 0
fi
deps_edns="deps.edn $(find bin java modules -type f -name deps.edn)"
# find the OLDEST cpcache and NEWEST deps.edn files.
oldest_cpcache=""
for cpcache in $cpcaches; do
if [ -z "$oldest_cpcache" ] || [ "$cpcache" -ot "$oldest_cpcache" ]; then
oldest_cpcache="$cpcache"
fi
done
newest_deps_edn=""
for deps_edn in $deps_edns; do
if [ -z "$newest_deps_edn" ] || [ "$deps_edn" -nt "$newest_deps_edn" ]; then
newest_deps_edn="$deps_edn"
fi
done
# if the newest deps.edn is newer than the *ANY* of the cpcaches, clear all the cpcaches.
if [ "$newest_deps_edn" -nt "$oldest_cpcache" ]; then
echo "$newest_deps_edn is newer than $oldest_cpcache; deleting all .cpcache directories"
for cpcache in $cpcaches; do
echo "rm -rf $cpcache"
rm -rf "$cpcache"
done
else
echo ".cpcache directories are up to date."
fi
}

View File

@@ -35,6 +35,7 @@
env-or-throw]
[files
absolute?
assert-file-exists
copy-file!
create-directory-unless-exists!
@@ -56,12 +57,12 @@
yes-or-no-prompt]
[misc
parse-as-keyword
varargs]
[output
announce
error
format-bytes
pretty-print-exception
safe-println]

View File

@@ -1,6 +1,6 @@
(ns metabuild-common.files
(:require [clojure.string :as str]
[environ.core :as env]
(:require [clojure.java.io :as io]
[clojure.string :as str]
[metabuild-common.misc :as misc]
[metabuild-common.output :as out]
[metabuild-common.shell :as sh]
@@ -97,20 +97,16 @@
(str/join File/separatorChar path-components))
(def ^String project-root-directory
"Root directory of the Metabase repo, e.g. `/users/cam/metabase`. Determined by finding the directory that has
`project.clj` in it."
(loop [^File dir (File. ^String (env/env :user-dir))]
(cond
(file-exists? (filename (.getAbsolutePath dir) "project.clj"))
(.getAbsolutePath dir)
(.getParentFile dir)
(recur (.getParentFile dir))
:else
(throw (ex-info (format "Can't find project root directory: no parent directory of %s has a project.clj file"
(env/env :user-dir))
{:dir (env/env :user-dir)})))))
"Root directory of the Metabase repo, e.g. `/users/cam/metabase`. Determined based on its location relative to this
source file."
(.. (Paths/get (.toURI (io/resource "metabuild_common/files.clj")))
toFile
getParentFile ; /home/cam/metabase/bin/common/src/metabuild_common
getParentFile ; /home/cam/metabase/bin/common/src/
getParentFile ; /home/cam/metabase/bin/common/
getParentFile ; /home/cam/metabase/bin/
getParentFile ; /home/cam/metabase/
getCanonicalPath))
(defn download-file!
"Download a file from `url` to `dest-path` using `wget`."
@@ -139,3 +135,8 @@
(when delete-on-exit?
(.deleteOnExit file))
file)))
(defn absolute?
"Whether `file` is an absolute path."
[file]
(.isAbsolute (io/file file)))

View File

@@ -1,10 +1,23 @@
(ns metabuild-common.misc)
(ns metabuild-common.misc
(:require [clojure.string :as str]))
(defmacro varargs
"Utility macro for passing varargs of a certain `klass` to a Java method.
(Files/createTempFile \"driver\" \".jar\" (varargs FileAttribute))"
{:style/indent 1, :arglists '([klass] [klass xs])}
{:arglists '([klass] [klass xs])}
[klass & [objects]]
(vary-meta `(into-array ~klass ~objects)
assoc :tag (format "[L%s;" (.getCanonicalName ^Class (ns-resolve *ns* klass)))))
(defn parse-as-keyword
"Like [[clojure.core/keyword]], but with a couple of tweaks to make it better for parsing command-line args:
* empty strings get parsed to `nil` instead of an empty keyword `:`
* strings starting with `:` e.g. `\":driver\"` get parsed to normal keywords e.g. `:driver` instead of `::driver`
(which is super confusing, because it's an _unnamespaced_ keyword whose the _name_ is `:driver`)"
[s]
(cond
(keyword? s) s
(not (str/blank? s)) (keyword (cond-> s
(str/starts-with? s ":") (.substring 1)))))

View File

@@ -40,12 +40,3 @@
(println (colorize/red (str "Step failed: " (.getMessage e))))
(binding [pprint/*print-right-margin* 120]
(pprint/pprint e-map))))
(defn format-bytes
"Nicely format `num-bytes` in a human-readable way (e.g. KB/MB/etc.)"
[num-bytes]
(loop [n num-bytes [suffix & more] ["B" "KB" "MB" "GB"]]
(if (and (seq more)
(>= n 1024))
(recur (/ n 1024.0) more)
(format "%.1f %s" n suffix))))

View File

@@ -0,0 +1,12 @@
(ns metabuild-common.misc-test
(:require [clojure.test :refer :all]
[metabuild-common.misc :as misc]))
(deftest parse-as-keyword-test
(are [input expected] (= expected (misc/parse-as-keyword input))
"abc" :abc
":abc" :abc
"" nil
" " nil
:abc :abc
nil nil))

View File

@@ -1,145 +0,0 @@
#!/usr/bin/env babel-node
import fetch from "isomorphic-fetch";
import path from "path";
import fs from "fs-promise"
import imageDiff_ from "image-diff";
import https from "https";
import os from "os";
import { WebClient } from "@slack/client";
const CIRCLECI_TOKEN = process.env["CIRCLECI_TOKEN"];
const SLACK_TOKEN = process.env["SLACK_TOKEN"];
const SLACK_CHANNEL = "#ci-screenshots";
const CIRCLE_PROJECT = "github/metabase/metabase";
const CIRCLE_BRANCH = "master";
const CIRCLE_SCREENSHOT_PATH = "/home/ubuntu/metabase/screenshots/";
const slack = new WebClient(SLACK_TOKEN);
async function circleci(path) {
const response = await fetch(
`https://circleci.com/api/v1.1/${path}?circle-token=${encodeURIComponent(CIRCLECI_TOKEN)}`
);
return response.json();
}
function imageDiff(options) {
return new Promise((resolve, reject) => {
imageDiff_.getFullResult(options, (err, result) =>
err ? reject(err) : resolve(result)
);
});
}
function download(url, path) {
return new Promise((resolve, reject) => {
https.get(url, response => {
response.pipe(fs.createWriteStream(path)).on("finish", resolve);
}).on('error', reject);
});
}
async function getCircleArtifactScreenshots(buildPath) {
let artifacts = await circleci(`project/${buildPath}/artifacts`);
let results = {};
for (const artifact of artifacts) {
if (artifact.pretty_path.startsWith(CIRCLE_SCREENSHOT_PATH)) {
const downloadPath = path.join(os.tmpdir(), path.basename(artifact.pretty_path));
console.log("Downloading ", artifact.url, "to", downloadPath);
await download(artifact.url, downloadPath);
results[artifact.pretty_path.slice(CIRCLE_SCREENSHOT_PATH.length)] = downloadPath;
}
}
return results;
}
async function getLocalScreenshots(directory) {
const filenames = await fs.readdir(directory);
let results = {};
for (const filename of filenames) {
results[filename] = path.resolve(directory, filename);
}
return results;
}
async function getScreenshots(target) {
if (target.circleProject && target.circleBranch) {
let builds = await circleci(`project/${target.circleProject}/tree/${target.circleBranch}`);
let ok = builds.filter(build => build.status === "success" || build.status === "fixed");
let screenshots = await getCircleArtifactScreenshots(`${target.circleProject}/${ok[0].build_num}`);
return screenshots;
} else if (target.localDirectory) {
return await getLocalScreenshots(target.localDirectory);
} else {
throw "unknown target type";
}
}
async function run(expectedTarget, actualTarget) {
try {
const expectedScreenshots = await getScreenshots(expectedTarget);
console.log("Expected", Object.keys(expectedScreenshots));
const actualScreenshots = await getScreenshots(actualTarget);
console.log("Actual", Object.keys(expectedScreenshots));
let images = Object.keys({ ...expectedScreenshots, ...actualScreenshots });
for (const image of images) {
const expectedImage = expectedScreenshots[image];
const actualImage = actualScreenshots[image];
const diffImage = path.join(os.tmpdir(), "diff-"+image);
if (!actualImage) {
console.log("Added", image);
await slack.files.upload(image, {
title: "Added " + image,
channels: [SLACK_CHANNEL],
file: fs.createReadStream(actualImage)
});
} else if (!expectedImage) {
console.log("Removed", image);
await slack.files.upload(image, {
title: "Removed " + image,
channels: [SLACK_CHANNEL],
file: fs.createReadStream(expectedImage)
});
} else {
const result = await imageDiff({
expectedImage,
actualImage,
diffImage,
shadow: true
})
if (result.percentage === 0.0) {
console.log("No difference", image);
} else {
console.log("Changed", result.percentage.toFixed(2), image);
await slack.files.upload(image, {
title: "Diff (" + result.percentage.toFixed(2) + ") " + image,
channels: [SLACK_CHANNEL],
file: fs.createReadStream(diffImage)
});
await slack.files.upload(image, {
title: "Expected " + image,
channels: [SLACK_CHANNEL],
file: fs.createReadStream(expectedImage)
});
await slack.files.upload(image, {
title: "Actual " + image,
channels: [SLACK_CHANNEL],
file: fs.createReadStream(actualImage)
});
}
}
}
} catch (e) {
console.error(e);
}
}
run(
{ circleProject: CIRCLE_PROJECT, circleBranch: CIRCLE_BRANCH },
{ localDirectory: "screenshots" }
);

View File

@@ -36,7 +36,7 @@
{:id (.getMsgid message)
:id-plural (.getMsgidPlural message)
:str (.getMsgstr message)
:str-plural (seq (remove str/blank? (.getMsgstrPlural message)))
:str-plural (seq (.getMsgstrPlural message))
:fuzzy? (.isFuzzy message)
:plural? (.isPlural message)
:source-references (seq (remove str/blank? (.getSourceReferences message)))

View File

@@ -25,6 +25,9 @@
(u/announce "Artifacts for locale %s created successfully." (pr-str locale))))
(defn- create-artifacts-for-all-locales! []
;; Empty directory in case some locales were removed
(u/delete-file-if-exists! backend/target-directory)
(u/delete-file-if-exists! frontend/target-directory)
(doseq [locale (i18n/locales)]
(create-artifacts-for-locale! locale)))

View File

@@ -43,7 +43,7 @@
(defn- i18n-map [locale]
(->i18n-map (i18n/po-contents locale)))
(def ^:private target-directory
(def target-directory
(u/filename u/project-root-directory "resources" "frontend_client" "app" "locales"))
(defn- target-filename [locale]

View File

@@ -25,5 +25,9 @@
"${ 0 } Queryable Table"
{:msgid_plural "{0} Queryable Tables"
:msgstr ["${ 0 } Tabla Consultable" "${ 0 } Tablas consultables"]}}}}
:msgstr ["${ 0 } Tabla Consultable" "${ 0 } Tablas consultables"]}
"${ 0 } metric"
{:msgid_plural "{0} metrics"
:msgstr ["${ 0 } metrik" ""]}}}}
(#'frontend/->i18n-map test-common/po-contents))))

View File

@@ -50,12 +50,23 @@
:source-references ["frontend/src/metabase/admin/datamodel/components/database/MetadataTableList.jsx:77"]
:comment nil})
(def plural-message-frontend-with-empty
{:id "{0} metric"
:id-plural "{0} metrics"
:str nil
:str-plural ["{0} metrik" ""]
:fuzzy? false
:plural? true
:source-references ["frontend/src/metabase/query_builder/components/view/QuestionDescription.jsx:20"]
:comment nil})
(def messages
[singular-message-frontend
singular-message-backend
singular-template-message-frontend
singular-template-message-backend
plural-message-frontend])
plural-message-frontend
plural-message-frontend-with-empty])
(def po-contents
{:headers {"MIME-Version" "1.0",

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#! /usr/bin/env bash
set -eu
set -euo pipefail
# gettext installed via homebrew is "keg-only", add it to the PATH
if [ -d "/usr/local/opt/gettext/bin" ]; then
@@ -13,6 +13,16 @@ if ! command -v xgettext > /dev/null; then
exit 1
fi
# switch to project root directory if we're not already there
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/../.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/prep.sh"
prep_deps
POT_NAME="locales/metabase.pot"
POT_BACKEND_NAME="locales/metabase-backend.pot"
# NOTE: hardcoded in .babelrc
@@ -27,7 +37,7 @@ mkdir -p "locales"
#######################
# NOTE: about twice as fast to call babel directly rather than a full webpack build
BABEL_ENV=extract ./node_modules/.bin/babel -q -x .js,.jsx -o /dev/null {enterprise/,}frontend/src
BABEL_ENV=extract ./node_modules/.bin/babel --quiet -x .js,.jsx -o /dev/null {enterprise/,}frontend/src
# BABEL_ENV=extract BABEL_DISABLE_CACHE=1 yarn run build
# NOTE: replace ttag's "${ 0 }" style references with xgettext "{0}" style references for consistency
@@ -68,7 +78,7 @@ rm "$POT_BACKEND_NAME.bak"
# update auto dash pot #
########################
lein generate-automagic-dashboards-pot
clojure -M:generate-automagic-dashboards-pot
##################
# merge all pots #

View File

@@ -9,5 +9,11 @@ cd "$script_directory/.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/clear-outdated-cpcaches.sh"
clear_outdated_cpcaches
source "./bin/prep.sh"
prep_deps
cd bin/lint-migrations-file
clojure -M -m lint-migrations-file $@

View File

@@ -1,7 +1,7 @@
{:paths ["src"]
:deps
{io.forward/yaml {:mvn/version "1.0.9"} ; don't upgrade to 1.0.10 -- doesn't work on Java 8 (!)
{io.forward/yaml {:mvn/version "1.0.9"} ; Don't upgrade yet, new version doesn't support Java 8 (see https://github.com/owainlewis/yaml/issues/37)
org.flatland/ordered {:mvn/version "1.5.9"}} ; used by io.forward/yaml -- need the newer version
:aliases

60
bin/prep.sh Executable file
View File

@@ -0,0 +1,60 @@
#! /usr/bin/env bash
# functions for running prep steps to compile Java and AOT source files, needed before running other stuff.
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/.."
project_root=`pwd`
clear_cpcaches() {
cd "$project_root"
for file in `find . -type d -name .cpcache`; do
rm -rf "$file"
done
}
compile_java_sources() {
cd "$project_root"
echo "Compile Java source files in $project_root/java if needed..."
if [ ! -d "$project_root/java/target/classes" ]; then
echo 'Compile Java source files'
cd "$project_root"
clojure -Sforce -X:deps prep
else
echo 'Java source files are already compiled'
fi
}
compile_spark_sql_aot_sources() {
cd "$project_root"
echo "Compile Spark SQL AOT source files in $project_root/modules/drivers/sparksql if needed..."
if [ ! -d "$project_root/modules/drivers/sparksql/target/classes" ]; then
echo 'Compile Spark SQL AOT source files'
cd "$project_root/modules/drivers"
clojure -Sforce -X:deps prep
else
echo 'Spark SQL AOT source files are already compiled'
fi
}
prep_deps() {
if compile_java_sources; then
echo "Java sources => OK"
else
echo 'Compilation failed (WHY?!); clearing classpath caches and trying again...'
clear_cpcaches
compile_java_sources
fi
if compile_spark_sql_aot_sources; then
echo "Spark SQL AOT sources => OK"
else
echo 'Compilation failed (WHY?!); clearing classpath caches and trying again...'
clear_cpcaches
compile_spark_sql_aot_sources
fi
cd "$project_root"
}

View File

@@ -1,13 +0,0 @@
#! /usr/bin/env bash
printf "\e[1;34mChecking for reflection warnings. This may take a few minutes, so sit tight...\e[0m\n"
warnings=`lein with-profile +ci,+ee check-reflection-warnings 2>&1 | grep Reflection | grep metabase | sort | uniq`
if [ ! -z "$warnings" ]; then
printf "\e[1;31mYour code has introduced some reflection warnings.\e[0m 😞\n"
echo "$warnings";
exit -1;
fi
printf "\e[1;32mNo reflection warnings! Success.\e[0m\n"

View File

@@ -2,8 +2,18 @@
set -euo pipefail
# switch to project root directory if we're not already there
script_directory=`dirname "${BASH_SOURCE[0]}"`
cd "$script_directory/.."
source "./bin/check-clojure-cli.sh"
check_clojure_cli
source "./bin/clear-outdated-cpcaches.sh"
clear_outdated_cpcaches
source "./bin/prep.sh"
prep_deps
cd bin/release
clojure -M -m release $@

View File

@@ -14,8 +14,4 @@
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "209b64504cb3bd3b99ecfec7937b358a879f55c1"}
org.clojure/data.json {:mvn/version "2.0.2"}}
:main-opts ["-m" "cognitect.test-runner"]}
:nREPL {:extra-paths ["test"]
:extra-deps {nrepl/nrepl {:mvn/version "0.8.3"}
org.clojure/data.json {:mvn/version "2.0.2"}}
:main-opts ["-m" "nrepl.cmdline" "-i"]}}}
:main-opts ["-m" "cognitect.test-runner"]}}}

View File

@@ -53,6 +53,6 @@
(u/exit-when-finished-nonzero-on-exception
(check-prereqs/check-prereqs)
(set-build-options/prompt-and-set-build-options!)
(let [steps (or (seq (map keyword steps))
(let [steps (or (seq (map u/parse-as-keyword steps))
(keys steps*))]
(do-steps! steps))))

View File

@@ -26,6 +26,10 @@
"Source location of the .ebextensions directory"
(u/assert-file-exists (u/filename c/root-directory "bin" "release" "src" "release" "elastic_beanstalk" ".ebextensions")))
(def ^:private eb-platform-source
"Source location of the .ebextensions directory"
(u/assert-file-exists (u/filename c/root-directory "bin" "release" "src" "release" "elastic_beanstalk" ".platform")))
(def ^:private archive-temp-dir
"Path where we'll put the contents of the ZIP file before we create it."
"/tmp/metabase-aws-eb")
@@ -75,6 +79,8 @@
(json/generate-string (dockerrun-json-content) {:pretty true})))
(u/step "Copy .ebextensions"
(u/copy-file! eb-extensions-source (u/filename archive-temp-dir ".ebextensions")))
(u/step "Copy .platform"
(u/copy-file! eb-platform-source (u/filename archive-temp-dir ".platform")))
(u/step "Create metabase-aws-eb.zip"
(u/delete-file-if-exists! archive-path)
(u/sh {:dir archive-temp-dir} "zip" "--recurse-paths" archive-path ".")

View File

@@ -4,59 +4,34 @@
# Comment out a variable to disable a feature
#####
files:
"/tmp/install" :
mode: "000755"
owner: root
group: root
source: https://inspector-agent.amazonaws.com/linux/latest/install
container_commands:
# do server_https first to avoid overwriting other config changes
01_server_https:
command: ".ebextensions/metabase_config/metabase-setup.sh server_https"
ignoreErrors: true
01-persist_env_vars:
command: ".ebextensions/metabase_config/metabase-setup.sh set_up_env_vars"
ignoreErrors: false
02_log_x_real_ip:
command: ".ebextensions/metabase_config/metabase-setup.sh log_x_real_ip"
ignoreErrors: true
03_install_papertrail:
02_install_papertrail:
command: ".ebextensions/metabase_config/metabase-setup.sh install_papertrail"
test: test $PAPERTRAIL_HOST
ignoreErrors: true
04_try_papertrail:
03_try_papertrail:
command: "/sbin/service remote_syslog restart"
test: test -e /etc/log_files.yml
ignoreErrors: true
05_try_nginx:
command: "/sbin/service nginx restart"
test: nginx -t
ignoreErrors: false
06-install_inspector:
command: bash -x install -u false
cwd: /tmp/
07-install_cloudwatch_agent:
command: sudo yum install amazon-cloudwatch-agent -y
08-run_cloudwatch_agent:
command: sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:.ebextensions/metabase_config/cloudwatch/config.json -s
09-persist_env_vars:
command: /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export \(.key)=\"\(.value)\""' > /etc/profile.d/sh.local
10_set_up_env_vars:
command: ".ebextensions/metabase_config/metabase-setup.sh set_up_env_vars"
04_install_inspector:
command: yum -q list installed AwsAgent &>/dev/null && echo "Inspector installed, nothing to do here" || curl -O https://inspector-agent.amazonaws.com/linux/latest/install | sudo bash
ignoreErrors: true
05-install_cloudwatch_agent:
command: sudo yum update && sudo yum upgrade -y && yum -q list installed amazon-cloudwatch-agent &>/dev/null && echo "Cloudwatch agent installed, nothing to do here" || sudo yum -y install https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
ignoreErrors: true
06-run_cloudwatch_agent:
command: sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:.ebextensions/metabase_config/cloudwatch/config.json -s
ignoreErrors: true
# NGINX will be disabled in future releases, this will make the trick
#option_settings:
# aws:elasticbeanstalk:application:environment
# NGINX_FORCE_SSL=1
# PAPERTRAIL_HOSTNAME=$HOSTNAME
# PAPERTRAIL_HOST=foobar.papertrailapp.com
# PAPERTRAIL_PORT=12345
# PAPERTRAIL_FILES=/var/log/nginx/access.log /var/log/nginx/error.log
# aws:elasticbeanstalk:environment:proxy:
# ProxyServer: "none"

View File

@@ -7,39 +7,39 @@
"metrics_collected": {
"cpu": {
"measurement": [
"time_active",
"time_guest",
"time_guest_nice",
"time_idle",
"time_iowait",
"time_irq",
"time_nice",
"time_softirq",
"time_steal",
"time_system",
"time_user",
"usage_active",
"usage_guest",
"usage_guest_nice",
"usage_idle",
"usage_iowait",
"usage_irq",
"usage_nice",
"usage_softirq",
"usage_steal",
"usage_system",
"time_active",
"time_guest",
"time_guest_nice",
"time_idle",
"time_iowait",
"time_irq",
"time_nice",
"time_softirq",
"time_steal",
"time_system",
"time_user",
"usage_active",
"usage_guest",
"usage_guest_nice",
"usage_idle",
"usage_iowait",
"usage_irq",
"usage_nice",
"usage_softirq",
"usage_steal",
"usage_system",
"usage_user"
],
"totalcpu": false
},
"disk": {
"measurement": [
"free",
"total",
"used",
"used_percent",
"inodes_free",
"inodes_used",
"free",
"total",
"used",
"used_percent",
"inodes_free",
"inodes_used",
"inodes_total"
],
"ignore_file_system_types": [
@@ -49,76 +49,76 @@
"measurement": [
"reads",
"writes",
"read_bytes",
"write_bytes",
"read_time",
"write_time",
"io_time",
"read_bytes",
"write_bytes",
"read_time",
"write_time",
"io_time",
"iops_in_progress"
]
},
"swap": {
"measurement": [
"free",
"used",
"free",
"used",
"used_percent"
]
},
"mem": {
"measurement": [
"active",
"available",
"available_percent",
"buffered",
"cached",
"free",
"inactive",
"total",
"used",
"active",
"available",
"available_percent",
"buffered",
"cached",
"free",
"inactive",
"total",
"used",
"used_percent"
]
},
"net": {
"measurement": [
"bytes_sent",
"bytes_recv",
"drop_in",
"drop_out",
"err_in",
"err_out",
"packets_sent",
"bytes_sent",
"bytes_recv",
"drop_in",
"drop_out",
"err_in",
"err_out",
"packets_sent",
"packets_recv"
]
},
"netstat": {
"measurement": [
"tcp_close",
"tcp_close_wait",
"tcp_closing",
"tcp_established",
"tcp_fin_wait1",
"tcp_fin_wait2",
"tcp_last_ack",
"tcp_listen",
"tcp_none",
"tcp_syn_sent",
"tcp_syn_recv",
"tcp_time_wait",
"tcp_close",
"tcp_close_wait",
"tcp_closing",
"tcp_established",
"tcp_fin_wait1",
"tcp_fin_wait2",
"tcp_last_ack",
"tcp_listen",
"tcp_none",
"tcp_syn_sent",
"tcp_syn_recv",
"tcp_time_wait",
"udp_socket"
]
},
"processes": {
"measurement": [
"blocked",
"dead",
"idle",
"paging",
"running",
"sleeping",
"stopped",
"total",
"total_threads",
"wait",
"blocked",
"dead",
"idle",
"paging",
"running",
"sleeping",
"stopped",
"total",
"total_threads",
"wait",
"zombies"
]
}
@@ -131,4 +131,4 @@
},
"aggregation_dimensions" : [["InstanceId"], ["InstanceType"], ["InstanceId","InstanceType"]]
}
}
}

View File

@@ -5,6 +5,52 @@
# Unset a variable to disable a feature
####
set_up_env_vars () {
# /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export \(.key)=\"\(.value)\""' > /etc/profile.d/sh.local
if grep -q "Amazon Linux 2" /etc/os-release; then
if [ ! -z "$RDS_HOSTNAME" ]; then
# sed -i 's/RDS_HOSTNAME/MB_DB_HOST/' /etc/profile.d/sh.local
sed -i 's/RDS_HOSTNAME/MB_DB_HOST/' /opt/elasticbeanstalk/deployment/env.list
# sed -i 's/RDS_USERNAME/MB_DB_USER/' /etc/profile.d/sh.local
sed -i 's/RDS_USERNAME/MB_DB_USER/' /opt/elasticbeanstalk/deployment/env.list
# sed -i 's/RDS_PASSWORD/MB_DB_PASS/' /etc/profile.d/sh.local
sed -i 's/RDS_PASSWORD/MB_DB_PASS/' /opt/elasticbeanstalk/deployment/env.list
# sed -i 's/RDS_PORT/MB_DB_PORT/' /etc/profile.d/sh.local
sed -i 's/RDS_PORT/MB_DB_PORT/' /opt/elasticbeanstalk/deployment/env.list
# sed -i 's/RDS_DB_NAME/MB_DB_DBNAME/' /etc/profile.d/sh.local
sed -i 's/RDS_DB_NAME/MB_DB_DBNAME/' /opt/elasticbeanstalk/deployment/env.list
if [ "$RDS_PORT" == "3306" ]; then
# echo 'export MB_DB_TYPE="mysql"' >> /etc/profile.d/sh.local
echo 'MB_DB_TYPE=mysql' >> /opt/elasticbeanstalk/deployment/env.list
else
# echo 'export MB_DB_TYPE="postgres"' >> /etc/profile.d/sh.local
echo 'MB_DB_TYPE=postgres' >> /opt/elasticbeanstalk/deployment/env.list
fi
fi
else
if [ ! -z "$RDS_HOSTNAME" ]; then
# sed -i 's/RDS_HOSTNAME/MB_DB_HOST/' /etc/profile.d/sh.local
sed -i 's/RDS_HOSTNAME/MB_DB_HOST/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
# sed -i 's/RDS_USERNAME/MB_DB_USER/' /etc/profile.d/sh.local
sed -i 's/RDS_USERNAME/MB_DB_USER/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
# sed -i 's/RDS_PASSWORD/MB_DB_PASS/' /etc/profile.d/sh.local
sed -i 's/RDS_PASSWORD/MB_DB_PASS/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
# sed -i 's/RDS_PORT/MB_DB_PORT/' /etc/profile.d/sh.local
sed -i 's/RDS_PORT/MB_DB_PORT/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
# sed -i 's/RDS_DB_NAME/MB_DB_DBNAME/' /etc/profile.d/sh.local
sed -i 's/RDS_DB_NAME/MB_DB_DBNAME/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
if [ "$RDS_PORT" == "3306" ]; then
# echo 'export MB_DB_TYPE="mysql"' >> /etc/profile.d/sh.local
sed -i 's/}}}}/,"MB_DB_TYPE":"mysql"}}}}/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
else
# echo 'export MB_DB_TYPE="postgres"' >> /etc/profile.d/sh.local
sed -i 's/}}}}/,"MB_DB_TYPE":"postgres"}}}}/' /opt/elasticbeanstalk/deploy/configuration/containerconfiguration
fi
fi
fi
}
# add files to papertrail
pt_files () {
sed -i '/ - .*/d' /etc/log_files.yml
@@ -31,118 +77,12 @@ pt_local_host () {
sed -i "s/.*hostname:.*/hostname: $PAPERTRAIL_HOSTNAME/" /etc/log_files.yml
}
# enable https redirect
server_https () {
cd /etc/nginx/sites-available/
if [[ "x$NGINX_FORCE_SSL" == "x1" ]] # && ! grep -q https elasticbeanstalk-nginx-docker-proxy.conf ;
then
cat << 'EOF' > elasticbeanstalk-nginx-docker-proxy.conf
map $http_upgrade $connection_upgrade {
default "upgrade";
"" "";
}
server {
listen 80;
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/access.log;
location /api/health {
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
location / {
if ($http_x_forwarded_proto != "https") {
rewrite ^ https://$host$request_uri? permanent;
}
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
EOF
else
cat << 'EOF' > elasticbeanstalk-nginx-docker-proxy.conf
map $http_upgrade $connection_upgrade {
default "upgrade";
"" "";
}
server {
listen 80;
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
EOF
fi
}
# download, install and configure papertrail
install_papertrail () {
cp .ebextensions/metabase_config/papertrail/log_files.yml /etc/log_files.yml && chmod 644 /etc/log_files.yml
cp .ebextensions/metabase_config/papertrail/remote_syslog /etc/init.d/remote_syslog && chmod 555 /etc/init.d/remote_syslog
cd /tmp/
wget -q "https://github.com/papertrail/remote_syslog2/releases/download/v0.14/remote_syslog_linux_amd64.tar.gz" &&
wget -q "https://github.com/papertrail/remote_syslog2/releases/download/v0.20/remote_syslog_linux_amd64.tar.gz" &&
tar xzf remote_syslog_linux_amd64.tar.gz
/sbin/service remote_syslog stop
mv /tmp/remote_syslog/remote_syslog /usr/local/bin/
@@ -154,43 +94,11 @@ install_papertrail () {
[[ "$PAPERTRAIL_HOSTNAME" ]] && pt_local_host
}
# update nginx logging to include x_real_ip
log_x_real_ip () {
cp .ebextensions/metabase_config/nginx/log_x_real_ip.conf /etc/nginx/conf.d/log_x_real_ip.conf
cd /etc/nginx/sites-available
if ! grep -q access_log *-proxy.conf ; then
sed -i 's|location \/ {|location \/ {\n\n access_log \/var\/log\/nginx\/access.log log_x_real_ip;\n|' *-proxy.conf
fi
}
set_up_env_vars () {
if [ ! -z "$RDS_HOSTNAME" ]; then
# EEK: this is a bit fragile. if user picks a non-standard port for their db we are screwed :(
if [ "$RDS_PORT" == "3306" ]; then
export MB_DB_TYPE=mysql
else
export MB_DB_TYPE=postgres
fi
export MB_DB_DBNAME=$RDS_DB_NAME
export MB_DB_USER=$RDS_USERNAME
export MB_DB_PASS=$RDS_PASSWORD
export MB_DB_HOST=$RDS_HOSTNAME
export MB_DB_PORT=$RDS_PORT
fi
}
case $1 in
set_up_env_vars)
set_up_env_vars
;;
server_https)
server_https
;;
install_papertrail)
install_papertrail
;;
log_x_real_ip)
log_x_real_ip
;;
esac
esac

View File

@@ -1,4 +0,0 @@
# /etc/nginx/conf.d/log_x_real_ip.conf
log_format log_x_real_ip '$proxy_add_x_forwarded_for - [$time_local] '
'$request $status $body_bytes_sent '
'$http_referer $http_user_agent';

View File

@@ -0,0 +1,6 @@
#!/bin/bash
if [[ "x$NGINX_FORCE_SSL" == "x1" ]]; then
cp .platform/nginx/nginx-ssl.conf /etc/nginx/nginx.conf && nginx -t && /sbin/service nginx restart
else
cp .platform/nginx/nginx.conf /etc/nginx/nginx.conf && nginx -t && /sbin/service nginx restart
fi

View File

@@ -0,0 +1,6 @@
#!/bin/bash
if [[ "x$NGINX_FORCE_SSL" == "x1" ]]; then
cp .platform/nginx/nginx-ssl.conf /etc/nginx/nginx.conf && nginx -t && /sbin/service nginx restart
else
cp .platform/nginx/nginx.conf /etc/nginx/nginx.conf && nginx -t && /sbin/service nginx restart
fi

View File

@@ -0,0 +1,58 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65936;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
gzip on;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
access_log /var/log/nginx/access.log main;
location / {
if ($http_x_forwarded_proto != "https") {
rewrite ^ https://$host$request_uri? permanent;
}
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}

View File

@@ -0,0 +1,54 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65936;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
gzip on;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
access_log /var/log/nginx/access.log main;
location / {
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}

View File

@@ -44,5 +44,3 @@
(json/read-json true))
expected (make-version-info edition test-versions)]
(is (= expected actual)))))))

160
build.clj Normal file
View File

@@ -0,0 +1,160 @@
(ns build
(:require [clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.build.api :as b]
[clojure.tools.build.util.zip :as b.zip]
[clojure.tools.namespace.dependency :as ns.deps]
[clojure.tools.namespace.find :as ns.find]
[clojure.tools.namespace.parse :as ns.parse]
[hf.depstar.api :as d]
[metabuild-common.core :as c])
(:import java.io.OutputStream
java.net.URI
[java.nio.file Files FileSystems OpenOption StandardOpenOption]
java.util.Collections
java.util.jar.Manifest))
(def class-dir "target/classes")
(def uberjar-filename "target/uberjar/metabase.jar")
(defn do-with-duration-ms [thunk f]
(let [start-time-ms (System/currentTimeMillis)
result (thunk)
duration (- (System/currentTimeMillis) start-time-ms)]
(f duration)
result))
(defmacro with-duration-ms [[duration-ms-binding] & body]
(let [[butlast-forms last-form] ((juxt butlast last) body)]
`(do-with-duration-ms
(fn [] ~@butlast-forms)
(fn [~duration-ms-binding]
~last-form))))
(defn create-basis [edition]
{:pre [(#{:ee :oss} edition)]}
(b/create-basis {:project "deps.edn", :aliases #{edition}}))
(defn all-paths [basis]
(concat (:paths basis)
(get-in basis [:classpath-args :extra-paths])))
(defn clean! []
(c/step "Clean"
(c/step (format "Delete %s" class-dir)
(b/delete {:path class-dir}))
(c/step (format "Delete %s" uberjar-filename)
(b/delete {:path uberjar-filename}))))
;; this topo sort order stuff is required for stuff to work correctly... I copied it from my Cloverage PR
;; https://github.com/cloverage/cloverage/pull/303
(defn- dependencies-graph
"Return a `clojure.tools.namespace` dependency graph of namespaces named by `ns-symbol`."
[ns-decls]
(reduce
(fn [graph ns-decl]
(let [ns-symbol (ns.parse/name-from-ns-decl ns-decl)]
(reduce
(fn [graph dep]
(ns.deps/depend graph ns-symbol dep))
graph
(ns.parse/deps-from-ns-decl ns-decl))))
(ns.deps/graph)
ns-decls))
(defn metabase-namespaces-in-topo-order [basis]
(let [ns-decls (mapcat
(comp ns.find/find-ns-decls-in-dir io/file)
(all-paths basis))
ns-symbols (set (map ns.parse/name-from-ns-decl ns-decls))]
(->> (dependencies-graph ns-decls)
ns.deps/topo-sort
(filter ns-symbols))))
(defn compile-sources! [basis]
(c/step "Compile Clojure source files"
(let [paths (all-paths basis)
_ (c/announce "Compiling Clojure files in %s" (pr-str paths))
ns-decls (c/step "Determine compilation order for Metabase files"
(metabase-namespaces-in-topo-order basis))]
(with-duration-ms [duration-ms]
(b/compile-clj {:basis basis
:src-dirs paths
:class-dir class-dir
:ns-compile ns-decls})
(c/announce "Finished compilation in %.1f seconds." (/ duration-ms 1000.0))))))
(defn copy-resources! [edition basis]
(c/step "Copy resources"
;; technically we don't NEED to copy the Clojure source files but it doesn't really hurt anything IMO.
(doseq [path (all-paths basis)]
(c/step (format "Copy %s" path)
(b/copy-dir {:target-dir class-dir, :src-dirs [path]})))))
(defn create-uberjar! [basis]
(c/step "Create uberjar"
(with-duration-ms [duration-ms]
(d/uber {:class-dir class-dir
:uber-file uberjar-filename
:basis basis})
(c/announce "Created uberjar in %.1f seconds." (/ duration-ms 1000.0)))))
(def manifest-entries
{"Manifest-Version" "1.0"
"Created-By" "Metabase build.clj"
"Build-Jdk-Spec" (System/getProperty "java.specification.version")
"Main-Class" "metabase.core"
"Liquibase-Package" (str/join ","
["liquibase.change"
"liquibase.changelog"
"liquibase.database"
"liquibase.datatype"
"liquibase.diff"
"liquibase.executor"
"liquibase.ext"
"liquibase.lockservice"
"liquibase.logging"
"liquibase.parser"
"liquibase.precondition"
"liquibase.sdk"
"liquibase.serializer"
"liquibase.snapshot"
"liquibase.sqlgenerator"
"liquibase.structure"
"liquibase.structurecompare"])})
(defn manifest ^Manifest []
(doto (Manifest.)
(b.zip/fill-manifest! manifest-entries)))
(defn write-manifest! [^OutputStream os]
(.write (manifest) os)
(.flush os))
;; the customizations we need to make are not currently supported by tools.build -- see
;; https://ask.clojure.org/index.php/10827/ability-customize-manifest-created-clojure-tools-build-uber -- so we need
;; to do it by hand for the time being.
(defn update-manifest! []
(c/step "Update META-INF/MANIFEST.MF"
(with-open [fs (FileSystems/newFileSystem (URI. (str "jar:file:" (.getAbsolutePath (io/file "target/uberjar/metabase.jar"))))
Collections/EMPTY_MAP)]
(let [manifest-path (.getPath fs "META-INF" (into-array String ["MANIFEST.MF"]))]
(with-open [os (Files/newOutputStream manifest-path (into-array OpenOption [StandardOpenOption/WRITE
StandardOpenOption/TRUNCATE_EXISTING]))]
(write-manifest! os))))))
;; clojure -T:build uberjar :edition <edition>
(defn uberjar [{:keys [edition], :or {edition :oss}}]
(c/step (format "Build %s uberjar" edition)
(with-duration-ms [duration-ms]
(clean!)
(let [basis (create-basis edition)]
(compile-sources! basis)
(copy-resources! edition basis)
(create-uberjar! basis)
(update-manifest!))
(c/announce "Built target/uberjar/metabase.jar in %.1f seconds."
(/ duration-ms 1000.0)))))
;; TODO -- add `jar` and `install` commands to install Metabase to the local Maven repo (?) could make it easier to
;; build 3rd-party drivers the old way

View File

@@ -5,12 +5,32 @@ codecov:
coverage:
status:
project:
default:
back-end:
# Project must always have at least 78% coverage (by line)
target: 78%
# Whole-project test coverage is allowed to drop up to 5%. (For situtations where we delete code with full coverage)
threshold: 5%
patch:
default:
# Changes must have at least 75% test coverage (by line)
target: 75%
flags:
- back-end
front-end:
target: 35%
threshold: 5%
flags:
- front-end
patch: off
flags:
back-end:
paths:
- enterprise/backend
- shared/src
- src/metabase
carryforward: true
front-end:
paths:
- enterprise/frontend
- frontend
carryforward: true

430
deps.edn Normal file
View File

@@ -0,0 +1,430 @@
;; -*- comment-column: 80; -*-
{:deps
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;; !! PLEASE KEEP THESE ORGANIZED ALPHABETICALLY !!
;; !! AND ADD A COMMENT EXPLAINING THEIR PURPOSE !!
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{aleph/aleph {:mvn/version "0.4.6" ; Async HTTP library; WebSockets
:exclusions [org.clojure/tools.logging]}
amalloy/ring-buffer {:mvn/version "1.3.1" ; fixed length queue implementation, used in log buffering
:exclusions [org.clojure/clojure
org.clojure/clojurescript]}
amalloy/ring-gzip-middleware {:mvn/version "0.1.4"} ; Ring middleware to GZIP responses if client can handle it
bigml/histogram {:mvn/version "4.1.3"} ; Histogram data structure
buddy/buddy-core {:mvn/version "1.10.1" ; various cryptograhpic functions
:exclusions [commons-codec/commons-codec
org.bouncycastle/bcpkix-jdk15on
org.bouncycastle/bcprov-jdk15on]}
buddy/buddy-sign {:mvn/version "3.4.1"} ; JSON Web Tokens; High-Level message signing library
cheshire/cheshire {:mvn/version "5.10.1"} ; fast JSON encoding (used by Ring JSON middleware)
clj-http/clj-http {:mvn/version "3.12.3" ; HTTP client
:exclusions [commons-codec/commons-codec
commons-io/commons-io
slingshot/slingshot]}
clojurewerkz/quartzite {:mvn/version "2.1.0" ; scheduling library
:exclusions [c3p0/c3p0]}
colorize/colorize {:mvn/version "0.1.1" ; string output with ANSI color codes (for logging)
:exclusions [org.clojure/clojure]}
com.cemerick/friend {:mvn/version "0.2.3" ; auth library
:exclusions [commons-codec/commons-codec
net.sourceforge.nekohtml/nekohtml
org.apache.httpcomponents/httpclient
ring/ring-core
slingshot/slingshot]}
com.clearspring.analytics/stream {:mvn/version "2.9.8" ; Various sketching algorithms
:exclusions [it.unimi.dsi/fastutil
org.slf4j/slf4j-api]}
com.draines/postal {:mvn/version "2.0.4"} ; SMTP library
com.google.guava/guava {:mvn/version "30.1.1-jre"} ; dep for BigQuery, Spark, and GA. Require here rather than letting different dep versions stomp on each other — see comments on #9697
com.h2database/h2 {:mvn/version "1.4.197"} ; embedded SQL database
com.taoensso/nippy {:mvn/version "3.1.1"} ; Fast serialization (i.e., GZIP) library for Clojure
com.vladsch.flexmark/flexmark {:mvn/version "0.62.2"} ; Markdown parsing
commons-codec/commons-codec {:mvn/version "1.15"} ; Apache Commons -- useful codec util fns
commons-io/commons-io {:mvn/version "2.11.0"} ; Apache Commons -- useful IO util fns
commons-validator/commons-validator {:mvn/version "1.7" ; Apache Commons -- useful validation util fns
:exclusions [commons-beanutils/commons-beanutils
commons-digester/commons-digester
commons-logging/commons-logging]}
compojure/compojure {:mvn/version "1.6.2" ; HTTP Routing library built on Ring
:exclusions [ring/ring-codec]}
dk.ative/docjure {:mvn/version "1.16.0" ; excel export
crypto-random/crypto-random {:mvn/version "1.2.1"} ; library for generating cryptographically secure random bytes and strings
:exclusions [org.apache.poi/poi
org.apache.poi/poi-ooxml]}
environ/environ {:mvn/version "1.2.0"} ; env vars/Java properties abstraction
hiccup/hiccup {:mvn/version "1.0.5"} ; HTML templating
honeysql/honeysql {:mvn/version "1.0.461" ; Transform Clojure data structures to SQL
:exclusions [org.clojure/clojurescript]}
instaparse/instaparse {:mvn/version "1.4.10"} ; Make your own parser
io.forward/yaml {:mvn/version "1.0.9" ; Clojure wrapper for YAML library SnakeYAML. Don't upgrade yet, new version doesn't support Java 8 (see https://github.com/owainlewis/yaml/issues/37)
:exclusions [org.clojure/clojure
org.flatland/ordered
org.yaml/snakeyaml]}
javax.xml.bind/jaxb-api {:mvn/version "2.4.0-b180830.0359"} ; add the `javax.xml.bind` classes which we're still using but were removed in Java 11
joda-time/joda-time {:mvn/version "2.10.10"}
kixi/stats {:mvn/version "0.4.4" ; Various statistic measures implemented as transducers
:exclusions [org.clojure/data.avl]}
me.raynes/fs {:mvn/version "1.4.6" ; Filesystem tools
:exclusions [org.apache.commons/commons-compress]}
medley/medley {:mvn/version "1.3.0"} ; lightweight lib of useful functions
metabase/connection-pool {:mvn/version "1.1.1"} ; simple wrapper around C3P0. JDBC connection pools
metabase/saml20-clj {:mvn/version "2.0.0"} ; EE SAML integration
metabase/throttle {:mvn/version "1.0.2"} ; Tools for throttling access to API endpoints and other code pathways
net.cgrand/macrovich {:mvn/version "0.2.1"} ; utils for writing macros for both Clojure & ClojureScript
net.redhogs.cronparser/cron-parser-core {:mvn/version "3.5" ; describe Cron schedule in human-readable language
:exclusions [joda-time/joda-time ; exclude joda time 2.3 which has outdated timezone information
org.slf4j/slf4j-api]}
net.sf.cssbox/cssbox {:mvn/version "5.0.0" ; HTML / CSS rendering
:exclusions [org.slf4j/slf4j-api]}
org.apache.commons/commons-compress {:mvn/version "1.21"} ; compression utils
org.apache.commons/commons-lang3 {:mvn/version "3.12.0"} ; helper methods for working with java.lang stuff
org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.14.1"} ; apache logging framework
org.apache.logging.log4j/log4j-api {:mvn/version "2.14.1"} ; add compatibility with log4j 1.2
org.apache.logging.log4j/log4j-core {:mvn/version "2.14.1"} ; apache logging framework
org.apache.logging.log4j/log4j-jcl {:mvn/version "2.14.1"} ; allows the commons-logging API to work with log4j 2
org.apache.logging.log4j/log4j-liquibase {:mvn/version "2.14.1"} ; liquibase logging via log4j 2
org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.14.1"} ; allows the slf4j API to work with log4j 2
org.apache.poi/poi {:mvn/version "5.0.0"} ; Work with Office documents (e.g. Excel spreadsheets) -- newer version than one specified by Docjure
org.apache.poi/poi-ooxml {:mvn/version "5.0.0"
:exclusions [org.bouncycastle/bcpkix-jdk15on
org.bouncycastle/bcprov-jdk15on]}
org.apache.sshd/sshd-core {:mvn/version "2.7.0"} ; ssh tunneling and test server
org.apache.xmlgraphics/batik-all {:mvn/version "1.14"} ; SVG -> image
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"} ; LDAP client
org.bouncycastle/bcpkix-jdk15on {:mvn/version "1.69"} ; Bouncy Castle crypto library -- explicit version of BC specified to resolve illegal reflective access errors
org.bouncycastle/bcprov-jdk15on {:mvn/version "1.69"}
org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/core.async {:mvn/version "1.3.618"
:exclusions [org.clojure/tools.reader]}
org.clojure/core.logic {:mvn/version "1.0.0"} ; optimized pattern matching library for Clojure
org.clojure/core.match {:mvn/version "1.0.0"}
org.clojure/core.memoize {:mvn/version "1.0.250"} ; useful FIFO, LRU, etc. caching mechanisms
org.clojure/data.csv {:mvn/version "1.0.0"} ; CSV parsing / generation
org.clojure/java.classpath {:mvn/version "1.0.0"} ; examine the Java classpath from Clojure programs
org.clojure/java.jdbc {:mvn/version "0.7.12"} ; basic JDBC access from Clojure
org.clojure/java.jmx {:mvn/version "1.0.0"} ; JMX bean library, for exporting diagnostic info
org.clojure/math.combinatorics {:mvn/version "0.1.6"} ; combinatorics functions
org.clojure/math.numeric-tower {:mvn/version "0.0.4"} ; math functions like `ceil`
org.clojure/tools.logging {:mvn/version "1.1.0"} ; logging framework
org.clojure/tools.namespace {:mvn/version "1.1.0"}
org.clojure/tools.reader {:mvn/version "1.3.6"}
org.clojure/tools.trace {:mvn/version "0.7.11"} ; function tracing
org.eclipse.jetty/jetty-server {:mvn/version "9.4.43.v20210629"} ; web server
org.flatland/ordered {:mvn/version "1.5.9"} ; ordered maps & sets
org.graalvm.js/js {:mvn/version "21.2.0"} ; JavaScript engine
org.liquibase/liquibase-core {:mvn/version "3.6.3" ; migration management (Java lib)
:exclusions [ch.qos.logback/logback-classic]}
org.mariadb.jdbc/mariadb-java-client {:mvn/version "2.6.2"} ; MySQL/MariaDB driver
org.postgresql/postgresql {:mvn/version "42.2.23"} ; Postgres driver
org.slf4j/slf4j-api {:mvn/version "1.7.32"} ; abstraction for logging frameworks -- allows end user to plug in desired logging framework at deployment time
org.tcrawley/dynapath {:mvn/version "1.1.0"} ; Dynamically add Jars (e.g. Oracle or Vertica) to classpath
org.threeten/threeten-extra {:mvn/version "1.7.0"} ; extra Java 8 java.time classes like DayOfMonth and Quarter
org.yaml/snakeyaml {:mvn/version "1.29"} ; YAML parser (required by liquibase)
potemkin/potemkin {:mvn/version "0.4.5" ; utility macros & fns
:exclusions [riddley/riddley]}
pretty/pretty {:mvn/version "1.0.5"} ; protocol for defining how custom types should be pretty printed
prismatic/schema {:mvn/version "1.1.12"} ; Data schema declaration and validation library
redux/redux {:mvn/version "0.1.4"} ; Utility functions for building and composing transducers
riddley/riddley {:mvn/version "0.2.0"} ; code walking lib -- used interally by Potemkin, manifold, etc.
ring/ring-core {:mvn/version "1.9.4"} ; web server (Jetty wrapper)
ring/ring-jetty-adapter {:mvn/version "1.9.4"} ; Ring adapter using Jetty webserver
ring/ring-json {:mvn/version "0.5.1"} ; Ring middleware for reading/writing JSON automatically
robdaemon/clojure.java-time {:mvn/version "0.3.3-SNAPSHOT"} ; Java 8 java.time wrapper. Fork to address #13102 - see upstream PR: https://github.com/dm3/clojure.java-time/pull/60
slingshot/slingshot {:mvn/version "0.12.2"} ; enhanced throw/catch, used by other deps
stencil/stencil {:mvn/version "0.5.0"} ; Mustache templates for Clojure
toucan/toucan {:mvn/version "1.15.4" ; Model layer, hydration, and DB utilities
:exclusions [honeysql/honeysql
org.clojure/java.jdbc
org.clojure/tools.logging
org.clojure/tools.namespace]}
user-agent/user-agent {:mvn/version "0.1.0"} ; User-Agent string parser, for Login History page & elsewhere
weavejester/dependency {:mvn/version "0.2.1"} ; Dependency graphs and topological sorting
;; dummy dependency for the Java source file(s)
metabase/java-deps {:local/root "java"}}
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;; !! PLEASE KEEP NEW DEPENDENCIES ABOVE ALPHABETICALLY ORGANIZED AND ADD COMMENTS EXPLAINING THEM. !!
;; !! *PLEASE DO NOT* ADD NEW ONES TO THE BOTTOM OF THE LIST. !!
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:paths
["src" "shared/src" "resources" "java/target/classes"]
:aliases
{
;;; Local Dev & test profiles
;; for local development: start a REPL with
;;
;; clojure -A:dev (basic dev REPL that includes test namespaces)
;; clojure -A:dev:drivers:drivers-dev (dev REPL w/ drivers + tests)
;; clojure -A:dev:ee:ee-dev (dev REPL w/ EE code including tests)
;;
;; You can start a web server from this REPL with
;;
;; (require 'dev)
;; (dev/start!)
:dev
{:extra-deps
{clj-http-fake/clj-http-fake {:mvn/version "1.0.3"
:exclusions [slingshot/slingshot]}
cloverage/cloverage {:mvn/version "1.2.2"}
eftest/eftest {:mvn/version "0.5.9"}
jonase/eastwood {:mvn/version "0.9.6"}
lein-check-namespace-decls/lein-check-namespace-decls {:mvn/version "1.0.4"} ; misnomer since this works on Clojure CLI now too
pjstadig/humane-test-output {:mvn/version "0.11.0"}
reifyhealth/specmonstah {:mvn/version "2.0.0"}
ring/ring-mock {:mvn/version "0.4.0"}
talltale/talltale {:mvn/version "0.5.4"}}
:extra-paths ["dev/src" "local/src" "test" "shared/test" "test_resources"]
:jvm-opts ["-Dmb.run.mode=dev"
"-Dmb.field.filter.operators.enabled=true"
"-Dmb.test.env.setting=ABCDEFG"
"-Duser.timezone=UTC"
"-Dfile.encoding=UTF-8"
"-Duser.language=en"
;; Exceptions that get thrown repeatedly are created without stacktraces as a performance
;; optimization in newer Java versions. This makes debugging pretty hard when working on stuff
;; locally -- prefer debuggability over performance for local dev work.
"-XX:-OmitStackTraceInFastThrow"
;; prevent Java icon from randomly popping up in macOS dock
"-Djava.awt.headless=true"]}
;; includes test code as source paths. Run tests with clojure -X:dev:test
:test
{:extra-paths ["test_config"]
:exec-fn metabase.test-runner/run-tests
:jvm-opts ["-Dmb.run.mode=test"
"-Dmb.db.in.memory=true"
"-Dmb.jetty.join=false"
"-Dmb.field.filter.operators.enabled=true"
"-Dmb.api.key=test-api-key"
;; Different port from normal `:dev` so you can run tests on a different server.
;; TODO -- figure out how to do a random port like in the old project.clj?
"-Dmb.jetty.port=3001"]}
;; run the dev server with
;; clojure -M:run
;; clojure -M:run:drivers (include all drivers)
;; clojure -M:run:ee (include EE code)
:run
{:main-opts ["-m" "metabase.core"]
:jvm-opts ["-Dmb.run.mode=dev"
"-Djava.awt.headless=true" ; prevent Java icon from randomly popping up in macOS dock
"-Dmb.jetty.port=3000"]}
;; alias for CI-specific options.
:ci
{:jvm-opts ["-Xmx2g"
;; normally CircleCI sets `CI` as an env var, so this is mostly to replicate that locally.
"-Dci=TRUE"]}
;; include EE source code.
:ee
{:extra-paths ["enterprise/backend/src"]}
;; Include EE tests.
;; for ee dev: :dev:ee:ee-dev
;; for ee tests: clojure -X:dev:ee:ee-dev:test
:ee-dev
{:extra-paths ["enterprise/backend/test"]}
;; these aliases exist for symmetry with the ee aliases. Empty for now.
:oss
{}
:oss-dev
{}
;; for local dev -- include the drivers locally with :dev:drivers
:drivers
{:extra-deps
{metabase/driver-modules {:local/root "modules/drivers"}}}
;; for local dev: include drivers as well as their tests.
;;
;; clojure -X:dev:drivers:drivers-dev:test
;;
;; or
;;
;; clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test (for EE)
:drivers-dev
{:extra-paths
["modules/drivers/bigquery/test"
"modules/drivers/bigquery-cloud-sdk/test"
"modules/drivers/druid/test"
"modules/drivers/google/test"
"modules/drivers/googleanalytics/test"
"modules/drivers/mongo/test"
"modules/drivers/oracle/test"
"modules/drivers/presto/test"
"modules/drivers/presto-common/test"
"modules/drivers/presto-jdbc/test"
"modules/drivers/redshift/test"
"modules/drivers/snowflake/test"
"modules/drivers/sparksql/test"
"modules/drivers/sqlite/test"
"modules/drivers/sqlserver/test"
"modules/drivers/vertica/test"]}
;;; Linters
;; clojure -X:dev:ee:ee-dev:drivers:drivers-dev:namespace-checker
:namespace-checker
{:exec-fn metabase.linters.namespace-checker/check-namespace-decls
:exec-args {:prefix-rewriting false}}
;; clojure -M:dev:ee:ee-dev:drivers:drivers-dev:check
:check
{:extra-deps {athos/clj-check {:git/url "https://github.com/athos/clj-check.git"
:sha "518d5a1cbfcd7c952f548e6dbfcb9a4a5faf9062"}}
:main-opts ["-m" "clj-check.check"]}
;; clojure -X:dev:ee:ee-dev:drivers:drivers-dev:eastwood
:eastwood
{:exec-fn metabase.linters.eastwood/eastwood
:exec-args {;; manually specify the source paths for the time being (exclude test paths) until we fix Eastwood
;; errors in the test paths (once PR #17193 is merged)
:source-paths ["src"
"shared/src"
"enterprise/backend/src"
"modules/drivers/bigquery/src"
"modules/drivers/bigquery-cloud-sdk/src"
"modules/drivers/druid/src"
"modules/drivers/google/src"
"modules/drivers/googleanalytics/src"
"modules/drivers/mongo/src"
"modules/drivers/oracle/src"
"modules/drivers/presto/src"
"modules/drivers/presto-common/src"
"modules/drivers/presto-jdbc/src"
"modules/drivers/redshift/src"
"modules/drivers/snowflake/src"
"modules/drivers/sparksql/src"
"modules/drivers/sqlite/src"
"modules/drivers/sqlserver/src"
"modules/drivers/vertica/src"]
:add-linters [:unused-private-vars
;; These linters are pretty useful but give a few false
;; positives and can't be selectively disabled (yet)
;;
;; For example see https://github.com/jonase/eastwood/issues/193
;;
;; It's still useful to re-enable them and run them every once
;; in a while because they catch a lot of actual errors too.
;; Keep an eye on the issue above and re-enable them if we can
;; get them to work
#_:unused-fn-args
#_:unused-locals]
:exclude-linters [ ;; Turn this off temporarily until we finish removing
;; self-deprecated functions & macros
:deprecations
;; this has a fit in libs that use Potemkin `import-vars` such
;; as `java-time`
:implicit-dependencies
;; too many false positives for now
:unused-ret-vals]}}
;; clojure -T:whitespace-linter
:whitespace-linter
{:deps {com.github.camsaul/whitespace-linter {:sha "b25716745f5875194bc38364e498d0ddda51f4b0"}}
:ns-default whitespace-linter
:exec-args {:paths ["./.dir-locals.el"
"./deps.edn"
"./package.json"
"./shadow-cljs.edn"
".circleci"
".github"
"bin"
"enterprise"
"frontend"
"resources"
"shared"
"src"
"test"]
:include-patterns ["\\.clj.?$"
"\\.edn$"
"\\.el$"
"\\.html$"
"\\.json$"
"\\.jsx?$"
"\\.sh$"
"\\.yaml$"
"\\.yml$"]
:exclude-patterns ["resources/i18n/.*\\.edn$"
"resources/frontend_client"
"resources/frontend_shared"
"resources/html-entities.edn"
"frontend/src/cljs"
"frontend/test/metabase/lib/urls\\.unit\\.spec\\.js$"
"frontend/test/metabase/lib/formatting\\.unit\\.spec\\.js$"
"shared/src/metabase/shared/util/currency\\.cljc$"]}}
;; clojure -X:dev:ee:ee-dev:test:cloverage
:cloverage
{:exec-fn metabase.cloverage-runner/run-project
:exec-args {:fail-threshold 69
:codecov? true
;; don't instrument logging forms, since they won't get executed as part of tests anyway
;; log calls expand to these
:exclude-call
[clojure.tools.logging/logf
clojure.tools.logging/logp]
:src-ns-path
["src" "enterprise/backend/src" "shared/src"]
:test-ns-path
["test" "enterprise/backend/test" "shared/test"]
:ns-regex
["^metabase.*" "^metabase-enterprise.*"]
;; don't instrument Postgres/MySQL driver namespaces, because we don't current run tests for them
;; as part of recording test coverage, which means they can give us false positives.
;;
;; regex literals aren't allowed in EDN. We parse them in `./test/cloverage.clj`
:ns-exclude-regex
["metabase\\.driver\\.mysql" "metabase\\.driver\\.postgres"]}
;; different port from `:test` so you can run it at the same time as `:test`.
:jvm-opts ["-Dmb.jetty.port=3002"]}
;;; building Uberjar
;; clojure -T:build uberjar
;; clojure -T:build uberjar :edition :ee
:build
{:deps {io.github.clojure/tools.build {:git/tag "v0.1.6", :git/sha "5636e61"}
com.github.seancorfield/depstar {:mvn/version "2.1.278"}
metabase/build.common {:local/root "bin/common"}
metabase/buid-mb {:local/root "bin/build-mb"}}
:ns-default build}
;;; Other misc convenience aliases
;; Profile Metabase start time with clojure -M:profile
:profile
{:main-opts ["-m" "metabase.core" "profile"]
:jvm-opts ["-XX:+CITime" ; print time spent in JIT compiler
"-XX:+PrintGC"]}
;; get the H2 shell with clojure -M:h2
:h2
{:main-opts ["-m" "org.h2.tools.Shell"]}
;; clojure -M:generate-automagic-dashboards-pot
:generate-automagic-dashboards-pot
{:main-opts ["-m" "metabase.automagic-dashboards.rules"]}
;; Start a Network REPL (nrepl) that you can connect your editor to.
;;
;; clojure -M:dev:nrepl (etc.)
:nrepl
{:extra-deps {nrepl/nrepl {:mvn/version "0.8.3"}}
:main-opts ["-m" "nrepl.cmdline"]}
;; TODO -- consider creating an alias that includes the `./bin` build-drivers & release code as well so we can work
;; on them all from a single REPL process.
}}

54
dev/src/dev/readme.md Normal file
View File

@@ -0,0 +1,54 @@
## Render png
Has some helper functions to help out with rendering debugging.
In this namespace, you can run `(help)` to get a bit of help. It's principle usage right now is to render and debug the svg images.
### NOTE!
You must build the js bundle used to create the svgs with visx. Run `yarn build-static-viz` to ensure that this bundle is created and the file `resources/frontend_client/app/dist/lib-static-viz.bundle.js` exists
Example usage below:
```clojure
dev=> (require 'dev.render-png)
nil
dev=> (in-ns 'dev.render-png)
#object[clojure.lang.Namespace 0x14fef810 "dev.render-png"]
dev.render-png=> (help)
To render some html, call the function `preview-html`. This takes one argument, a map.
The keys in the map are `:chart` and either `:html-file` or `:html-inline`.
(preview-html {:chart :donut :html-inline some-html-to-render})
or
(preview-html {:chart :donut :html-file some-file-with-html})
This function will render the html and open an image.
Valid charts are `:donut`, `:line`, and `:bar`.
You can use {{chart}} in your html to indicate where the image of the chart should be embedded.
It will be <img src=data-uri-of-chart style="display: block; width: 100%">
nil
dev.render-png=> (preview-html {:chart :donut :html-file "chart.html"})
nil
dev.render-png=>
```
The steps were
1. require the namespace, so the code is loaded
2. `in-ns` to go "in" the namespace so we can easily call the functions
3. call the function we care about. It will open up an image preview.
An example chart.html is
```html
<div>
<h1>behold the donut</h1>
{{chart}}
<hr>
<h3>the donut has been beholden</h3>
</div>
```
This file should be saved at the root of the repository for the call to `preview-html` to find it.

View File

@@ -1,14 +1,20 @@
(ns dev.render-png
"Improve feedback loop for dealing with png rendering code"
"Improve feedback loop for dealing with png rendering code. Will create images using the rendering that underpins
pulses and subscriptions and open those images without needing to send them to slack or email."
(:require [clojure.java.io :as io]
[clojure.java.shell :as sh]
[clojure.string :as str]
[hiccup.core :as h]
[metabase.models.card :as card]
[metabase.models.user :as user]
[metabase.pulse :as pulse]
[metabase.pulse.render :as pulse-render]
[metabase.pulse.render.js-svg :as js-svg]
[metabase.pulse.render.png :as png]
[metabase.query-processor :as qp]
[metabase.query-processor.middleware.permissions :as qp.perms]
[toucan.db :as tdb]))
[toucan.db :as tdb])
(:import org.fit.cssbox.misc.Base64Coder))
;; taken from https://github.com/aysylu/loom/blob/master/src/loom/io.clj
(defn- os
@@ -46,15 +52,102 @@
user (tdb/select-one user/User)
query-results (binding [qp.perms/*card-id* nil]
(qp/process-query-and-save-execution!
(assoc dataset_query :async? false)
(-> dataset_query
(assoc :async? false)
(assoc-in [:middleware :process-viz-settings?] true))
{:executed-by (:id user)
:context :pulse
:card-id card-id}))
png-bytes (pulse-render/render-pulse-card-to-png (pulse/defaulted-timezone card)
card
query-results)
query-results
1000)
tmp-file (java.io.File/createTempFile "card-png" ".png")]
(with-open [w (java.io.FileOutputStream. tmp-file)]
(.write w ^bytes png-bytes))
(.deleteOnExit tmp-file)
(open tmp-file)))
(defn open-png-bytes [bytes]
(let [tmp-file (java.io.File/createTempFile "card-png" ".png")]
(with-open [w (java.io.FileOutputStream. tmp-file)]
(.write w ^bytes bytes))
(.deleteOnExit tmp-file)
(open tmp-file)))
(defn render-img-data-uri
"Takes a PNG byte array and returns a Base64 encoded URI"
[img-bytes]
(str "data:image/png;base64," (String. (Base64Coder/encode img-bytes))))
(defn svg-image [kind]
(let [line|bar-data [["2015-02-01T00:00:00-08:00" 443]
["2015-03-01T00:00:00-08:00" 875]
["2015-04-01T00:00:00-07:00" 483]
["2015-05-01T00:00:00-07:00" 421]]
donut-data [["alpha" 32]
["beta" 49]
["gamma" 23]
["delta" 67]]
donut-colors {"alpha" "red"
"beta" "green"
"gamma" "blue"
"delta" "yellow"}]
(case kind
:line (js-svg/timelineseries-line line|bar-data)
:bar (js-svg/timelineseries-bar line|bar-data)
:donut (js-svg/categorical-donut donut-data donut-colors)
(throw (ex-info (str "Invalid chart type: " kind "\n Valid choices are :line, :bar, :donut")
{})))))
(defn preview-html
"Chart type is one of :line, :bar, :donut. Html is a string with a placeholder {{chart}} which will be replaced with
the [:img {:src chart-placeholder}] and the resulting html will be opened."
[{:keys [chart html-file html-inline]}]
(let [chart-image (render-img-data-uri (svg-image chart))
chart-html (h/html [:img {:src chart-image :style "display: block; width: 100%"}])
html (cond html-file
(slurp html-file)
html-inline
(str "<html><body style=\"margin: 0; padding: 0; background-color: white;\">"
html-inline
"</body></html>"))
html (h/html (str/replace html #"\{\{chart\}\}" chart-html))]
(with-open [os (java.io.ByteArrayOutputStream.)]
(let [image-bytes (do (#'png/render-to-png! html os 1000)
(.toByteArray os))]
(open-png-bytes image-bytes)))))
(defn help []
(println
"
To render some html, call the function `preview-html`. This takes one argument, a map.
The keys in the map are `:chart` and either `:html-file` or `:html-inline`.
(preview-html {:chart :donut :html-inline some-html-to-render})
or
(preview-html {:chart :donut :html-file some-file-with-html})
This function will render the html and open an image.
Valid charts are `:donut`, `:line`, and `:bar`.
You can use {{chart}} in your html to indicate where the image of the chart should be embedded.
It will be <img src=data-uri-of-chart style=\"display: block; width: 100%\">
For instance
(preview-html {:chart :donut
:html-inline \"<div><h1>behold the donut</h1>{{chart}}</div>\"})
"))
(comment
(preview-html {:chart :donut :html-inline "
<div>
{{chart}}
<table>
<tr><td style=\"color: #509EE3; font-size: 24px; font-weight: 700; padding-right: 16px;\">500</td>
<td style=\"color: #7C8381; font-size: 24px; font-weight: 700;\">600</td>
</tr>
<tr><td style=\"color: #509EE3; font-size: 16px; font-weight: 700; padding-right: 16px;\">March</td>
<td style=\"color: #7C8381; font-size: 16px;\">April</td>
</tr>
</table>
</div>"}))

View File

@@ -1,37 +1,103 @@
## Getting Help
# Metabase documentation and resources
#### [FAQs](faq/start.md)
## Tutorials
### [Learn Metabase][learn]
Learn how to set Metabase up, build out your analytics, organize things and set permissions, and how to do data ops right.
## Getting help
### [Troubleshooting Guide][troubleshooting]
Problems, their causes, how to detect them, and how to fix them.
### [Metabase forum][forum]
A place to get help on installation, setting up as well as sharing tips and tricks.
### [FAQs][faq]
Frequently asked questions about Metabase.
#### [Troubleshooting Guide](troubleshooting-guide/index.md)
Have a problem and need help? Start with our troubleshooting guide.
## Metabase reference guides
## In-depth Guides
Documentation guides for the Metabase application.
#### [Users Guide](users-guide/start.md)
This is the go-to guide on asking questions and sharing answers using Metabase. You'll learn in depth about how questions are expressed, how to chart answers, as well as how to share questions and create dashboards.
### [Users Guide][users-guide]
#### [Admin Guide](administration-guide/start.md)
This guide is for advanced users and those who will be setting up and maintaining a Metabase installation. You'll learn how to set the instance up, how to configure common settings, how to manage user accounts, and how to add databases.
How to ask questions, how to visualize answers, as well as how to share questions and create dashboards.
#### [Operations Guide](operations-guide/start.md)
This guide contains more detailed information about how to install Metabase for production use. It covers topics like SSL termination, deploying via Docker Containers vs. Jars, as well as the tradeoffs involved.
### [Admin Guide][admin-guide]
## Enterprise Edition
How to set up Metabase, configure common settings, manage accounts and permissions, and add databases.
#### [Enterprise Features Guide](./enterprise-guide/start.md)
Here’s where to go for help using the features included in the Enterprise Edition of Metabase.
### [Operations Guide][operations-guide]
## For Developers
Learn how to install Metabase for production use. The guide covers topics like SSL termination, deploying via Docker Containers vs. JAR files, as well as the tradeoffs involved.
#### [Developers Guide](developers-guide.md)
This guide covers how to contribute back to the Metabase open source project. It includes setting up a development environment, running tests, and the contribution and product process Metabase follows.
### [Enterprise Guide][enterprise]
#### [Driver Development](developers-guide-drivers.md)
Want to write your own database driver? This guide lists existing community drivers and shows how to get started with driver development.
Here’s where to go for help using the features included in [Metabase Enterprise Edition][enterprise-landing].
## Metabase for developers
### [Developers Guide][developers]
Learn how to contribute to the Metabase open source project.
### [Driver Development][drivers]
This guide lists existing community drivers, and shows how to get started with driver development.
### [Embedding reference apps][embedding-ref-apps]
Code examples for embedding Metabase in applications.
## Metabase community
Connect with others using Metabase and catch up on the latest news.
### [Metabase forum][forum]
A place to get help on installation, setting up as well as sharing tips and tricks.
### [Data stories][data-stories]
Real stories about teams working and learning with data. You can also share your own stories.
### [Case studies][case-studies]
See how other organizations, big and small, have leveled up using Metabase.
### [Blog][blog]
Stay up to date on the latest from Metabase.
### [Source code repository on GitHub][source-code]
Metabase is open source: come on over and check out the code.
## Reference
#### [Anonymous Information Collection Reference](information-collection.md)
This describes the anonymous usage information we collect (if you opt-in) as well as why we collect it and the ways we use it.
### [Anonymous Information Collection Reference][info-collection]
This page describes the anonymous usage information we collect (only if you opt-in), why we collect it, and how we use it to improve Metabase.
[admin-guide]: administration-guide/start.md
[blog]: /blog
[case-studies]: https://www.metabase.com/case_studies/
[embedding-ref-apps]: https://github.com/metabase/embedding-reference-apps
[enterprise]: enterprise-guide/start.md
[enterprise-landing]: /enterprise
[data-stories]: /community
[developers]: developers-guide/start.md
[drivers]: developers-guide-drivers.md
[faq]: faq/start.md
[forum]: https://discourse.metabase.com/
[info-collection]: information-collection.md
[learn]: /learn
[operations-guide]: operations-guide/start.md
[source-code]: https://github.com/metabase/metabase
[troubleshooting]: troubleshooting-guide/index.md
[users-guide]: users-guide/start.md

View File

@@ -12,8 +12,6 @@
In the main navigation bar, click on the **gears** icon in the top right, and select **Admin**.
![profiledropdown](images/ProfileDropdown.png)
Once in the Admin section, select the **Databases** tab from the navigation bar at the top of the screen. You’ll see a list of your connected databases (if any). To connect a database to Metabase, click **Add database** and follow the connection instructions for your database.
Although connection details differ database to database, in general you'll need to get connection info from your database admin, usually some combination of hostname (sometimes called endpoint), port, database username and password, and the name of the database.

View File

@@ -110,17 +110,17 @@ You can also designate a column as the table's **primary key** or **foreign key*
- Category
- Comment
- Description
- Common
- Number
- Title
- Common
- **Location**
- City
- Country
- Latitude
- Longitude
- State
- Zip Code
- **Financial**
- Cost
- Currency
- Discount
- Gross margin
- Income
@@ -143,7 +143,12 @@ You can also designate a column as the table's **primary key** or **foreign key*
- Creation date
- Creation time
- Creation timestamp
- Deletion date
- Deletion time
- Deletion timestamp
- Updated date
- Updated time
- Updated timestamp
- Join date
- Join time
- Join timestamp
@@ -159,6 +164,7 @@ You can also designate a column as the table's **primary key** or **foreign key*
- URL
- **Other**
- Field containing JSON
- No semantic type
### Casting to a specific data type

View File

@@ -36,6 +36,12 @@ Right now, the only special role someone can have is Admin. The only difference
To make someone an admin, click on the Groups dropdown and click the check mark next to the Administrators group.
### Unsubscribe from all subscriptions / alerts
This action will delete any dashboard subscriptions or alerts the person has created, and remove them as a recipient from any other subscriptions or alerts.
This action doesn't affect email distribution lists that are managed outside of Metabase.
### Adding people to Groups
Adding people to groups allows you to assign [data access](05-setting-permissions.md) and [collection permissions](06-collections.md) to them. To add someone to one or more groups, just click the Groups dropdown and click the checkboxes next to the group(s) you want to add the person to.

View File

@@ -1,89 +1,80 @@
## Setting Data Access Permissions
# Permissions overview
There are always going to be sensitive bits of information in your databases and tables, and thankfully Metabase provides a simple way to ensure that people on your team only see the data they’re supposed to.
### How permissions work in Metabase
## How permissions work in Metabase
Metabase uses a group-based approach to set permissions and restrictions on your databases and tables. At a high level, to set up permissions in your Metabase instance you’ll need to create one or more groups, add members to those groups, and then choose what level of database and SQL access those groups should have.
Metabase uses a group-based approach to set permissions. At a high-level, you can set permissions on two things: data and collections. **Data permissions** are about defining what raw data groups are allowed to use when creating new questions (i.e., self-service analytics). **Collection permissions** determine what existing dashboards and questions groups can see. On some plans, you can also sandbox data, which "filters" what data people can see when they view a particular questions, such as limiting the rows or columns they can see.
A user can be a member of multiple groups, and if one of the groups they’re in has access to a particular database or table, but another group they’re a member of does not, then they **will** have access to that database.
You can set permissions on:
In addition to setting permissions on your databases and tables, you can also [set access permissions on the collections](06-collections.md) where your dashboards, questions, and pulses are saved. Collection permissions can be set and edited from the collection itself, or the Admin Panel.
- [Databases connected to Metabase][data-permissions]
- [Tables and schemas in those databases][table-permissions]
- [Rows and columns of a table][data-sandboxing] (only on some plans)
- [Collections of questions and dashboards][collections]
### Groups
For plans that include [SQL Snippet Folders][sql-snippet-folders], you can also set permissions on those folders.
To view and manage your groups, go to the Admin Panel, click on the People section, and then click on Groups from the side menu.
To determine who has access to what, you’ll need to create one or more groups, choose which level of access that group has to different databases, collections, and so on, then add people to that group.
### Key points regarding permissions
Some key things to keep in mind when thinking about permissions in Metabase:
- Permissions are granted to groups, not people.
- People can be in more than one group.
- If a person is in multiple groups, they will have the most permissive access granted to them across all of their groups. For example, if they are part of three groups, and two of those groups don't have permissions to a database, but the third group they're in can query that database, then that person will have access to that database.
## Groups
To view and manage your groups, go to the __Admin Panel__ > __People__, and then click on __Groups__ from the side menu.
![Groups](images/groups.png)
#### Special default groups
### Special default groups
You’ll notice that you already have two default groups: Administrators and All Users. These are special groups that can’t be removed.
Every Metabase has two default groups: Administrators and All Users. These are special groups that can’t be removed.
You’ll also see that you’re a member of the **Administrators** group — that’s why you were able to go to the Admin Panel in the first place. So, to make someone an admin of Metabase you just need to add them to this group. Metabase admins can log into the Admin Panel and make changes there, and they always have unrestricted access to all data that you have in your Metabase instance. So be careful who you add to the Administrator group!
#### Administrators
You’re a member of the **Administrators** group — that’s why you were able to go to the Admin Panel in the first place. To make someone an admin of Metabase, you just need to add them to this group. Metabase admins can log into the Admin Panel and make changes there, and they always have unrestricted access to all data that you have in your Metabase instance. So be careful who you add to the Administrator group!
#### All users
The **All Users** group is another special one. Every Metabase user is always a member of this group, though they can also be a member of as many other groups as you want. We recommend using the All Users group as a way to set default access levels for new Metabase users. If you have [Google single sign-on](10-single-sign-on.md) enabled, new users who join that way will be automatically added to the All Users group.
#### An important note on the All Users group
As we mentioned above, a person is given the _most permissive_ setting she has for a given database/schema/table across _all_ groups she's in. Because of that, it's important that your All Users group should never have _greater_ access for an item than a group for which you're trying to restrict access — otherwise the more permissive setting will win out. This goes for both data access as well as [collection permission](06-collections.md) settings.
As we mentioned above, a user is given the _most permissive_ setting she has for a given database/schema/table across _all_ groups she is in. Because of that, it is important that your All Users group should never have _greater_ access for an item than a group for which you're trying to restrict access — otherwise the more permissive setting will win out. This goes for both data access as well as [collection permission](06-collections.md) settings.
### Managing groups
If you’ve set up the [Slack integration](09-setting-up-slack.md) and enabled [Metabot](../users-guide/11-metabot.md), you’ll also see a special **Metabot** group, which will allow you to restrict which questions your users will be able to access in Slack via Metabot.
#### Creating a group and adding people to it
#### Managing groups
From the Groups section, click the `Add a group` button to create a new group. We recommend creating groups that correspond to the teams your company or organization has, such as Human Resources, Engineering, Finance, etc. Click the X icon to the right of a group in the list to remove it (remember, you can’t remove the special default groups). By default, newly created groups don’t have access to anything.
From the Admin > Groups tab, click the **Add a group** button to create a new group. We recommend creating groups that correspond to the teams your company or organization has, such as Human Resources, Engineering, Finance, and so on. By default, newly created groups don’t have access to anything.
Click into a group and then click `Add members` to add users to that group. Click on the X on the right side of a group member to remove them from that group. You can also add and remove users from groups from the People list using the dropdown in the Groups column.
### Permissions view
#### Removing a group
Now that you have some groups, you’ll want to control their data access by going to the `Permissions` section of the Admin Panel. You’ll see an interactive table that displays all of your databases and all of your groups, and the level of access your groups have for each database.
To remove a group, click the X icon to the right of a group in the list to remove it (remember, you can’t remove the special default groups).
![Permissions view](images/permissions.png)
## Further reading
You can click on any cell in the table to change a group’s access level. When you’re done making your changes, just click the `save changes` button in the top-right, and you’ll see a confirmation dialog summarizing the changes.
![Changing access level](images/change-access.png)
At the database level, there are two different kinds of access you can set: data access, and SQL (or native query) access.
#### Data access
- **Unrestricted access:** can access data from all tables (within all namespaces/schemas, if your database uses those), including any tables that might get added to this database in the future.
- **Limited access:** can only access the tables that you explicitly select within namespaces/schemas you explicitly select. If a new table gets added to this database in the future, access to it will not automatically be given. Saved questions based on tables the user doesn’t have access to won’t show up in the list of saved questions, dashboard cards based on those questions won’t appear, and they won’t be able to ask new questions about those tables. If every card on a dashboard is hidden for a user, then that dashboard won’t be shown to them in the dashboard list.
- **No access:** can’t see anything based on data contained in this database. Won’t see saved questions based on tables contained in this database, and won’t be able to ask new questions about those tables.
#### SQL (or native query) access
- **Write raw queries:** can write new SQL/native queries using the SQL editor. This access level requires the group to additionally have Unrestricted data access for the database in question, since SQL queries can circumvent table-level permissions.
- **No access**: can't view, write, or edit SQL/native queries. Users will still be able to view the results of questions created from SQL/native queries, but not the code itself. They also won't see the "View the SQL" button when composing custom questions in the notebook editor.
If you select `Limit access` for one of your databases, your view will change to show the contents of that database. If the database utilizes namespaces or schemas, you’ll see a list of all the schemas in the database, and the level of data access each group has for them. Similarly, if you select `Limit access` on one of your schemas, you’ll drill down a level and see all the tables within it. From these views, you can navigate back by using the breadcrumb links in the top-left, and you can always drill down into a database or schema using the link under its name in the left column.
![Table permissions](images/table-permissions.png)
Data access levels for schemas follows the same pattern as for databases:
- **Unrestricted access:** can access all tables in this schema, including any tables that might get added in the future.
- **Limited access:** can only access the tables that you explicitly select.
- **No access:** can’t access any tables in this schema.
Lastly, data access levels for tables are almost exactly the same as well:
- **Unrestricted access:** can ask questions about this table and see saved questions and dashboard cards using this table.
- **No access:** can’t ask questions about this table or see saved questions or dashboard cards using this table.
_Note: you’ll notice that tables don’t have the option for limited access. If you need to set column-level or row-level data permissions, check out the [data sandboxing](https://www.metabase.com/docs/latest/enterprise-guide/data-sandboxes.html) feature of the [Enterprise Edition](https://www.metabase.com/enterprise/)._
For more, check out our [Guide to data permissions](https://www.metabase.com/learn/organization/organization/data-permissions.html).
### A note about Pulses
Pulses act a bit differently with regard to permissions. When a user creates a new Pulse, they will only have the option to include saved questions that they have permission to view. Note, however, that they are not prevented from emailing that Pulse to anyone, or posting that Pulse to a Slack channel (if you have Slack integration set up), regardless of the recipients’ permissions. Unlike dashboards, where individual cards are blocked based on a user’s permissions, a Pulse will always render all of its cards.
Checkout our track on [Permissions][permissions] in Learn Metabase.
---
## Next: collections
## Next: Data permissions
Metabase lets you create and set permissions on collections of dashboards and questions. [Learn how](06-collections.md).
Metabase lets you [set permissions on databases and their tables][data-permissions].
[collections]: 06-collections.md
[dashboard-subscriptions]: ../users-guide/dashboard-subscriptions.md
[data-permissions]: data-permissions.md
[pulses]: ../users-guide/10-pulses.md
[data-sandboxing]: ../enterprise-guide/data-sandboxes.md
[permissions]: /learn/permissions/
[sandbox-columns]: /learn/permissions/data-sandboxing-column-permissions.html
[sandbox-rows]: /learn/permissions/data-sandboxing-row-permissions.html
[slack-integration]: 09-setting-up-slack.md
[sql-snippet-folders]: ../enterprise-guide/sql-snippets.md
[table-permissions]: data-permissions.md#table-permissions

Some files were not shown because too many files have changed in this diff Show More