Skip to content

Commit 6f3eb19

Browse files
authored
[minor] ✨ Add sci scripting feature (#3)
* ✨ Add sci scripting feature * 🎨 Reformat ctx in sci interpreter * 📝 Add docs
1 parent d9d482a commit 6f3eb19

File tree

8 files changed

+148
-25
lines changed

8 files changed

+148
-25
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,38 @@ $ gitwerk semver major
7777
v1.0.0
7878
```
7979

80+
### sci
81+
82+
gitwerk supports to run user-defined scripts written in clojure (powered by [borkdude/sci](https://github.com/borkdude/sci)).
83+
84+
```
85+
## can read stdin
86+
$ echo '(semver ctx ["patch"])' | gitwerk sci
87+
v0.0.2
88+
89+
## also read a file as a script
90+
$ cat examples/example1.clj
91+
(semver ctx ["patch"])
92+
$ gitwerk sci examples/example1.clj
93+
v0.0.3
94+
95+
## fetch executed command result and modify returned message
96+
$ cat examples/example2.clj
97+
(let [res (semver-auto ctx nil)
98+
status (get-in res [:console-out :status])
99+
oldv (get-in res [:console-out :old-version])
100+
newv (get-in res [:console-out :new-version])]
101+
(if (= status :updated)
102+
(str "Version updated: " oldv " -> " newv)
103+
"Version not updated"))
104+
$ gitwerk sci examples/example2.clj
105+
Version not updated
106+
107+
$ git commit --allow-empty -m "[patch] version updated"
108+
$ gitwerk sci examples/example2.clj
109+
Version updated: v0.0.3 -> v0.0.4
110+
```
111+
80112
## License
81113

82114
Copyright © 2019 rinx

examples/example1.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(semver ctx ["patch"])

examples/example2.clj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(let [res (semver-auto ctx nil)
2+
status (get-in res [:console-out :status])
3+
oldv (get-in res [:console-out :old-version])
4+
newv (get-in res [:console-out :new-version])]
5+
(if (= status :updated)
6+
(str "Version updated: " oldv " -> " newv)
7+
"Version not updated"))

project.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
[metosin/jsonista "0.2.2"]
1010
[camel-snake-kebab "0.4.0"]
1111
[io.quarkus/quarkus-jgit "1.1.0.CR1"]
12+
[borkdude/sci "0.0.12-alpha.7"]
1213
[org.martinklepsch/clj-http-lite "0.4.3"]]
1314
:profiles {:dev {:dependencies [[org.clojure/tools.namespace "0.2.11"]
1415
[orchestra "2019.02.06-1"]]

src/gitwerk/command/sci.clj

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
(ns gitwerk.command.sci
2+
(:require
3+
[clojure.spec.alpha :as spec]
4+
[clojure.pprint :as pprint]
5+
[sci.core :as sci]
6+
[gitwerk.internal.io :as internal.io]))
7+
8+
(def clj-primitives
9+
{'println println
10+
'pprint pprint/pprint})
11+
12+
(defn run-fn [sci-opts]
13+
(fn [ctx args]
14+
(try
15+
(let [file (first args)
16+
body (if (nil? file)
17+
(internal.io/read-from-stdin)
18+
(internal.io/safe-read file))
19+
ctx (dissoc ctx :command :summary)
20+
opts (-> sci-opts
21+
(update
22+
:bindings
23+
#(-> %
24+
(merge clj-primitives)
25+
(merge {'ctx ctx}))))
26+
res (sci/eval-string body opts)]
27+
(if (and (map? res) (:status res))
28+
res
29+
{:status 0
30+
:console-out res}))
31+
(catch Exception e
32+
{:status 1
33+
:console-out
34+
{:error (.getMessage e)}}))))

src/gitwerk/core.clj

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,27 @@
33
[clojure.spec.alpha :as spec]
44
[clojure.tools.cli :as cli]
55
[clojure.string :as string]
6+
[clojure.pprint :as pprint]
67
[clojure.edn :as edn]
78
[clojure.java.io :as io]
89
[gitwerk.service.runner :as runner])
910
(:gen-class))
1011

1112
(def cli-header
1213
(string/join
13-
"\n"
14+
"\n"
15+
(concat
1416
["gitwerk is a CLI tool for supporting Git(Hub) operations on CI."
1517
""
1618
"Usage: gitwerk [command] [options]"
1719
""
18-
"Available commands:"
19-
" clone [url] clone git repository"
20-
" log show git logs of current directory"
21-
" semver [type] print incremented version"
22-
" semver-auto increment version by latest git log message contexts"
23-
" tag show git tags of current directory"
24-
""
25-
"Options:"]))
20+
"Available commands:"]
21+
(mapv (fn [[k v]]
22+
(let [name (format " %-12s " (name k))
23+
desc (:description v)]
24+
(str name desc))) runner/definitions)
25+
[""
26+
"Options:"])))
2627
(def cli-options
2728
[["-f" "--file PATH" "config"
2829
:id :config-filename
@@ -33,19 +34,21 @@
3334

3435
(defn edn-output
3536
[ctx res]
36-
(println res))
37+
(pprint/pprint res))
3738

3839
(defn std-output
3940
[{:keys [summary] :as ctx}
4041
{:keys [status invalid-arg? console-out]}]
41-
(when console-out
42-
(println console-out))
43-
(when invalid-arg?
44-
(println cli-header)
45-
(println summary))
46-
(if status
47-
(System/exit status)
48-
(System/exit 1)))
42+
(when console-out
43+
(if (map? console-out)
44+
(pprint/pprint console-out)
45+
(println console-out)))
46+
(when invalid-arg?
47+
(println cli-header)
48+
(println summary))
49+
(if status
50+
(System/exit status)
51+
(System/exit 1)))
4952

5053
(defn run
5154
[{:keys [options] :as ctx}]

src/gitwerk/internal/io.clj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
(ns gitwerk.internal.io
2+
(:require
3+
[clojure.spec.alpha :as spec]
4+
[clojure.java.io :as io]
5+
[clojure.string :as string])
6+
(:import
7+
[java.io BufferedReader]))
8+
9+
(defn read-from-stdin []
10+
(->> (BufferedReader. *in*)
11+
(line-seq)
12+
(string/join "\n")))
13+
14+
(defn safe-read
15+
[file]
16+
(if (.exists (io/file file))
17+
(slurp file)
18+
(throw
19+
(Exception.
20+
(str "File not found: " file)))))

src/gitwerk/service/runner.clj

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,47 @@
44
[camel-snake-kebab.core :as csk]
55
[gitwerk.command.clone :as command.clone]
66
[gitwerk.command.log :as command.log]
7+
[gitwerk.command.sci :as command.sci]
78
[gitwerk.command.semver :as command.semver]
89
[gitwerk.command.semver-auto :as command.semver-auto]
910
[gitwerk.command.tag :as command.tag]))
1011

12+
(def primitives
13+
{:clone
14+
{:command command.clone/run
15+
:description "clone git repository"}
16+
:log
17+
{:command command.log/run
18+
:description "show git logs of current directory"}
19+
:semver
20+
{:command command.semver/run
21+
:description "print incremented version"}
22+
:semver-auto
23+
{:command command.semver-auto/run
24+
:description "increment version by latest git log message contexts"}
25+
:tag
26+
{:command command.tag/run
27+
:description "show git tags of current directory"}})
28+
29+
(def definitions
30+
(let [->binding (fn [[k v]]
31+
(let [sym (symbol (name k))
32+
com (:command v)]
33+
[sym com]))
34+
bindings (->> primitives
35+
(map ->binding)
36+
(into {}))
37+
sci-opts {:bindings bindings}]
38+
(into primitives
39+
{:sci {:command (command.sci/run-fn sci-opts)
40+
:description "run user-defined script (written in clojure)"}})))
41+
1142
(defn dispatch
1243
[{:keys [args] :as ctx} cmd]
1344
(let [default (fn [_ _]
1445
{:status 1
1546
:invalid-arg? true})
16-
cmd (case cmd
17-
:clone command.clone/run
18-
:log command.log/run
19-
:semver command.semver/run
20-
:semver-auto command.semver-auto/run
21-
:tag command.tag/run
22-
default)]
47+
cmd (or (:command (cmd definitions)) default)]
2348
(cmd ctx args)))
2449

2550
(defn run

0 commit comments

Comments
 (0)