tagging apps with git and other intel
once the app is built it is an immutable artifact. this artifact usually has quite a limitted way to describe itself:
name-version.jar
is not exactly very telling.
tag
is run right before building an artifact to include additional useful intel about it.
by the time artifact is built it would have an about.edn
file that can be looked at by the app at runtime:
described-at
in this case would be a build time.
=> (require '[tag.core :as t])
tag
knows how to describe the app:
=> (t/describe "hubble" {:about "I explore new worlds"})
{:about {:app-name "hubble",
"what do I do?" "I explore new worlds"},
:git
{:commit-id "8b15218",
:version/tag "v0.1.42",
:commit-time "Wed May 6 20:26:03 2020 -0400",
"commit human (or not)" "'anatoly'",
:commit-message "readjust a low gain antena for the cat's eye nebula"},
:described-at #inst "2020-05-07T00:55:03.260-00:00"}
and how to export it:
=> (-> (t/describe "hubble")
t/export-intel)
:intel-exported
once the jar is built the edn
above will (by default) live inside the jar in ./META-INF/[app-name]/about.edn
.
so for example if your, say http, app has an /about
endpoint, it could read this file on start or at runtime and display the immutable intel above.
tag
uses itself to include the intel in itself right before it is built. so let's look at what it does.
it has an alias in deps.edn:
:tag {:main-opts ["-m" "tag.core" "tag" "I tag apps with immutable intel"]}
which calls out to tag
and exports the intel.
it also has a :jar
alias with an addition of an :extra-paths
:
:extra-paths ["target/about"]
tag
will place "about.edn
" to target/about/META-INF
in order for a jar
task to pick it up during the build.
hence in order to tag and build we can do:
$ clj -A:tag
$ clj -A:jar
let's look at what inside this newly built tag.jar
:
$ jar -tvf tag.jar
0 Thu May 07 00:17:10 EDT 2020 META-INF/
0 Thu May 07 00:17:10 EDT 2020 META-INF/tag/
321 Thu May 07 00:17:06 EDT 2020 META-INF/tag/about.edn ## <<< oh.. look who is here
0 Thu May 07 00:17:10 EDT 2020 tag/
1769 Thu May 07 00:16:58 EDT 2020 tag/core.clj
58 Thu May 07 00:17:10 EDT 2020 META-INF/MANIFEST.MF
0 Thu May 07 00:17:10 EDT 2020 META-INF/maven/
0 Thu May 07 00:17:10 EDT 2020 META-INF/maven/tolitius/
0 Thu May 07 00:17:10 EDT 2020 META-INF/maven/tolitius/tag/
110 Thu May 07 00:17:10 EDT 2020 META-INF/maven/tolitius/tag/pom.properties
1711 Thu May 07 00:17:10 EDT 2020 META-INF/maven/tolitius/tag/pom.xml
$ jar -xvf tag.jar META-INF/tag/about.edn
inflated: META-INF/tag/about.edn
$ cat META-INF/tag/about.edn
{:about {:app-name "tag", "what do I do?" "I tag apps with immutable intel"}, :git {:commit-id "58df09d", :version/tag "v0.1.0", :commit-time "Wed May 6 23:41:33 2020 -0400", "commit human (or not)" "'Anatoly'", :commit-message "[docs]: add lein :prep-tasks example"}, :described-at #inst "2020-05-07T04:17:06.081-00:00"}
great success.
this way tag
can also be used with lein:
:prep-tasks [["run" "-m" "tag.core/-main"
"hubble" "I explore new worlds"]
["compile"]]
:jar {:resource-paths ["target/about"] ;; ... }
;; or and uberjar:
:uberjar {:resource-paths ["target/about"] ;; ... }
boot, make, and other build tools.
one intersing side effect of tagging libs or dependencies with tag
is that the final app jar / uberjar has them all:
$ jar -tvf target/hubble-standalone.jar | grep about
369 Thu May 07 01:18:32 EDT 2020 META-INF/hubble/about.edn
331 Thu May 07 01:06:21 EDT 2020 META-INF/tag/about.edn
301 Thu May 07 01:02:25 EDT 2020 META-INF/mount/about.edn
395 Thu May 07 01:01:42 EDT 2020 META-INF/cprop/about.edn
384 Thu May 07 01:01:57 EDT 2020 META-INF/lasync/about.edn
...
hence building something like /about/[dependency-name]
app endponts is straightforward and allows to have reliable intel about not just the app itself but its dependencies as well.
configuration is usually overriden by system props, ENV vars, consul, etcd, etc.
the idea behind tag
is to make sure the built artifact "describes itself consistently", or constantly as we say in Clojure circles.
Copyright © 2020 tolitius
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation? These fine people already did:
Anatoly & anatolyEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close