-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.clj
136 lines (107 loc) · 3.3 KB
/
core.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(ns monkey.ci.build.core
"Core build script functionality. This is used by build scripts to create
the configuration which is then executed by the configured runner. Which
runner is configured or active depends on the configuration of the MonkeyCI
application that executes the script."
(:require [clojure.spec.alpha :as s]
[medley.core :as mc]
[monkey.ci.build.spec]))
(defn status [v]
{:status v})
(def success (status :success))
(def failure (status :failure))
(def skipped (status :skipped))
(defn status?
"Checks if the given object is a job status"
[x]
(some? (:status x)))
(defn success? [{:keys [status]}]
(or (nil? status)
(= :success status)))
(defn failed? [{:keys [status]}]
(= :failure status))
(defn skipped? [{:keys [status]}]
(= :skipped status))
;; Job that executes a function
(defrecord ActionJob [id status action])
(defn action-job
"Creates a new job"
([id action opts]
(map->ActionJob (merge opts {:id id :action action})))
([id action]
(action-job id action {})))
(def action-job? (partial instance? ActionJob))
;; Job that runs in a container
(defrecord ContainerJob [id status image script])
(defn container-job
"Creates a job that executes in a container"
[id props]
(map->ContainerJob (assoc props :id id)))
(def container-job? (partial instance? ContainerJob))
(defn step->job
"Converts legacy map jobs into job records"
[m]
(cond
(action-job? m) m
(container-job? m) m
(some? (:action m)) (map->ActionJob (mc/assoc-some m :id (:name m)))
(some? (:container/image m)) (map->ContainerJob (assoc m :image (:container/image m)))
(fn? m) m
:else nil))
(defrecord Pipeline [jobs name])
(defn pipeline? [x]
(instance? Pipeline x))
(defn job-id [x]
(or (:id x) (:job/id (meta x))))
(defn pipeline
"Create a pipeline with given config"
[config]
{:pre [(s/valid? :ci/pipeline config)]}
(-> config
;; Convert steps into jobs, backwards compatibility
(mc/assoc-some :jobs (:steps config))
(dissoc :steps)
(update :jobs (partial map step->job))
(map->Pipeline)))
(defmacro defpipeline
"Convenience macro that declares a var for a pipeline with the given name
with specified jobs"
[n jobs]
`(def ~n
(pipeline
{:name ~(name n)
:jobs ~jobs})))
(defn as-job
"Marks fn `f` as a job"
[f]
(with-meta f {:job true}))
(defmacro defjob
"Defines an action job function"
[n & args]
`(def ~n (action-job ~(name n) (fn ~@args))))
(defn depends-on
"Adds dependencies to the given job"
[job ids]
(update job :dependencies (comp vec distinct concat) ids))
(defn git-ref
"Gets the git ref from the context"
[ctx]
(get-in ctx [:build :git :ref]))
(def branch-regex #"^refs/heads/(.*)$")
(def tag-regex #"^refs/tags/(.*)$")
(defn ref-regex
"Applies the given regex on the ref from the context, returns the matching groups."
[ctx re]
(some->> (git-ref ctx)
(re-matches re)))
(def branch
"Gets the commit branch from the context"
(comp second #(ref-regex % branch-regex)))
(def main-branch (comp :main-branch :git :build))
(defn main-branch? [ctx]
(= (main-branch ctx)
(branch ctx)))
(def tag
"Gets the commit tag from the context"
(comp second #(ref-regex % tag-regex)))
(def work-dir "The job work dir" (comp :work-dir :job))