If you plan to work on the Metabase code and make changes then you’ll need to understand a few more things.
The Metabase application has two basic components:
Both components are built and assembled together into a single jar file which runs the entire application.
Metabase depends on lots of third-party libraries to run, so you’ll need to keep those up to date. The Clojure CLI will automatically fetch the dependencies when needed. With JavaScript dependencies, however, you’ll need to kick off the installation process manually.
# javascript dependencies
$ yarn
Run your backend development server with
clojure -M:run
Start the frontend build process with
yarn build-hot
We use these technologies for our FE build process to allow us to use modules, es6 syntax, and css variables.
Frontend tasks are executed using yarn
. All available tasks can be found in package.json
under scripts.
To build the frontend client without watching for changes, you can use:
$ yarn build
If you’re working on the frontend directly, you’ll most likely want to reload changes on save, and in the case of React components, do so while maintaining state. To start a build with hot reloading, use:
$ yarn build-hot
Note that at this time if you change CSS variables, those changes will only be picked up when a build is restarted.
There is also an option to reload changes on save without hot reloading if you prefer that.
$ yarn build-watch
Some systems may have trouble detecting changes to frontend files. You can enable filesystem polling by uncommenting the watchOptions
clause in webpack.config.js
. If you do this it may be worth making git ignore changes to webpack config, using git update-index --assume-unchanged webpack.config.js
All frontend tests are located in frontend/test
directory. Run all frontend tests with
yarn test
which will run unit and Cypress end-to-end tests in sequence.
By default, we use a simple source mapping option that is optimized for speed.
If you run into issues with breakpoints, especially inside jsx, please set env variable BETTER_SOURCE_MAPS
to true before you run the server.
Example:
BETTER_SOURCE_MAPS=true yarn dev
End-to-end tests simulate realistic sequences of user interactions. Read more about how we approach end-to-end testing with Cypress.
Cypress end-to-end tests use an enforced file naming convention <test-suite-name>.cy.spec.js
to separate them from unit tests.
Unit tests are focused around isolated parts of business logic.
Unit tests use an enforced file naming convention <test-suite-name>.unit.spec.js
to separate them from end-to-end tests.
yarn test-unit # Run all tests at once
yarn test-unit-watch # Watch for file changes
Clojure REPL is the main development tool for the backend. There are some directions below on how to setup your REPL for easier development.
And of course your Jetty development server is available via
clojure -M:run
Most of the drivers Metabase uses to connect to external data warehouse databases are separate projects under the
modules/
subdirectory. When running Metabase via clojure
, you’ll need to build these drivers in order to have access
to them. You can build drivers as follows:
# Build the 'mongo' driver
./bin/build-driver.sh mongo
(or)
# Build all drivers
./bin/build-drivers.sh
For development when running various Clojure tasks you can add the drivers
and drivers-dev
aliases to merge the
drivers’ dependencies and source paths into the Metabase project:
# Install dependencies, including for drivers
clojure -P -X:dev:ci:drivers:drivers-dev
Run unit tests with
# OSS tests only
clojure -X:dev:test
# OSS + EE tests
clojure -X:dev:ee:ee-dev:test
or a specific test (or test namespace) with
# run tests in only one namespace (pass in a symbol)
clojure -X:dev:test :only metabase.api.session-test
# run one specific test (pass in a qualified symbol)
clojure -X:dev:test :only metabase.api.session-test/my-test
# run tests in one specific folder (test/metabase/util in this example)
# pass arg in double-quotes so Clojure CLI interprets it as a string;
# our test runner treats strings as directories
clojure -X:dev:test :only '"test/metabase/util"'
By default, the tests only run against the h2
driver. You can specify which drivers to run tests against with the env var DRIVERS
:
DRIVERS=h2,postgres,mysql,mongo clojure -X:dev:drivers:drivers-dev:test
Some drivers require additional environment variables when testing since they are impossible to run locally (such as Redshift and Bigquery). The tests will fail on launch and let you know what parameters to supply if needed.
clj-kondo
must be installed separately; see https://github.com/clj-kondo/clj-kondo/blob/master/doc/install.md for
instructions.
# Run Eastwood
clojure -X:dev:ee:ee-dev:drivers:drivers-dev:eastwood
# Run the namespace checker
clojure -X:dev:ee:ee-dev:drivers:drivers-dev:namespace-checker
# Run clj-kondo
clj-kondo --parallel --lint src shared/src enterprise/backend/src --config lint-config.edn
.dir-locals.el
contains some Emacs Lisp that tells clojure-mode
how to indent Metabase macros and which arguments are docstrings. Whenever this file is updated,
Emacs will ask you if the code is safe to load. You can answer !
to save it as safe.
By default, Emacs will insert this code as a customization at the bottom of your init.el
.
You’ll probably want to tell Emacs to store customizations in a different file. Add the following to your init.el
:
(setq custom-file (concat user-emacs-directory ".custom.el")) ; tell Customize to save customizations to ~/.emacs.d/.custom.el
(ignore-errors ; load customizations from ~/.emacs.d/.custom.el
(load-file custom-file))
First, install the following extension:
Note: Debugger for Chrome has been deprecated. You can safely delete it as Visual Studio Code now has a bundled JavaScript Debugger that covers the same functionality.
Before starting the debugging session, make sure that Metabase is built and running. Choose menu View, Command Palette, search for and choose Tasks: Run Build Task. Alternatively, use the corresponding shortcut Ctrl+Shift+B
. The built-in terminal will appear to show the progress, wait a few moment until webpack indicates a complete (100%) bundling.
To begin debugging Metabase, switch to the Debug view (shortcut: Ctrl+Shift+D
) and then select one of the two launch configurations from the drop-down at the top:
After that, begin the debugging session by choosing menu Run, Start Debugging (shortcut: F5
).
For more details, please refer to the complete VS Code documentation on Debugging.
These instructions allow you to work on Metabase codebase on Windows, Linux, or macOS using Visual Studio Code, without manually installing the necessary dependencies. This is possible by leveraging Docker container and the Remote Containers extension from VS Code.
For more details, please follow the complete VS Code guide on Developing inside a Container. The summary is as follows.
Requirements:
Important: Ensure that Docker is running properly and it can be used to download an image and launch a container, e.g. by running:
$ docker run hello-world
If everything goes well, you should see the following message:
Hello from Docker!
This message shows that your installation appears to be working correctly.
Steps:
Clone Metabase repository
Launch VS Code and open your cloned Metabase repository
From the View menu, choose Command Palette… and then find Remote-Container: Reopen in Container. (VS Code may also prompt you to do this with an “Open in container” popup). Note: VS Code will create the container for the first time and it may take some time. Subsequent loads should be much faster.
Use the menu View, Command Palette, search for and choose Tasks: Run Build Task (alternatively, use the shortcut Ctrl+Shift+B
).
After a while (after all JavaScript and Clojure dependencies are completely downloaded), open localhost:3000 with your web browser.