Compare commits

...

3 Commits

Author SHA1 Message Date
bryan
157592f127 Merge branch 'master' into better-error-printing 2025-05-01 15:14:59 -06:00
Bryan Maass
e81f4075cc document how error-report and exit code work
- pretty print ex-data (w/ color)
- fix passing MAGE_DEBUG
- `-runbb` task to check exceptions from shell
- add CI mode (always prints exceptions)
2025-05-01 11:15:48 -06:00
Bryan Maass
6413df8dae better mage error printing
- adds :mage/error-report. when included in ex-data, it will get printed
out at the top level.
- if there is ex-message or ex-data, they will get printed out
- if there is only an exception, then we print that (last resort)
2025-04-30 13:25:38 -06:00
6 changed files with 84 additions and 22 deletions

View File

@@ -859,6 +859,7 @@
{:main-without-gen-class {:level :off}
:discouraged-var {clojure.pprint/pprint {:level :off}
clojure.core/print {:level :off}
clojure.core/prn {:level :off}
clojure.core/printf {:level :off}
clojure.core/println {:level :off}
clojure.string/lower-case {:level :off}

8
bb.edn
View File

@@ -3,7 +3,8 @@
;; so the namespaces are mage.cli, mage.format, etc.
:paths ["mage" "test" "bin/lint-migrations-file/src"]
:deps {metosin/malli {:mvn/version "0.17.0"}
table/table {:mvn/version "0.5.0"}}
table/table {:mvn/version "0.5.0"}
mvxcvi/puget {:mvn/version "1.3.4"}}
:tasks
{:requires [[mage.cli :as cli]]
:init (do (defmacro task! "Binds the parsed command line arguments to `parsed`."
@@ -212,6 +213,11 @@
[clojure.test :refer [run-tests]]]
:task (run-tests 'mage.core-test)}
-runbb {:doc "run the input as a babashka script, good for testing."
:requires [[clojure.string :as str]]
:task (task!
(eval (read-string (str/join " " (:arguments parsed)))))}
-test-examples
{:doc "Runs every example and checks that it exits with 0"
:requires [[mage.examples-test :as examples-test]]

View File

@@ -231,7 +231,7 @@ main() {
dbg_info "Running mage_core with args: '$*'"
# log_info $MAGE_CORE_PATH
# log_info "${BB_EXEC} ${MAGE_CORE_PATH}"
(cd "${MB}" && exec "${BB_EXEC}" "${MAGE_CORE_PATH}" "$@")
(export MAGE_DEBUG && cd "${MB}" && exec "${BB_EXEC}" "${MAGE_CORE_PATH}" "$@")
}
# Run the main function with all arguments

View File

@@ -8,12 +8,12 @@
[babashka.tasks :as bt]
[clojure.string :as str]
[mage.color :as c]
[mage.shell :as sh]
[mage.util :as u]))
[mage.util :as u]
[puget.printer]))
(set! *warn-on-reflection* true)
(defn lolcat [f]
(defn- lolcat [f]
(if (try (u/sh "command -v lolcat")
(catch Exception _ false))
(bt/shell (str "lolcat " f))
@@ -22,7 +22,7 @@
(when (> (rand) 0.8)
(println (c/yellow "Tip: install lolcat for a better experience!"))))))
(defn invalid-task? []
(defn- invalid-task? []
(let [task-name (first *command-line-args*)]
(when-not (contains? (set (u/all-bb-tasks-list)) task-name)
(println (c/red (str "Unknown task: " task-name)))
@@ -33,7 +33,7 @@
(filter (fn [x] (str/starts-with? x "-"))
(str/split-lines (slurp "zen.md")))))
(defn tip-o-day []
(defn- tip-o-day []
(rand-nth
(concat ["Did you know? You can use `./bin/mage <task> --help` to get more information about a specific task."
"Pro tip: Use `./bin/mage <task>` to run a specific task."
@@ -44,15 +44,46 @@
(zen))))
(defn- print-help []
(do
(lolcat "./mage/resource.txt")
(flush)
(println (c/bold " ✨ Metabase Automation Genius Engine ✨"))
(println "")
(println (u/sh "bb tasks"))
(println (tip-o-day))))
(lolcat "./mage/resource.txt")
(flush)
(println (c/bold " ✨ Metabase Automation Genius Engine ✨"))
(println "")
(println (u/sh "bb tasks"))
(println (tip-o-day)))
(defn -main [& _]
(defn show-exception [e]
(println (c/on-red "* Exception: " (type e) " *"))
(.printStackTrace e))
(defn- -main
"Babashka Entrypoint for Mage task runner.
Tasks may throw exceptions to signal failure. The task runner supports structured
error handling via metadata in the exception's `ex-data` map:
- `:mage/error-report` — A user-facing error message string. If present, this will be
printed instead of the exception or stack trace. Intended for friendly, concise output.
Put output of failing tasks that are meant to be printed in this key.
- `:mage/exit-code` — An integer exit code to use when the task fails. Defaults to 1 if omitted.
If no `:mage/error-report` is provided, the runner will fall back to printing the exception's
message (via `ex-message`), and optionally `ex-data` or the full stack trace depending on
debugging settings.
To enable debug output (e.g., for CI runs or local troubleshooting), set the environment variable:
MAGE_DEBUG=true
This will print the full exception stack trace and any exception.
Debug mode is also automatically enabled in common CI environments by checking:
- `MAGE_DEBUG`
- `CI`
- `GITHUB_ACTIONS`
This design helps produce clean output by default, while still allowing detailed diagnostics
in development or continuous integration environments."
[& _]
(cond
;; help
(or
@@ -75,10 +106,28 @@
(try (bt/run task)
(catch Exception e
(let [message (ex-message e)
data (ex-data e)]
(when message (println (c/red (c/reverse-color "Error :")) message))
(when data (println (c/yellow (c/reverse-color "Error data:")) data))
(when e (println (c/yellow "\nException:\n") e))
data (ex-data e)
report (:mage/error-report data)
debug? (some System/getenv ["MAGE_DEBUG" "CI" "GITHUB_ACTIONS"])]
(when debug?
(binding [*out* *err*] (show-exception e))
(println ""))
(when report
(println (c/on-red " * mage/error-report * "))
(println report))
(when message
(println (c/on-red " * ex-message * "))
(println message))
(when data
(println (c/on-red " * ex-data * "))
(-> data
(dissoc :mage/error-report :mage/exit-code)
puget.printer/pprint
puget.printer/with-color))
(if (and (not data) (not message) (not report))
(binding [*out* *err*] (show-exception e))
(when-not debug?
(println "\nException hidden: Run with MAGE_DEBUG set for more information.")))
(System/exit (:mage/exit-code data 1))))))))))
(when (= *file* (System/getProperty "babashka.file"))

View File

@@ -45,4 +45,9 @@
[{{force-check? :force-check} :options}]
(let [mode (->mode force-check?)]
(println (str mode "ing all clojure files, sit tight: this could take a minute..."))
(u/sh (str "clojure -T:cljfmt " mode))))
(try
(u/sh (str "clojure -T:cljfmt " mode))
(catch Exception e
(throw (ex-info (ex-message e)
{:mage/exit-code 1
:mage/error-report (:out (:proc (ex-data e)))}))))))

View File

@@ -100,10 +100,11 @@
"--" "*.clj" "*.cljc" "*.cljs" ":!/.clj-kondo" ":!/dev")
:out
(str/split-lines)
;; filter out any files that have been deleted/moved
(remove #{""})
;; filter out any files that have been deleted/moved:
(filter (fn [filename]
(fs/exists? (str project-root-directory "/" filename)))))))
(fs/exists? (str project-root-directory "/" filename))))
sort)))
(comment
(count (updated-files "master"))