          args-with-name (if (args "appName")
                           args
                           (assoc args "appName" *pipeline-builder-caller*))
-         reformed-args (map (fn [[k v]] (str "--" k "=" v)) args-with-name)
+         args-with-jobname (if-let [tpl (args-with-name "jobNameTemplate")]
+                             (-> args-with-name
+                                 (assoc "jobName" (job-name-template tpl args-with-name))
+                                 (dissoc "jobNameTemplate"))
+                             args-with-name)
+         reformed-args (map (fn [[k v]] (str "--" k "=" v)) args-with-jobname)
          builder (PipelineOptionsFactory/fromArgs
                   (into-array String reformed-args))
          options (if itf

           [java.io InputStream OutputStream DataInputStream DataOutputStream File]
           [java.util UUID]
           [java.net URI]
           [clojure.lang MapEntry ExceptionInfo]))

(def required-ns (atom #{}))



(def ^:dynamic *pipeline-builder-caller* "unknown")

(defn create-timestamp
  []
  (let [formatter (-> "MMddHHmmss"
                      (DateTimeFormat/forPattern)
                      (.withZone DateTimeZone/UTC))]
    (.print formatter (DateTimeUtils/currentTimeMillis))))

(defn job-name-template
  [tpl args]
  (-> tpl
      (str/replace #"%U" (or (System/getProperty "user.name") "nemo"))
      (str/replace #"%A" *pipeline-builder-caller*)
      (str/replace #"%T" (create-timestamp))
      (str/lower-case)
      (str/replace #"[^-a-z0-9]" "0")))

(defn make-pipeline*
  ([itf str-args kw-args]
   (let [atomic-args (into {} (map (fn [kv] (let [[k v] (str/split kv #"=" 2)]
                                              [(str/camel-case (str/replace k #"^--" "")) v]))
