Giter VIP home page Giter VIP logo

tag's Introduction

tag

tagging apps with git, maven and other intel

<! release <! clojars

why

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.

how

=> (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",
  :repo-url "[email protected]:tolitius/hubble.git",
  :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"},
  :maven
 {:group-id "tolitius",
  :artifact-id "hubble",
  :version "0.1.42",
  :name "hubble",
  :description "I explore new worlds",
  :url "https://github.com/tolitius/hubble"}
 :described-at #inst "2020-05-07T00:55:03.260-00:00"}

and how to export it:

=> (-> (t/describe "hubble")
       (t/export-intel {:app-name "tolitius/hubble"}))

{:intel-exported-to "target/about/META-INF/tolitius/hubble/about.edn"}

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.

show me

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" "tolitius/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

look inside

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/tolitius/tag/
   321 Thu May 07 00:17:06 EDT 2020 META-INF/tolitius/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/tolitius/tag/about.edn
 inflated: META-INF/tolitius/tag/about.edn
$ cat META-INF/tolitius/tag/about.edn

{:about {:app-name "tolitius/tag", "what do I do?" "I tag apps with immutable intel"}, :git {:commit-id "58df09d", :version/tag "v0.1.0", :repo-url "[email protected]:tolitius/tag.git", :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:

:dependencies [;; ...
               [tolitius/tag "x.x.x" :scope "provided"]]
:prep-tasks [["run" "-m" "tag.core/-main"
                         "tolitius/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.

composing tags

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/tolitius/hubble/about.edn
   331 Thu May 07 01:06:21 EDT 2020 META-INF/tolitius/tag/about.edn
   301 Thu May 07 01:02:25 EDT 2020 META-INF/tolitius/mount/about.edn
   395 Thu May 07 01:01:42 EDT 2020 META-INF/tolitius/cprop/about.edn
   384 Thu May 07 01:01:57 EDT 2020 META-INF/tolitius/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.

access intel

a likely http route (in this case reitit) would look like this:

["/about"
 {:get (constantly
         {:status 200
          :body   (tools/edn-resource "META-INF/tolitius/hubble/about.edn")})}]]

tools/edn-resource might be something like this:

(ns app.tools
  (:require [clojure.java.io :as io]
            [clojure.edn :as edn]))

(defn slurp-resource [path]
  (-> path
      io/resource
      slurp))

(defn edn-resource [path]
  (-> path
      slurp-resource
      edn/read-string))

yes, but why not in config?

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.

License

Copyright © 2020 tolitius

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

tag's People

Contributors

tolitius avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.