diff --git a/.circleci/config.yml b/.circleci/config.yml index 97533d0389e37ac9722b6fea85a7f58e922249a4..11dfd0fccc71812779c1a84080f75bcbacf8ce2a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -201,15 +201,15 @@ commands: steps: - restore_cache: keys: - - be-deps-v2-{{ checksum "project.clj" }} - - be-deps-v2- + - be-deps-v4-{{ checksum "project.clj" }} + - be-deps-v4- restore-fe-deps-cache: steps: - restore_cache: keys: - - fe-deps-v2-{{ checksum "yarn.lock" }} - - fe-deps-v2- + - fe-deps-v4-{{ checksum "yarn.lock" }} + - fe-deps-v4- run-yarn-command: parameters: @@ -361,7 +361,7 @@ jobs: - restore-be-deps-cache - run: lein with-profile +include-all-drivers,+cloverage,+junit,+<< parameters.edition >> deps - save_cache: - key: be-deps-v2-{{ checksum "project.clj" }} + key: be-deps-v4-{{ checksum "project.clj" }} paths: - /home/circleci/.m2 @@ -495,7 +495,7 @@ jobs: name: Save yarn checksum command: md5sum yarn.lock > yarn.lock.checksum - save_cache: - key: fe-deps-v2-{{ checksum "yarn.lock" }} + key: fe-deps-v4-{{ checksum "yarn.lock" }} paths: - /home/circleci/.yarn - /home/circleci/.yarn-cache @@ -562,7 +562,7 @@ jobs: # restore already-built uberjar - restore_cache: keys: - - uberjar-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }}-{{ checksum "./frontend-checksums.txt" }}-{{ checksum "./modules-checksums.txt" }} + - uberjar-v4-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }}-{{ checksum "./frontend-checksums.txt" }}-{{ checksum "./modules-checksums.txt" }} # restore the local maven installation of Metabase which is needed for building drivers - restore_cache: keys: @@ -570,13 +570,13 @@ jobs: # restore already-built drivers - restore_cache: keys: - - drivers-v3-{{ checksum "./modules-checksums.txt" }}-{{ checksum "./backend-checksums.txt" }} - - drivers-v3-{{ checksum "./modules-checksums.txt" }} - - drivers-v3- + - drivers-v4-{{ checksum "./modules-checksums.txt" }}-{{ checksum "./backend-checksums.txt" }} + - drivers-v4-{{ checksum "./modules-checksums.txt" }} + - drivers-v4- # restore already-built frontend - restore_cache: keys: - - frontend-{{ checksum "./frontend-checksums.txt" }} + - frontend-v4-{{ checksum "./frontend-checksums.txt" }} - run: name: Install Clojure CLI command: > @@ -605,11 +605,14 @@ jobs: no_output_timeout: 10m - store_artifacts: path: /home/circleci/metabase/metabase/target/uberjar/metabase.jar - # Cache the built uberjar + - store_artifacts: + path: /home/circleci/metabase/metabase/resources/version.properties + # Cache the built uberjar & version.properties - save_cache: - key: uberjar-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }}-{{ checksum "./frontend-checksums.txt" }}-{{ checksum "./modules-checksums.txt" }} + key: uberjar-v4-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }}-{{ checksum "./frontend-checksums.txt" }}-{{ checksum "./modules-checksums.txt" }} paths: - /home/circleci/metabase/metabase/target/uberjar/metabase.jar + - /home/circleci/metabase/metabase/resources/version.properties # Cache the maven installation of metabase-core - save_cache: key: metabase-core-{{ checksum "./backend-checksums.txt" }} @@ -617,7 +620,7 @@ jobs: - /home/circleci/.m2/repository/metabase-core # Cache the built drivers - save_cache: - key: drivers-v3-{{ checksum "./modules-checksums.txt" }}-{{ checksum "./backend-checksums.txt" }} + key: drivers-v4-{{ checksum "./modules-checksums.txt" }}-{{ checksum "./backend-checksums.txt" }} paths: - /home/circleci/metabase/metabase/modules/drivers/bigquery/target - /home/circleci/metabase/metabase/modules/drivers/druid/target @@ -634,7 +637,7 @@ jobs: - /home/circleci/metabase/metabase/modules/drivers/vertica/target # Cache the built frontend - save_cache: - key: frontend-{{ checksum "./frontend-checksums.txt" }} + key: frontend-v4-{{ checksum "./frontend-checksums.txt" }} paths: - /home/circleci/metabase/metabase/resources/frontend_client @@ -665,12 +668,7 @@ jobs: before-steps: - restore_cache: keys: - - uberjar-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }} - - run: - name: Generate version file - environment: - MB_EDITION: << parameters.edition >> - command: ./bin/build version + - uberjar-v4-<< parameters.edition >>-{{ checksum "./backend-checksums.txt" }} - store_artifacts: path: /home/circleci/metabase/metabase/cypress - store_test_results: diff --git a/Dockerfile b/Dockerfile index 55d9aaef4f8ea36ea1bd4ee81fd709d1871dfce1..f2020aed70b8426d42eddb37f3b6d2fd74fce607 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,7 +45,7 @@ RUN yarn ADD . . # build the app -RUN bin/build +RUN INTERACTIVE=false bin/build # import AWS RDS cert into /etc/ssl/certs/java/cacerts ADD https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem . diff --git a/OSX/deps.edn b/OSX/deps.edn index 20c635d42cd50152e705525a68fa640c76921c86..b1c58d89fe70fab455f96e8a8f3ca8b02396eec7 100644 --- a/OSX/deps.edn +++ b/OSX/deps.edn @@ -1,12 +1,10 @@ {:paths ["./"] :deps - {org.clojure/data.xml {:mvn/version "0.0.8"} - cheshire {:mvn/version "5.8.1"} - clj-http {:mvn/version "3.9.1"} - clj-tagsoup {:mvn/version "0.3.0"} - commons-io/commons-io {:mvn/version "2.6"} - colorize {:mvn/version "0.1.1"} - environ {:mvn/version "1.1.0"} - hiccup {:mvn/version "1.0.5"} - org.flatland/ordered {:mvn/version "1.5.7"}}} + {common/common {:local/root "../bin/common"} + org.clojure/data.xml {:mvn/version "0.0.8"} + cheshire/cheshire {:mvn/version "5.8.1"} + clj-http/clj-http {:mvn/version "3.9.1"} + clj-tagsoup/clj-tagsoup {:mvn/version "0.3.0"} + hiccup/hiccup {:mvn/version "1.0.5"} + org.flatland/ordered {:mvn/version "1.5.7"}}} diff --git a/OSX/macos_release.clj b/OSX/macos_release.clj index 5f3b7712ed5dd7c729d0304c556f2a5f5657f2c6..2a486e83305446599ac64e20698156899222d632 100644 --- a/OSX/macos_release.clj +++ b/OSX/macos_release.clj @@ -4,13 +4,11 @@ [macos-release [build :as build] [codesign :as codesign] - [common :as c] [create-dmg :as create-dmg] [notarize :as notarize] [sparkle-artifacts :as sparkle-artifacts] - [upload :as upload]])) - -(set! *warn-on-reflection* true) + [upload :as upload]] + [metabuild-common.core :as u])) (def ^:private steps* (ordered-map/ordered-map @@ -29,17 +27,13 @@ (thunk))) (defn- do-steps! [steps] - (c/announce "Running steps: %s" steps) + (u/announce "Running steps: %s" steps) (doseq [step-name steps] (do-step! step-name)) - (c/announce "Success.")) + (u/announce "Success.")) (defn -main [& steps] - (let [steps (or (seq steps) - (keys steps*))] - (try - (do-steps! steps) - (catch Throwable e - (println (colorize/red (pr-str e))) - (System/exit -1)))) - (System/exit 0)) + (u/exit-when-finished-nonzero-on-exception + (let [steps (or (seq steps) + (keys steps*))] + (do-steps! steps)))) diff --git a/OSX/macos_release/common.clj b/OSX/macos_release/common.clj index af64e1ebee0e15f754b5d809a1fb67b76db2280d..4459042e06dd7274379e96913840ecd9491b592f 100644 --- a/OSX/macos_release/common.clj +++ b/OSX/macos_release/common.clj @@ -1,9 +1,23 @@ (ns macos-release.common (:require [clojure.string :as str] - [colorize.core :as colorize] - [environ.core :as env]) - (:import [java.io BufferedReader File InputStreamReader] - org.apache.commons.io.FileUtils)) + [environ.core :as env] + [metabuild-common.core :as u] + [potemkin :as p]) + (:import java.io.File)) + +(comment u/keep-me) + +(p/import-vars + [u + announce + assert-file-exists + copy-file! + create-directory-unless-exists! + delete-file! + safe-println + sh + sh* + step]) (def ^String macos-source-dir "e.g. /Users/cam/metabase/OSX" @@ -20,142 +34,19 @@ "e.g. /Users/cam/metabase/osx-artifacts" (str root-directory "/osx-artifacts")) -;;; ---------------------------------------------------- Util Fns ---------------------------------------------------- - -(def ^:dynamic *steps* []) - -(def ^:private step-indent (str/join (repeat 2 \space))) - -(defn- steps-indent [] - (str/join (repeat (count *steps*) step-indent))) - -(defn safe-println [& args] - (locking println - (print (steps-indent)) - (apply println args))) - -(defn announce - "Like `println` + `format`, but outputs text in green. Use this for printing messages such as when starting build - steps." - ([s] - (safe-println (colorize/magenta s))) - - ([format-string & args] - (announce (apply format (str format-string) args)))) - -(defn do-step [step thunk] - (safe-println (colorize/green (str step))) - (binding [*steps* (conj *steps* step)] - (try - (thunk) - (catch Throwable e - (throw (ex-info (str step) {} e)))))) - -(defmacro step {:style/indent 1} [step & body] - `(do-step ~step (fn [] ~@body))) - (defn exists? [^String filename] (when filename (.exists (File. filename)))) -(defn assert-file-exists - "If file with `filename` exists, return `filename` as is; otherwise, throw Exception." - ^String [filename & [message]] - (when-not (exists? filename) - (throw (ex-info (format "File %s does not exist. %s" (pr-str filename) (or message "")) {:filename filename}))) - (str filename)) - -(defn create-directory-unless-exists! [^String dir] - (when-not (exists? dir) - (step (format "Creating directory %s..." dir) - (.mkdirs (File. dir)))) - dir) - (defn artifact "Return the full path of a file in the build artifacts directory." ^String [filename] - (create-directory-unless-exists! artifacts-directory) + (when-not (u/file-exists? artifacts-directory) + (create-directory-unless-exists! artifacts-directory)) (str artifacts-directory "/" filename)) -(defn delete-file! - "Delete a file or directory if it exists." - ([^String filename] - (step (format "Deleting %s..." filename) - (if (exists? filename) - (let [file (File. filename)] - (if (.isDirectory file) - (FileUtils/deleteDirectory file) - (.delete file)) - (safe-println (format "Deleted %s." filename))) - (safe-println (format "Don't need to delete %s, file does not exist." filename))) - (assert (not (exists? filename))))) - - ([file & more] - (dorun (map delete-file! (cons file more))))) - -(declare sh) - -(defn copy-file! [^String source ^String dest] - (let [source-file (File. (assert-file-exists source)) - dest-file (File. dest)] - ;; Use native `cp` rather than FileUtils or the like because codesigning is broken when you use those because they - ;; don't preserve symlinks or something like that. - (if (.isDirectory source-file) - (step (format "Copying directory %s -> %s" source dest) - (sh "cp" "-R" source dest)) - (step (format "Copying file %s -> %s" source dest) - (sh "cp" source dest)))) - (assert-file-exists dest)) - -(defn- read-lines [^java.io.BufferedReader reader {:keys [quiet? err?]}] - (loop [lines []] - (if-let [line (.readLine reader)] - (do - (when-not quiet? - (safe-println (if err? (colorize/red line) line))) - (recur (conj lines line))) - lines))) - -(defn- deref-with-timeout [dereffable timeout-ms] - (let [result (deref dereffable timeout-ms ::timed-out)] - (when (= result ::timed-out) - (throw (ex-info (format "Timed out after %d ms." timeout-ms) {}))) - result)) - -(def ^:private command-timeout-ms (* 15 60 1000)) ; 15 minutes - -(defn sh* - "Run a shell command. Like `clojure.java.shell/sh`, but prints output to stdout/stderr and returns results as a vector - of lines." - {:arglists '([cmd & args] [{:keys [dir quiet?]} cmd & args])} - [& args] - (step (colorize/blue (str "$ " (str/join " " (map (comp pr-str str) args)))) - (let [[opts & args] (if (map? (first args)) - args - (cons nil args)) - {:keys [dir]} opts - cmd-array (into-array (map str args)) - proc (.exec (Runtime/getRuntime) ^"[Ljava.lang.String;" cmd-array nil ^File (when dir (File. ^String dir)))] - (with-open [out-reader (BufferedReader. (InputStreamReader. (.getInputStream proc))) - err-reader (BufferedReader. (InputStreamReader. (.getErrorStream proc)))] - (let [exit-code (future (.waitFor proc)) - out (future (read-lines out-reader opts)) - err (future (read-lines err-reader (assoc opts :err? true)))] - {:exit (deref-with-timeout exit-code command-timeout-ms) - :out (deref-with-timeout out command-timeout-ms) - :err (deref-with-timeout err command-timeout-ms)}))))) - -(defn sh - "Run a shell command, returning its output if it returns zero or throwning an Exception if it returns non-zero." - {:arglists '([cmd & args] [{:keys [dir quiet?]} cmd & args])} - [& args] - (let [{:keys [exit out err], :as response} (apply sh* args)] - (if (zero? exit) - (concat out err) - (throw (ex-info (str/join "\n" (concat out err)) response))))) - (defn- version* [] - (let [[out] (sh (assert-file-exists (str root-directory "/bin/version"))) + (let [[out] (sh "git" "describe" "--abbrev=0" "--tags") [_ version] (re-find #"^v([\d.]+)" out)] (when-not (seq version) (throw (ex-info "Error parsing version." {:out out}))) diff --git a/OSX/release.sh b/OSX/release.sh new file mode 100755 index 0000000000000000000000000000000000000000..f44195faa4f3d0c1374365b37c985763cd18b18d --- /dev/null +++ b/OSX/release.sh @@ -0,0 +1,9 @@ +#! /usr/bin/env bash + +set -euo pipefail + +source "./bin/check-clojure-cli.sh" +check_clojure_cli + +cd OSX/macos_release +clojure -M -m macos-release $@ diff --git a/bin/build b/bin/build index 0a83b8bac6a2d7a47342ec7b114957e5550114ca..7833eef8487ec74df5643e65605eb60b84c49b55 100755 --- a/bin/build +++ b/bin/build @@ -1,82 +1,9 @@ #!/usr/bin/env bash -set -e +set -euo pipefail -MB_EDITION=${MB_EDITION:=oss} +source "./bin/check-clojure-cli.sh" +check_clojure_cli -if [ "$MB_EDITION" != ee ] && [ "$MB_EDITION" != oss ]; then - echo "MB_EDITION must be either 'ee' or 'oss'." - exit 1 -fi - -# Generate the resources/version.properties file -version() { - VERSION_INFO=$(./bin/version) - IFS=', ' read -a info <<< ${VERSION_INFO} - - echo "Tagging uberjar with version '$VERSION_INFO'..." - - # Ok, now generate the appropriate version.properties file. - echo "tag=${info[0]}" > resources/version.properties - echo "hash=${info[1]}" >> resources/version.properties - echo "branch=${info[2]}" >> resources/version.properties - echo "date=${info[3]}" >> resources/version.properties -} - -frontend-deps() { - echo "Running 'yarn' to download javascript dependencies..." && - yarn -} - -frontend() { - frontend-deps - echo "Running 'webpack' with NODE_ENV=production assemble and minify frontend assets..." && - NODE_ENV=production ./node_modules/.bin/webpack --bail -} - -frontend-fast() { - frontend-deps - echo "Running 'webpack' with NODE_ENV=development to assemble frontend assets..." && - NODE_ENV=development ./node_modules/.bin/webpack --bail --devtool eval -} - -translations() { - frontend-deps - echo "Running './bin/i18n/build-translation-resources' to build translation resources..." - if ! ./bin/i18n/build-translation-resources; then - echo "Building translation resources failed, please install 'gettext', or build without translations by running './bin/build no-translations'." - exit 1 - fi -} - -drivers() { - echo "Building Metabase drivers..." - ./bin/build-drivers.sh -} - -uberjar() { - lein clean - echo "Running 'lein with-profile +$MB_EDITION uberjar'..." - lein with-profile +$MB_EDITION uberjar -} - -all() { - version && translations && frontend && drivers && uberjar -} - -no-translations() { - version && frontend && drivers && uberjar -} - -# Default to running all but let someone specify one or more sub-tasks to run instead if desired -# e.g. -# ./bin/build # do everything -# ./bin/build version # just update version.properties -# ./bin/build version uberjar # just update version.properties and build uberjar -if [ "$1" ]; then - for cmd in "$@"; do - $cmd - done -else - all -fi +cd bin/build-mb +clojure -M -m build $@ diff --git a/bin/build-drivers/build_drivers.clj b/bin/build-drivers/build_drivers.clj index d65dfee59a51ff8af302217c1f3a5b4698c3ce92..7dba107c801b7e127548e8cfcab52fce48a34ccb 100644 --- a/bin/build-drivers/build_drivers.clj +++ b/bin/build-drivers/build_drivers.clj @@ -1,15 +1,13 @@ (ns build-drivers "Entrypoint for `bin/build-drivers.sh`. Builds all drivers, if needed." - (:require [build-drivers - [build-driver :as build-driver] - [common :as c]] + (:require [build-drivers.build-driver :as build-driver] [clojure.java.io :as io] [metabuild-common.core :as u])) (defn- all-drivers [] - (map keyword (.list (io/file (c/filename c/project-root-directory "modules" "drivers"))))) + (map keyword (.list (io/file (u/filename u/project-root-directory "modules" "drivers"))))) -(defn- build-drivers! [] +(defn build-drivers! [] (u/step "Building all drivers" (doseq [driver (all-drivers)] (build-driver/build-driver! driver)) diff --git a/bin/build-drivers/build_drivers/build_driver.clj b/bin/build-drivers/build_drivers/build_driver.clj index c067cbc5589c586bcab3593cec28f8ee31a58b4e..8ce49da879fb3b5cd9185fabbe572c96fdffc868 100644 --- a/bin/build-drivers/build_drivers/build_driver.clj +++ b/bin/build-drivers/build_drivers/build_driver.clj @@ -81,7 +81,7 @@ ([target source] (u/step (format "Remove classes from %s that are present in %s and recompress" target source) - (u/sh {:dir c/project-root-directory} + (u/sh {:dir u/project-root-directory} "lein" "strip-and-compress" (u/assert-file-exists target) diff --git a/bin/build-drivers/build_drivers/checksum.clj b/bin/build-drivers/build_drivers/checksum.clj index b6f8e2ae6f9e071b7a27eac999cff41997bbd114..eedd60ccc1eff81a9a8220bccb28aee7d52f454b 100644 --- a/bin/build-drivers/build_drivers/checksum.clj +++ b/bin/build-drivers/build_drivers/checksum.clj @@ -25,15 +25,15 @@ (defn- metabase-source-paths [] (sort (cons - (c/filename c/project-root-directory "project.clj") + (u/filename u/project-root-directory "project.clj") (mapcat (fn [dir] (try (u/find-files dir #(str/ends-with? % ".clj")) (catch Throwable _ []))) - [(c/filename c/project-root-directory "src") - (c/filename c/project-root-directory "enterprise" "backend" "src") - (c/filename c/project-root-directory "backend" "mbql")])))) + [(u/filename u/project-root-directory "src") + (u/filename u/project-root-directory "enterprise" "backend" "src") + (u/filename u/project-root-directory "backend" "mbql")])))) (defn metabase-source-checksum "Checksum of Metabase backend source files and `project.clj`." @@ -58,7 +58,7 @@ (u/find-files (c/driver-project-dir driver) (fn [path] (or (and (str/ends-with? path ".clj") - (not (str/starts-with? path (c/filename (c/driver-project-dir driver) "test")))) + (not (str/starts-with? path (u/filename (c/driver-project-dir driver) "test")))) (str/ends-with? path ".yaml"))))) (defn driver-checksum diff --git a/bin/build-drivers/build_drivers/common.clj b/bin/build-drivers/build_drivers/common.clj index 953effd1260dd7ece5afbebc08732d9d54be8276..2af68af2d07d7954e4792ee5770b442ef21fd96e 100644 --- a/bin/build-drivers/build_drivers/common.clj +++ b/bin/build-drivers/build_drivers/common.clj @@ -1,28 +1,10 @@ (ns build-drivers.common "Shared constants and functions related to source and artifact paths used throughout this code." - (:require [clojure.string :as str] - [environ.core :as env] - [metabuild-common.core :as u]) - (:import java.io.File)) - -;; since this file is used pretty much everywhere, this seemed like a good place to put this. -(set! *warn-on-reflection* true) - -(when-not (str/ends-with? (env/env :user-dir) "/build-drivers") - (throw (ex-info "Please run build-driver scripts from the `bin/build-drivers` directory e.g. `cd bin/build-drivers; clojure -m build-driver`" - {:user-dir (env/env :user-dir)}))) - -(defn ^:deprecated filename - "DEPRECATED -- use u/filename instead." - [& path-components] - (apply u/filename path-components)) - -(def ^String project-root-directory - "e.g. /Users/cam/metabase" - (.. (File. ^String (env/env :user-dir)) getParentFile getParentFile getAbsolutePath)) + (:require [environ.core :as env] + [metabuild-common.core :as u])) (def ^String maven-repository-path - (filename (env/env :user-home) ".m2" "repository")) + (u/filename (env/env :user-home) ".m2" "repository")) ;;; -------------------------------------------------- Driver Paths -------------------------------------------------- @@ -30,7 +12,7 @@ (defn driver-project-dir "e.g. \"/home/cam/metabase/modules/drivers/redshift\"" [driver] - (filename project-root-directory "modules" "drivers" (name driver))) + (u/filename u/project-root-directory "modules" "drivers" (name driver))) (defn driver-jar-name "e.g. \"redshift.metabase-driver.jar\"" @@ -39,34 +21,34 @@ (defn driver-target-directory [driver] - (filename (driver-project-dir driver) "target")) + (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] - (filename (driver-target-directory driver) "uberjar" (driver-jar-name driver))) + (u/filename (driver-target-directory driver) "uberjar" (driver-jar-name driver))) (def ^String driver-jar-destination-directory - (filename project-root-directory "resources" "modules")) + (u/filename u/project-root-directory "resources" "modules")) (defn driver-jar-destination-path "e.g. \"/home/cam/metabase/resources/modules/redshift.metabase-driver.jar\"" [driver] - (filename driver-jar-destination-directory (driver-jar-name driver))) + (u/filename driver-jar-destination-directory (driver-jar-name driver))) (defn driver-checksum-filename "e.g. \"/home/cam/metabase/modules/drivers/redshift/target/checksum.txt\"" [driver] - (filename (driver-project-dir driver) "target" "checksum.txt")) ; TODO - rename to checksum.md5 + (u/filename (driver-project-dir driver) "target" "checksum.txt")) ; TODO - rename to checksum.md5 (defn driver-plugin-manifest-filename "e.g. \"/home/cam/metabase/modules/drivers/bigquery/resources/plugin-manifest.yaml\"" [driver] - (filename (driver-project-dir driver) "resources" "metabase-plugin.yaml")) + (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\"" - (filename project-root-directory "target" "uberjar" "metabase.jar")) + (u/filename u/project-root-directory "target" "uberjar" "metabase.jar")) diff --git a/bin/build-drivers/build_drivers/install_driver_locally.clj b/bin/build-drivers/build_drivers/install_driver_locally.clj index 484e880cc903aa8ac75f4cf6ac072589244e3b8a..c2cb31407215a5e236668f0224fcfd675d3dbd40 100644 --- a/bin/build-drivers/build_drivers/install_driver_locally.clj +++ b/bin/build-drivers/build_drivers/install_driver_locally.clj @@ -9,10 +9,10 @@ [metabuild-common.core :as u])) (defn- driver-local-install-path [driver] - (c/filename c/maven-repository-path "metabase" (format "%s-driver" (name driver)))) + (u/filename c/maven-repository-path "metabase" (format "%s-driver" (name driver)))) (defn- driver-local-install-checksum-filename [driver] - (c/filename (driver-local-install-path driver) "checksum.md5")) + (u/filename (driver-local-install-path driver) "checksum.md5")) (defn clean! "Delete local Maven installation of the library version of `driver`." diff --git a/bin/build-drivers/build_drivers/metabase.clj b/bin/build-drivers/build_drivers/metabase.clj index 5ba36429de0b8b4fde513a954db8d37c78e6afa5..9c209e10fbcc69149109945ab83a8af229345607 100644 --- a/bin/build-drivers/build_drivers/metabase.clj +++ b/bin/build-drivers/build_drivers/metabase.clj @@ -10,10 +10,10 @@ (str c/metabase-uberjar-path ".md5")) (def ^String ^:private metabase-core-install-path - (c/filename c/maven-repository-path "metabase-core")) + (u/filename c/maven-repository-path "metabase-core")) (def ^String ^:private metabase-core-checksum-path - (c/filename metabase-core-install-path "checksum.md5")) + (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" @@ -35,8 +35,8 @@ (u/announce "Up-to-date metabase-core already installed to local Maven repo") (do (delete-metabase-core-install!) - (u/sh {:dir c/project-root-directory} "lein" "clean") - (u/sh {:dir c/project-root-directory} "lein" "install-for-building-drivers") + (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."))))) @@ -57,7 +57,7 @@ (defn- delete-metabase-uberjar! [] (u/step "Delete exist metabase uberjar" - (u/delete-file! (c/filename c/project-root-directory "target")))) + (u/delete-file! (u/filename u/project-root-directory "target")))) (defn- build-metabase-uberjar! [] (u/step "Build Metabase uberjar if needed" @@ -65,8 +65,8 @@ (u/announce "Update-to-date uberjar already built") (do (delete-metabase-uberjar!) - (u/sh {:dir c/project-root-directory} "lein" "clean") - (u/sh {:dir c/project-root-directory} "lein" "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"))))) diff --git a/bin/build-drivers/deps.edn b/bin/build-drivers/deps.edn index 0e9cf9483eb79d841f24debf85558cae5e65556a..bb291868c5a7504f871501e25eb642b94da3f87d 100644 --- a/bin/build-drivers/deps.edn +++ b/bin/build-drivers/deps.edn @@ -1,13 +1,9 @@ -{:paths ["./" "../"] +{:paths ["./"] :deps - {cheshire/cheshire {:mvn/version "5.8.1"} + {common/common {:local/root "../common"} + cheshire/cheshire {:mvn/version "5.8.1"} commons-codec/commons-codec {:mvn/version "1.14"} - commons-io/commons-io {:mvn/version "2.6"} - colorize/colorize {:mvn/version "0.1.1"} - environ/environ {:mvn/version "1.1.0"} hiccup/hiccup {:mvn/version "1.0.5"} io.forward/yaml {:mvn/version "1.0.9"} - org.flatland/ordered {:mvn/version "1.5.7"} - potemkin/potemkin {:mvn/version "0.4.5"} stencil/stencil {:mvn/version "0.5.0"}}} diff --git a/bin/build-mb/build.clj b/bin/build-mb/build.clj new file mode 100644 index 0000000000000000000000000000000000000000..432d6a1b3f686e4b2a10bb83146bb25857d58f8c --- /dev/null +++ b/bin/build-mb/build.clj @@ -0,0 +1,92 @@ +(ns build + (:require [build-drivers :as build-drivers] + [build.version-info :as version-info] + [clojure.string :as str] + [environ.core :as env] + [flatland.ordered.map :as ordered-map] + [metabuild-common + [core :as u] + [java :as java]])) + +(defn- build-translation-resources! + [] + (u/step "Build translation resources" + (java/check-java-8) + (u/sh {:dir u/project-root-directory} "./bin/i18n/build-translation-resources") + (u/announce "Translation resources built successfully."))) + +(defn- build-frontend! [] + (u/step "Build frontend" + (u/step "Run 'yarn' to download javascript dependencies" + (u/sh {:dir u/project-root-directory} "yarn")) + (u/step "Run 'webpack' with NODE_ENV=production to assemble and minify frontend assets" + (u/sh {:dir u/project-root-directory + :env {"PATH" (env/env :path) + "HOME" (env/env :user-home) + "NODE_ENV" "production"}} + "./node_modules/.bin/webpack" "--bail")) + (u/announce "Frontend built successfully."))) + +(def uberjar-filename (u/filename u/project-root-directory "target" "uberjar" "metabase.jar")) + +(defn- build-uberjar! [edition] + {:pre [(#{:ce :ee} edition)]} + ;; clojure scripts currently use :ee vs :ce but everything else uses :ee vs :oss + (let [profile (case edition + :ee "ee" + :ce "oss")] + (u/delete-file-if-exists! uberjar-filename) + (u/step "Build uberjar" + (u/sh {:dir u/project-root-directory} "lein" "clean") + (u/sh {:dir u/project-root-directory} "lein" "with-profile" (str \+ profile) "uberjar") + (u/assert-file-exists uberjar-filename) + (u/announce "Uberjar built successfully.")))) + +(def all-steps + (ordered-map/ordered-map + :version (fn [{:keys [version]}] + (version-info/generate-version-info-file! version)) + :translations (fn [_] + (build-translation-resources!)) + :frontend (fn [_] + (build-frontend!)) + :drivers (fn [_] + (build-drivers/build-drivers!)) + :uberjar (fn [{:keys [edition]}] + (build-uberjar! edition)))) + +(defn build! + ([] + (build! nil)) + + ([{:keys [version edition steps] + :or {version (version-info/current-snapshot-version) + edition :ce + steps (keys all-steps)}}] + (u/step (format "Running build steps for %s version %s: %s" + (case edition + :ce "Community (OSS) Edition" + :ee "Enterprise Edition") + version + (str/join ", " (map name steps))) + (doseq [step-name steps + :let [step-fn (or (get all-steps (keyword step-name)) + (throw (ex-info (format "Invalid step: %s" step-name) + {:step step-name + :valid-steps (keys all-steps)})))]] + (step-fn {:version version, :edition edition})) + (u/announce "All build steps finished.")))) + +(defn- edition-from-env-var [] + ;; MB_EDITION is either oss/ee, but the Clojure build scripts currently use :ce/:ee + (if-not (env/env :mb-edition) + :ce + (case (env/env :mb-edition) + "oss" :ce + "ee" :ee))) + +(defn -main [& steps] + (u/exit-when-finished-nonzero-on-exception + (build! (merge {:edition (edition-from-env-var)} + (when-let [steps (not-empty steps)] + {:steps steps}))))) diff --git a/bin/build-mb/build/version_info.clj b/bin/build-mb/build/version_info.clj new file mode 100644 index 0000000000000000000000000000000000000000..011b31093251eb8c86ed346b0939cad7760bc7b4 --- /dev/null +++ b/bin/build-mb/build/version_info.clj @@ -0,0 +1,77 @@ +(ns build.version-info + (:require [clojure.string :as str] + [metabuild-common.core :as u])) + +(def version-properties-filename + (u/filename u/project-root-directory "resources" "version.properties")) + +(defn- shell-output-when-nonzero + "Call an external shell command, and return the first line that is output if it has a nonzero exit code. (Sometimes + `git` will fail, e.g. in CI where we delete the `.git` directory to reduce the workspace snapshot size.)" + [& args] + (let [{:keys [exit out]} (apply u/sh* args)] + (when (zero? exit) + (first out)))) + +(defn git-hash [] + ;; first 7 letters of hash should be enough; that's what GitHub uses + (or (shell-output-when-nonzero "git" "show-ref" "--head" "--hash=7" "head") + "?")) + +(defn git-branch [] + (or (shell-output-when-nonzero "git" "symbolic-ref" "--short" "HEAD") + "?")) + +(defn git-last-commit-date [] + (or (shell-output-when-nonzero "git" "log" "-1" "--pretty=%ad" "--date=short") + "?")) + +(defn- version-properties [version] + (str/join "\n" (for [[k v] {:tag (if-not (str/starts-with? version "v") + (str \v version) + version) + :hash (git-hash) + :branch (git-branch) + :date (git-last-commit-date)}] + (str (name k) \= v)))) + +(defn most-recent-tag [] + (shell-output-when-nonzero "git" "describe" "--abbrev=0" "--tags")) + +(defn most-recent-tag-parts [] + (when-let [tag (most-recent-tag)] + (for [part (str/split tag #"\.") + :let [numeric-part (re-find #"\d+" part)] + :when (seq numeric-part)] + (Integer/parseInt numeric-part)))) + +(defn current-snapshot-version + "Attempt to come up with a snapshot version for builds that aren't given explicit version info based on the most + recent tag. e.g. + + v0.37.1 -> v0.37.2-SNAPSHOT + + For builds from `master`, increment the minor version instead e.g. + + v0.37.1 -> v0.38.0-SNAPSHOT" + [] + (if-let [tag-parts (most-recent-tag-parts)] + (let [[major minor patch] tag-parts + major (or major 0) + [minor patch] (if (= (git-branch) "master") + [(inc (or minor 0)) 0] + [(or minor 0) (inc (or patch 0))])] + (format "v%d.%d.%d-SNAPSHOT" major minor patch)) + "UNKNOWN")) + +(defn generate-version-info-file! + "Generate version.properties file" + ([] + (generate-version-info-file! (current-snapshot-version))) + + ([version] + (u/delete-file-if-exists! version-properties-filename) + (u/step (format "Generate version.properties file for version %s" version) + (spit version-properties-filename (version-properties version)) + (u/assert-file-exists version-properties-filename) + (u/announce "version.properties generated successfully.")))) diff --git a/bin/build-mb/deps.edn b/bin/build-mb/deps.edn new file mode 100644 index 0000000000000000000000000000000000000000..434f9aeabe2e88fbc7905f40855896c289f4a1cc --- /dev/null +++ b/bin/build-mb/deps.edn @@ -0,0 +1,6 @@ +{:paths ["./"] + + :deps + {common/common {:local/root "../common"} + build-drivers/build-drivers {:local/root "../build-drivers"} + org.flatland/ordered {:mvn/version "1.5.7"}}} diff --git a/bin/common/deps.edn b/bin/common/deps.edn new file mode 100644 index 0000000000000000000000000000000000000000..31ea40aa43947ccbfe94b444dfdeb87b329a6a78 --- /dev/null +++ b/bin/common/deps.edn @@ -0,0 +1,7 @@ +{:paths ["./"] + + :deps + {commons-io/commons-io {:mvn/version "2.6"} + colorize/colorize {:mvn/version "0.1.1"} + environ/environ {:mvn/version "1.1.0"} + potemkin/potemkin {:mvn/version "0.4.5"}}} diff --git a/bin/metabuild_common/aws.clj b/bin/common/metabuild_common/aws.clj similarity index 100% rename from bin/metabuild_common/aws.clj rename to bin/common/metabuild_common/aws.clj diff --git a/bin/metabuild_common/core.clj b/bin/common/metabuild_common/core.clj similarity index 86% rename from bin/metabuild_common/core.clj rename to bin/common/metabuild_common/core.clj index c55aa1e36edd7ebe6d855722044f7348094a51b8..db228554d51a5b1fe96c9791f4e7274adc245410 100644 --- a/bin/metabuild_common/core.clj +++ b/bin/common/metabuild_common/core.clj @@ -10,6 +10,9 @@ [steps :as steps]] [potemkin :as p])) +;; since this file is used pretty much everywhere, this seemed like a good place to put this. +(set! *warn-on-reflection* true) + (comment aws/keep-me entrypoint/keep-me build.env/env @@ -38,7 +41,8 @@ delete-file-if-exists! file-exists? filename - find-files] + find-files + project-root-directory] [input interactive? diff --git a/bin/metabuild_common/entrypoint.clj b/bin/common/metabuild_common/entrypoint.clj similarity index 100% rename from bin/metabuild_common/entrypoint.clj rename to bin/common/metabuild_common/entrypoint.clj diff --git a/bin/metabuild_common/env.clj b/bin/common/metabuild_common/env.clj similarity index 100% rename from bin/metabuild_common/env.clj rename to bin/common/metabuild_common/env.clj diff --git a/bin/metabuild_common/files.clj b/bin/common/metabuild_common/files.clj similarity index 83% rename from bin/metabuild_common/files.clj rename to bin/common/metabuild_common/files.clj index 007831ec61ae1d11817b00f829de3d2a44f4edcc..3bfd999864772d1b0d0770173ad005111b8af3ec 100644 --- a/bin/metabuild_common/files.clj +++ b/bin/common/metabuild_common/files.clj @@ -1,5 +1,6 @@ (ns metabuild-common.files (:require [clojure.string :as str] + [environ.core :as env] [metabuild-common [output :as out] [shell :as sh] @@ -94,3 +95,19 @@ ;; -> \"usr/cam/.emacs.d/init.el\"" [& path-components] (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)}))))) diff --git a/bin/metabuild_common/input.clj b/bin/common/metabuild_common/input.clj similarity index 90% rename from bin/metabuild_common/input.clj rename to bin/common/metabuild_common/input.clj index edb4ae7a2d79043297c5a6ce478d41cd8975e916..dafc59c4f822549bc51cb3db29b134e34c13fac6 100644 --- a/bin/metabuild_common/input.clj +++ b/bin/common/metabuild_common/input.clj @@ -4,13 +4,13 @@ [metabuild-common.output :as out])) (defn interactive? - "Whether we're running these scripts interactively, and can prompt the user for input. By default, this is true, but - if the env var `INTERACTIVE=false` is set, these scripts will not prompt for input. Be sure to set this when running - scripts in CI or other places that automate them." + "Whether we're running these scripts interactively, and can prompt the user for input. By default, this is + true (except when running in CircleCI), but if the env var `INTERACTIVE=false` is set, these scripts will not prompt + for input. Be sure to set this when running scripts in CI or other places that automate them." [] (if-let [env-var (env/env :interactive)] (Boolean/parseBoolean env-var) - true)) + (not (:circleci env/env)))) (defn read-line-with-prompt "Prompt for and read a value from stdin. Accepts two options: `:default`, which is the default value to use if the diff --git a/bin/common/metabuild_common/java.clj b/bin/common/metabuild_common/java.clj new file mode 100644 index 0000000000000000000000000000000000000000..970c842cebba0538d8c014cfcd92df0e48f87360 --- /dev/null +++ b/bin/common/metabuild_common/java.clj @@ -0,0 +1,18 @@ +(ns metabuild-common.java + (:require [metabuild-common.core :as u])) + +(defn java-version + "Get `major.minor` version of the `java` command, e.g. `14.0` or `1.8` (Java 8)." + [] + (when-let [[_ version] (re-find #"version \"(\d+\.\d+)\..*\"" (first (u/sh "java" "-version")))] + (Double/parseDouble version))) + +(defn check-java-8 [] + (u/step "Verify Java version is Java 8" + (let [version (or (java-version) + (throw (Exception. "Unable to determine Java major version.")))] + ;; TODO -- is it possible to invoke `jabba` or some other command programmatically, or prompt for a different + ;; `JAVA_HOME`/`PATH` to use? + (when-not (#{1.8 8} version) + (throw (Exception. "The Metabase build script currently requires Java 8 to run. Please change your Java version and try again."))) + (u/announce "Java version is Java 8.")))) diff --git a/bin/metabuild_common/output.clj b/bin/common/metabuild_common/output.clj similarity index 100% rename from bin/metabuild_common/output.clj rename to bin/common/metabuild_common/output.clj diff --git a/bin/metabuild_common/shell.clj b/bin/common/metabuild_common/shell.clj similarity index 100% rename from bin/metabuild_common/shell.clj rename to bin/common/metabuild_common/shell.clj diff --git a/bin/metabuild_common/steps.clj b/bin/common/metabuild_common/steps.clj similarity index 100% rename from bin/metabuild_common/steps.clj rename to bin/common/metabuild_common/steps.clj diff --git a/bin/release/deps.edn b/bin/release/deps.edn index 52716c01fb9128d754e4df8b92627983a9d78315..e4e3bb9f579709dad333fdd99b12fb9fe14cd6ad 100644 --- a/bin/release/deps.edn +++ b/bin/release/deps.edn @@ -1,13 +1,11 @@ -{:paths ["./" "../"] +{:paths ["./"] :deps - {cheshire/cheshire {:mvn/version "5.8.1"} - clj-http/clj-http {:mvn/version "3.9.1"} - commons-io/commons-io {:mvn/version "2.6"} - colorize/colorize {:mvn/version "0.1.1"} - enlive/enlive {:mvn/version "1.1.6"} - environ/environ {:mvn/version "1.1.0"} - hiccup/hiccup {:mvn/version "1.0.5"} - org.flatland/ordered {:mvn/version "1.5.7"} - potemkin/potemkin {:mvn/version "0.4.5"} - stencil/stencil {:mvn/version "0.5.0"}}} + {common/common {:local/root "../common"} + build/build {:local/root "../build-mb"} + cheshire/cheshire {:mvn/version "5.8.1"} + clj-http/clj-http {:mvn/version "3.9.1"} + enlive/enlive {:mvn/version "1.1.6"} + hiccup/hiccup {:mvn/version "1.0.5"} + org.flatland/ordered {:mvn/version "1.5.7"} + stencil/stencil {:mvn/version "0.5.0"}}} diff --git a/bin/release/release/check_prereqs.clj b/bin/release/release/check_prereqs.clj index dfb9b292bf8e913ac97d683a1dad65d858e21e6b..5c922f71d7cbf9e013ab80c045e91a9a6a6766a6 100644 --- a/bin/release/release/check_prereqs.clj +++ b/bin/release/release/check_prereqs.clj @@ -1,7 +1,9 @@ (ns release.check-prereqs (:require [clojure.string :as str] [environ.core :as env] - [metabuild-common.core :as u])) + [metabuild-common + [core :as u] + [java :as java]])) (def ^:private required-commands ["git" "node" "yarn" "aws" "docker" "java" "wget" "shasum" "gettext" "zip"]) @@ -43,25 +45,9 @@ (throw (ex-info "Docker is not running. Please start it and try again." {}))) (u/announce "Docker is running."))) -(defn- java-version - "Get `major.minor` version of the `java` command, e.g. `14.0` or `1.8` (Java 8)." - [] - (when-let [[_ version] (re-find #"version \"(\d+\.\d+)\..*\"" (first (u/sh "java" "-version")))] - (Double/parseDouble version))) - -(defn- check-java-8 [] - (u/step "Verify Java version is Java 8" - (let [version (or (java-version) - (throw (Exception. "Unable to determine Java major version.")))] - ;; TODO -- is it possible to invoke `jabba` or some other command programmatically, or prompt for a different - ;; `JAVA_HOME`/`PATH` to use? - (when-not (#{1.8 8} version) - (throw (Exception. "The Metabase build script currently requires Java 8 to run. Please change your Java version and try again."))) - (u/announce "Java version is Java 8.")))) - (defn check-prereqs [] (u/step "Check prereqs" (check-for-required-commands) (check-for-required-env-vars) (check-docker-is-running) - (check-java-8))) + (java/check-java-8))) diff --git a/bin/release/release/common/upload.clj b/bin/release/release/common/upload.clj index 024874034d7826edf92f0b6169ecf26a49ecdb32..2e58f3c55754d39ffb08ce2f43aef7539009ba73 100644 --- a/bin/release/release/common/upload.clj +++ b/bin/release/release/common/upload.clj @@ -1,5 +1,6 @@ (ns release.common.upload - (:require [release.common :as c])) + (:require [metabuild-common.core :as u] + [release.common :as c])) (defn upload-artifact! "Upload an artifact to downloads.metabase.com and create a CloudFront invalidation." diff --git a/bin/release/release/set_build_options.clj b/bin/release/release/set_build_options.clj index dcc013bc0654a9fdd2b366a51bc961789b4ab6d5..1b12dbacab9c2bf254af6794169414ca86c89d13 100644 --- a/bin/release/release/set_build_options.clj +++ b/bin/release/release/set_build_options.clj @@ -8,7 +8,7 @@ (loop [] (let [version (u/read-line-with-prompt "What version are we building (e.g. 0.36.0)?") branch current-branch - edition (case (first (c/version)) + edition (case (first version) \0 :ce \1 :ee)] (if-not (u/yes-or-no-prompt (format "Building %s version %s from branch %s. Is this correct?" diff --git a/bin/release/release/uberjar.clj b/bin/release/release/uberjar.clj index ee7535bc09e5439c54e93f1b17eb2b8abc3c932b..48d0df7afe741dd3c8ecb319890092436f348cde 100644 --- a/bin/release/release/uberjar.clj +++ b/bin/release/release/uberjar.clj @@ -1,7 +1,6 @@ (ns release.uberjar "Code related to building, pushing, and validating metabase.jar" - (:require [clojure.string :as str] - [environ.core :as env] + (:require [build :as build] [metabuild-common.core :as u] [release.common :as c] [release.common @@ -9,38 +8,11 @@ [http :as common.http] [upload :as upload]])) -(def ^:private bin-version-file - (str c/root-directory "/bin/version")) - -(defn- update-version-info! [] - (u/step (format "Update %s if needed" (u/assert-file-exists bin-version-file)) - (u/step "Update version in bin/version" - (let [lines (str/split-lines (slurp bin-version-file)) - updated-lines (for [line lines] - (if (re-matches #".*VERSION=.*" line) - (format "VERSION='v%s'" (c/version)) - line))] - (if (= lines updated-lines) - (u/announce "Correct version is already set.") - (do - (u/announce "Version set to 'v%s'" (c/version)) - (spit bin-version-file (str/join (interleave updated-lines (repeat "\n")))) - (u/sh "chmod" "+x" bin-version-file) - (u/step "Commit updated bin/version" - (u/sh "git" "add" bin-version-file) - (u/sh "git" "commit" "-m" (str \v (c/version)) bin-version-file)))))))) - (defn build-uberjar! [] - (update-version-info!) (u/step "Run bin/build to build uberjar" - (u/delete-file! (str c/root-directory "/target")) - (u/sh {:dir c/root-directory - :env (merge {"JAVA_HOME" (env/env :java-home) - "PATH" (env/env :path) - "HOME" (env/env :user-home)} - (when (= (c/edition) :ee) - {"MB_EDITION" "ee"}))} - "bin/build") + (u/delete-file-if-exists! (str c/root-directory "/target")) + (build/build! {:version (str \v (c/version)) + :edition (c/edition)}) (u/step "Verify uberjar exists" (u/assert-file-exists c/uberjar-path)))) @@ -54,7 +26,7 @@ (common.http/check-url-exists url) (u/step (format "Check hash of %s" url) (let [temp-location "/tmp/metabase.jar"] - (u/delete-file! temp-location) + (u/delete-file-if-exists! temp-location) (u/sh {:quiet? true} "wget" "--quiet" "--no-cache" "--output-document" temp-location url) (let [uberjar-hash (hash/sha-256-sum c/uberjar-path) url-hash (hash/sha-256-sum temp-location)] diff --git a/bin/remove-drivers.sh b/bin/remove-drivers.sh deleted file mode 100755 index c82c6db24a4875fc4b55bf084c26b72f808c723c..0000000000000000000000000000000000000000 --- a/bin/remove-drivers.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /usr/bin/env bash - -set -eu - -for file in `find resources plugins -name '*.metabase-driver.jar'`; do - echo "Deleting $file..." - rm "$file" -done diff --git a/bin/verify-driver b/bin/verify-driver deleted file mode 100755 index 4e463736085f653c5c2f4ce47b0a50b223285cd4..0000000000000000000000000000000000000000 --- a/bin/verify-driver +++ /dev/null @@ -1,16 +0,0 @@ -#! /usr/bin/env bash - -set -eo pipefail - -driver="$1" - -if [ ! "$driver" ]; then - echo "Usage: ./bin/verify-driver [driver]" - exit -1 -fi - -source "./bin/check-clojure-cli.sh" -check_clojure_cli - -cd bin/build-drivers -clojure -M -m verify-driver "$driver" diff --git a/bin/version b/bin/version deleted file mode 100755 index cb1ee17a4434db2bba36a4bedb0006875aa71176..0000000000000000000000000000000000000000 --- a/bin/version +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -VERSION='v0.37.0.2' - -# dynamically pull more interesting stuff from latest git commit -HASH=$(git show-ref --head --hash=7 head) # first 7 letters of hash should be enough; that's what GitHub uses -BRANCH=$(git rev-parse --abbrev-ref HEAD) -DATE=$(git log -1 --pretty=%ad --date=short) - -# Return the version string used to describe this version of Metabase. -echo "$VERSION $HASH $BRANCH $DATE" diff --git a/docs/developers-guide-osx.md b/docs/developers-guide-osx.md index da7ab9a6a5ca2491a5090099c073e8ae4df2c7b9..5da8402904279d3c03f1fa75e9d18c6ca453f3ac 100644 --- a/docs/developers-guide-osx.md +++ b/docs/developers-guide-osx.md @@ -8,7 +8,7 @@ our [developers' guide](developers-guide.md). <summary> Steps </summary> - + ### Building The following steps need to be done before building the Mac App: @@ -16,11 +16,11 @@ The following steps need to be done before building the Mac App: 1. Install XCode. 1. Add a JRE to the `/path/to/metabase/repo/OSX/Metabase/jre` - + You must acquire a copy of a JRE (make sure you get a JRE rather than JDK) and move it to the correct location in the Mac App source directory so it can be included as part of the Mac App. To ship Java applications as Mac Apps, you must ship them with their own JRE. In this case we want to get a JRE from somewhere (more on this below) and move the `Contents/Home` directory from the JRE archive into `OSX/Metabase/jre`. (`OSX/Metabase` already exists inside the `metabase/metabase` repo.) <details><summary>Option 1: Download from AdoptOpenJDK (currently broken -- do not use)</summary> - + You can download a copy of a JRE from https://adoptopenjdk.net/releases.html?jvmVariant=hotspot — make sure you download a JRE rather than JDK. Move the `Contents/Home` directory from the JRE archive into `OSX/Metabase/jre`. (`OSX/Metabase` already exists inside the `metabase/metabase` repo.) For example: ```bash @@ -33,7 +33,7 @@ The following steps need to be done before building the Mac App: **VERY IMPORTANT!** - Make sure the JRE version you use is one that is known to work successfully with notarization. We have found out the one linked above does not work. + Make sure the JRE version you use is one that is known to work successfully with notarization. We have found out the one linked above does not work. I have found a nightly build that *does* work, but it's no longer available for download. Cam and Sameer both have copies of a JRE that is known to work. Refer to Option 2. If you get notarization errors like @@ -44,9 +44,9 @@ The following steps need to be done before building the Mac App: Assuming the OpenJDK folks have resolved this issue going forward, you are fine to use whatever the latest JRE version available is. I have been using the HotSpot JRE instead of the OpenJ9 one but it ultimately shouldn't make a difference. </details> - + <details><summary>Option 2: Ask Cam or Sameer for known working JRE</summary> - + Have Cam or Sameer ZIP up their `/path/to/metabase/repo/OSX/Metabase/jre` folder and send it to you. Don't try Option 1 until we know the issues are fixed </details> @@ -89,18 +89,18 @@ The following steps are prereqs for *releasing* the Mac App: 1) Add `Apple Developer ID Application Certificate` to your computer's keychain. - 1) Generate a Certificate Signing Request from the Keychain Access app. - - 1) `Keychain Access` > `Certificate Assistant` > `Request a Certificate From a Certificate Authority`. - + 1) Generate a Certificate Signing Request from the Keychain Access app. + + 1) `Keychain Access` > `Certificate Assistant` > `Request a Certificate From a Certificate Authority`. + 1) Enter the email associated with your Apple Developer account. - + 1) Leave "CA Email Address" blank - + 1) Choose "Save to Disk" - + 1) Have Sameer go to [the Apple Developer Site](https://developer.apple.com/account/mac/certificate/) and generate a `Developer ID Application` certificate for you by uploading the Certificate Signing Request you creating in the last step. - + 1) Load the generated certificate on your computer. 1) Export your Apple ID for building the app as `METABASE_MAC_APP_BUILD_APPLE_ID`. (This Apple ID must be part of the Metabase org in the Apple developer site. Ask Cam or Sameer to add you if it isn't.) @@ -137,7 +137,7 @@ After following the configuration steps above, to build and release the app you 1. Make sure release is *published* on GitHub and release notes are ready. The script copies these for the update release notes. -1. Make sure you're on the appropriate release branch locally. The script reads the version number from `./bin/version` +1. Make sure you're on the appropriate release branch locally. The script reads the version number from the most recent tag 1. Copy latest uberjar to the Mac App build directory @@ -148,8 +148,7 @@ After following the configuration steps above, to build and release the app you 1. Bundle entire app, and upload to s3 ```bash - cd OSX - clojure -m macos-release + ./OSX/release.sh ``` - + **Important Note** Do not let your computer lock the screen while running the script — if the screen is locked, macOS will not allow the script to access your Apple Developer credentials from the Keychain (needed for notarization) and the script will fail. diff --git a/src/metabase/config.clj b/src/metabase/config.clj index b78315f6db562094e31d39ba050845634e4ddc01..672512c023c97b8a964a060c916f1df26a41827e 100644 --- a/src/metabase/config.clj +++ b/src/metabase/config.clj @@ -1,7 +1,5 @@ (ns metabase.config - (:require [clojure.java - [io :as io] - [shell :as shell]] + (:require [clojure.java.io :as io] [clojure.string :as str] [environ.core :as environ] [metabase.plugins.classloader :as classloader]) @@ -68,19 +66,6 @@ (def ^Boolean is-test? "Are we running in `test` mode (i.e. via `lein test`)?" (= :test (config-kw :mb-run-mode))) ;;; Version stuff -;; Metabase version is of the format `GIT-TAG (GIT-SHORT-HASH GIT-BRANCH)` - -(defn- version-info-from-shell-script [] - (try - (let [[tag hash branch date] (-> (shell/sh "./bin/version") :out str/trim (str/split #" "))] - {:tag (or tag "?") - :hash (or hash "?") - :branch (or branch "?") - :date (or date "?")}) - ;; if ./bin/version fails (e.g., if we are developing on Windows) just return something so the whole thing doesn't - ;; barf - (catch Throwable _ - {:tag "?", :hash "?", :branch "?", :date "?"}))) (defn- version-info-from-properties-file [] (when-let [props-file (io/resource "version.properties")] @@ -92,14 +77,11 @@ ;; TODO - Can we make this `^:const`, so we don't have to read the file at launch when running from the uberjar? (def mb-version-info - "Information about the current version of Metabase. - This comes from `resources/version.properties` for prod builds and is fetched from `git` via the `./bin/version` - script for dev. + "Information about the current version of Metabase. Comes from `version.properties` which is generated by the build + script. mb-version-info -> {:tag: \"v0.11.1\", :hash: \"afdf863\", :branch: \"about_metabase\", :date: \"2015-10-05\"}" - (or (if is-prod? - (version-info-from-properties-file) - (version-info-from-shell-script)) + (or (version-info-from-properties-file) ;; if version info is not defined for whatever reason {}))