travis-conditions 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/Gemfile.lock +1 -1
- data/NOTES.md +107 -0
- data/README.md +261 -13
- data/bin/travis-conditions +34 -0
- data/lib/travis/conditions.rb +10 -16
- data/lib/travis/conditions/v0.rb +30 -0
- data/lib/travis/conditions/v0/data.rb +57 -0
- data/lib/travis/conditions/v0/eval.rb +70 -0
- data/lib/travis/conditions/v0/parser.rb +204 -0
- data/lib/travis/conditions/v1.rb +19 -0
- data/lib/travis/conditions/v1/boolean.rb +71 -0
- data/lib/travis/conditions/v1/data.rb +75 -0
- data/lib/travis/conditions/v1/eval.rb +114 -0
- data/lib/travis/conditions/v1/helper.rb +30 -0
- data/lib/travis/conditions/v1/parser.rb +214 -0
- data/lib/travis/conditions/version.rb +1 -1
- data/spec/conditions_spec.rb +15 -0
- data/spec/v0/conditions_spec.rb +15 -0
- data/spec/{data_spec.rb → v0/data_spec.rb} +6 -1
- data/spec/{eval_spec.rb → v0/eval_spec.rb} +1 -1
- data/spec/v0/fixtures/failures.txt +342 -0
- data/spec/v0/fixtures/passes.txt +1685 -0
- data/spec/{parser_spec.rb → v0/parser_spec.rb} +1 -1
- data/spec/v1/conditions_spec.rb +44 -0
- data/spec/v1/data_spec.rb +30 -0
- data/spec/v1/eval_spec.rb +349 -0
- data/spec/v1/fixtures/failures.txt +336 -0
- data/spec/v1/fixtures/passes.txt +1634 -0
- data/spec/v1/parser/boolean_spec.rb +215 -0
- data/spec/v1/parser/call_spec.rb +68 -0
- data/spec/v1/parser/comma_spec.rb +28 -0
- data/spec/v1/parser/cont_spec.rb +41 -0
- data/spec/v1/parser/eq_spec.rb +16 -0
- data/spec/v1/parser/in_list_spec.rb +60 -0
- data/spec/v1/parser/is_pred_spec.rb +24 -0
- data/spec/v1/parser/list_spec.rb +36 -0
- data/spec/v1/parser/operand_spec.rb +16 -0
- data/spec/v1/parser/parens_spec.rb +28 -0
- data/spec/v1/parser/quoted_spec.rb +24 -0
- data/spec/v1/parser/re_spec.rb +16 -0
- data/spec/v1/parser/regex_spec.rb +12 -0
- data/spec/v1/parser/space_spec.rb +40 -0
- data/spec/v1/parser/term_spec.rb +84 -0
- data/spec/v1/parser/val_spec.rb +24 -0
- data/spec/v1/parser/var_spec.rb +16 -0
- data/spec/v1/parser_spec.rb +486 -0
- data/spec/v1/user_spec.rb +223 -0
- metadata +48 -9
- data/lib/travis/conditions/data.rb +0 -45
- data/lib/travis/conditions/eval.rb +0 -68
- data/lib/travis/conditions/parser.rb +0 -202
@@ -0,0 +1,223 @@
|
|
1
|
+
# notes
|
2
|
+
#
|
3
|
+
# people seem to be confusing `=` (equality) with `IS` (predicate) a lot
|
4
|
+
# reject builds that fail to parse the condition, instead of ignoring it
|
5
|
+
#
|
6
|
+
# docs: change docs to recommend quotes around values in `= "string"`
|
7
|
+
# docs: change docs to recommend quotes around values in `IN ("list")`
|
8
|
+
# docs: mention NO SHELL CODE PLEASE
|
9
|
+
# docs: mention reqexp limitations, and recommend using `/.../` first
|
10
|
+
# docs: make the warning about `env` only having the .travis.yml vars bigger and fatter
|
11
|
+
|
12
|
+
describe Travis::Conditions::V1, 'real conditions' do
|
13
|
+
broken = <<~strs.split("\n")
|
14
|
+
branch =~ ^(!:release\/) or tag =~ ^version_code\/
|
15
|
+
tag =~ (^version_code\/)|(^$)
|
16
|
+
branch = develop/pipes=travis
|
17
|
+
strs
|
18
|
+
|
19
|
+
used = <<~strs.split("\n")
|
20
|
+
((NOT branch =~ ^develop/.*$) OR (branch = develop/travis)) AND (tag IS blank)
|
21
|
+
(NOT branch =~ ^develop/.*$) AND (tag IS blank)
|
22
|
+
(branch != master OR type = cron OR type = api)
|
23
|
+
(branch = develop/travis) AND (tag IS blank)
|
24
|
+
(branch = master) AND (NOT (type IN (api, pull_request)))
|
25
|
+
(branch = master) AND (NOT (type IN (api,pull_request)))
|
26
|
+
(branch = master) AND (NOT (type IN (push, pull_request)))
|
27
|
+
(branch = master) AND (NOT (type IN (push,pull_request)))
|
28
|
+
(branch = master) AND (NOT(type IN (api, pull_request)))
|
29
|
+
(branch = master) AND (NOT(type IN (api,pull_request)))
|
30
|
+
(branch = master) AND (NOT(type IN (push ,pull_request)))
|
31
|
+
(branch = master) AND (NOT(type IN (push, pull_request)))
|
32
|
+
(branch = master) AND (NOT(type IN (push,pull_request)))
|
33
|
+
(type = pull_request) OR (tag IS present)
|
34
|
+
(type = push AND NOT (branch = develop)) OR (type = cron)
|
35
|
+
NOT branch = master
|
36
|
+
NOT branch =~ ^develop/.*$
|
37
|
+
NOT tag = "stable"
|
38
|
+
NOT tag = stable
|
39
|
+
NOT tag =~ \+d2$
|
40
|
+
branch = develop/hardening
|
41
|
+
branch = develop/pipes-travis
|
42
|
+
branch = develop/travis
|
43
|
+
branch = master
|
44
|
+
branch = master AND NOT(type IN (push,pull_request))
|
45
|
+
branch = master AND type = pull_request
|
46
|
+
branch = master AND type = push
|
47
|
+
branch = master OR tag =~ ^v\d+\.\d+$
|
48
|
+
branch = master OR tag IS present
|
49
|
+
branch = master OR type = pull_request OR branch =~ ^rc_.*
|
50
|
+
branch = staging
|
51
|
+
branch = task/ASI-93-auto-update-campaign-performance-summary-for-periscope
|
52
|
+
branch = travis
|
53
|
+
branch =~ /^release.*$/
|
54
|
+
branch =~ /release/
|
55
|
+
branch =~ ^develop
|
56
|
+
branch =~ ^develop OR branch =~ ^master OR branch =~ ^release
|
57
|
+
branch =~ ^release
|
58
|
+
branch =~ ^release.*$
|
59
|
+
branch =~ ^release/ or tag =~ ^version_code\/
|
60
|
+
branch IN (master, ^develop, ^release)
|
61
|
+
branch IN (master, develop) OR branch =~ ^release\/.+$ OR branch =~ ^hotfix\/.+$ OR branch =~ ^bugfix\/.+$ OR branch =~ ^support\/.+$ ORtag IS present OR type IN (pull_request, api)
|
62
|
+
branch IN (master, development, features)
|
63
|
+
branch is blank
|
64
|
+
env(TRAVIS_SECURE_ENV_VARS) = true
|
65
|
+
fork = false
|
66
|
+
not tag =~ ^autobuild
|
67
|
+
tag =~ ''
|
68
|
+
tag =~ /(^version_code\/)|(^$)/
|
69
|
+
tag =~ /^$|\s+/
|
70
|
+
tag =~ [0-9]+\.[0-9]+\.[0-9]+
|
71
|
+
tag =~ ^\d+(\.\d+)+(-.*)?
|
72
|
+
tag =~ ^\d+(\.\d+)+(-.*)? OR branch = travisbuilds-selenium
|
73
|
+
tag =~ ^travis*
|
74
|
+
tag =~ ^v
|
75
|
+
tag =~ ^v
|
76
|
+
tag =~ ^version_code/ OR (tag IS NOT present)
|
77
|
+
tag =~ ^version_code/ OR tag IS NOT present
|
78
|
+
tag =~ ^version_code\/ OR tag =~ ^$
|
79
|
+
tag =~ ^version_code\/|^$
|
80
|
+
tag IS blank
|
81
|
+
tag IS blank
|
82
|
+
tag IS present
|
83
|
+
tag is blank
|
84
|
+
type = push
|
85
|
+
type IN (api, cron)
|
86
|
+
type IN (push, pull_request)
|
87
|
+
strs
|
88
|
+
|
89
|
+
fixed = <<~strs.split("\n").reject(&:empty?)
|
90
|
+
true
|
91
|
+
1=1
|
92
|
+
( branch NOT IN (master) OR fork = true ) AND type IN (push, api, pull_request)
|
93
|
+
(((type != pull_request) AND (branch = master)) OR (tag =~ ^\\d+\\.\\d+\\.\\d+$))
|
94
|
+
((branch = master) OR (tag =~ ^\\d+\\.\\d+\\.\\d+$))
|
95
|
+
(branch = master AND type != pull_request) AND (NOT tag =~ ^v)
|
96
|
+
(branch = master AND type != pull_request) OR (tag =~ ^v)
|
97
|
+
(branch = master OR branch =~ ^infra/$) AND type = push
|
98
|
+
(branch = master OR tag =~ ^deploy/) AND (type != pull_request)
|
99
|
+
(branch = master) AND (NOT (tag =~prod_))
|
100
|
+
(branch = master) AND (tag =~ ^v\\d+\\.\\d+\\.\\d+.*$) AND (type IN (push, pull_request))
|
101
|
+
(branch = master) AND (tag =~ ^v\\d+\\.\\d+\\.\\d+.*$) AND type IN (push, pull_request)
|
102
|
+
(tag =~ ^prod_)
|
103
|
+
(tag =~ ^v) AND (branch = master)
|
104
|
+
(tag =~ ^v) AND (branch = release)
|
105
|
+
(tag =~ ^v) AND (repo = meniga/mobile-sdk-android)
|
106
|
+
(type IN (cron, api)) OR ((tag IS present) AND (tag =~ ^v))
|
107
|
+
(type IN (cron, api)) OR (tag =~ ^v)
|
108
|
+
(type IN (cron, api)) OR (tag =~ ^v?([0-9]+)\\.([0-9]+)\\.([0-9]+)(?:(?:\\-|\\+)([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)){0,2}$)
|
109
|
+
NOT type IN (pull_request) AND (branch = master OR tag =~ ^v[1-9])
|
110
|
+
TRAVIS_PULL_REQUEST = false
|
111
|
+
branch = master AND tag is blank AND fork is false AND repo = head_repo AND type != pull_request
|
112
|
+
branch = master AND tag is blank AND fork is false AND type != pull_request
|
113
|
+
branch = master AND type = push
|
114
|
+
branch = master AND type == pull_request
|
115
|
+
branch IN (master, dev_package)
|
116
|
+
branch NOT IN (master) OR fork = true
|
117
|
+
branch in (master, dev) OR type == pull
|
118
|
+
env(FOO) = env(TRAVIS_SECURE_ENV_VARS)
|
119
|
+
env(IS_TAGS_ONLY) = env(NO)
|
120
|
+
env(IS_TAGS_ONLY) = env(NO) AND env(YES) IN (env(IS_FULL_REGRESSION), env(IS_READY_TO_BUILD))
|
121
|
+
env(PRIOR_VERSION) != env(RELEASE_VERSION)
|
122
|
+
env(PRIOR_VERSION) IS present AND env(PRIOR_VERSION) != env(RELEASE_VERSION) AND branch = master AND type = push AND repo = cotsog/travis_ci_prod_regular
|
123
|
+
env(PRIOR_VERSION) IS present AND env(PRIOR_VERSION) != env(RELEASE_VERSION) AND branch = master AND type = push AND repo = justien/travis_conditional_stages
|
124
|
+
env(PRIOR_VERSION) IS present AND env(PRIOR_VERSION) != env(RELEASE_VERSION) AND branch = master AND type = push AND repo = plus3it/terraform-aws-watchmaker
|
125
|
+
env(TRAVIS_SECURE_ENV_VARS) IS true
|
126
|
+
env(env_name) IS blank
|
127
|
+
env(env_name) IS present
|
128
|
+
tag =~ ^version_code/ OR tag IS NOT present
|
129
|
+
tag IS NOT blank
|
130
|
+
tag IS NOT present
|
131
|
+
tag IS blank
|
132
|
+
tag IS present
|
133
|
+
tag IS present OR branch == master
|
134
|
+
true = false
|
135
|
+
type = pull_request
|
136
|
+
type IN (api, cron)
|
137
|
+
type IN (push, cron) AND (NOT branch =~ [0-9]{8,})
|
138
|
+
type IN (push, cron) AND (tag =~ ^$)
|
139
|
+
type IN (push, cron) AND NOT (branch =~ [0-9]{8,})
|
140
|
+
type NOT IN (api, cron)
|
141
|
+
type NOT IN (cron)
|
142
|
+
|
143
|
+
env(FORCE_REBUILD) ~= ^true$
|
144
|
+
env(REBUILD) ~= ^true$ OR env(FORCE_REBUILD) ~= ^true$ OR (branch = master AND type = push)
|
145
|
+
type = cron OR env(TEST_SQLITE) ~= ^true$
|
146
|
+
|
147
|
+
branch = master AND tag is blank AND fork is false AND repo = head_repo AND type != pull_request
|
148
|
+
tags IS blank
|
149
|
+
type = cron OR env(TEST_SQLITE) IS true
|
150
|
+
tag !~ \\\n ^v-
|
151
|
+
|
152
|
+
env(REBUILD) OR env(FORCE_REBUILD) OR branch = master
|
153
|
+
env(DOCKER_BUILD)
|
154
|
+
env(DOCKER_PASSWORD)
|
155
|
+
type = cron OR env(TEST_SQLITE)
|
156
|
+
|
157
|
+
type != pull_request AND ( branch =~ ^release$ OR branch =~ ^release-(\d).(\d).(\d)$ )
|
158
|
+
type != pull_request AND (branch =~ ^release$ OR branch =~ ^release-(\d).(\d).(\d)$)
|
159
|
+
(branch = master) OR (branch =~ ^release/) OR (tag is present)
|
160
|
+
strs
|
161
|
+
|
162
|
+
kaputt = <<~strs.split("\n")
|
163
|
+
# IS used for comparison
|
164
|
+
(branch = dev) AND (type IS cron)
|
165
|
+
(repo IS 2m/sssio) AND (tag =~ ^v)
|
166
|
+
branch IS master
|
167
|
+
type IS push
|
168
|
+
|
169
|
+
# broken IN list
|
170
|
+
(type = pull_request) AND (branch IN dev)
|
171
|
+
|
172
|
+
# = followed by IN
|
173
|
+
branch = IN (master, dev_package)
|
174
|
+
|
175
|
+
# missing boolean operand
|
176
|
+
branch = master AND ( tag =~ ^deploy/ OR )
|
177
|
+
|
178
|
+
# NON instead of NOT
|
179
|
+
branch = master AND type NON IN (pull_request)
|
180
|
+
|
181
|
+
# missing AND or OR
|
182
|
+
branch = master NOT type = pull_request
|
183
|
+
|
184
|
+
# triple operator
|
185
|
+
branch = type = pull_request
|
186
|
+
|
187
|
+
# missing IS
|
188
|
+
tag NOT present
|
189
|
+
|
190
|
+
# bash code
|
191
|
+
env(FORCE_JOBS) IS blank && (branch = ${MASTER_BRANCH} OR type = pull_request)
|
192
|
+
|
193
|
+
# operator !=~
|
194
|
+
branch = master or branch !=~ ^renovate/
|
195
|
+
|
196
|
+
# needs /.../ around the pattern
|
197
|
+
env(TRAVIS_COMMIT_MESSAGE) =~ ^Replace Conditionalaaa$
|
198
|
+
|
199
|
+
# missing quotes
|
200
|
+
env(TRAVIS_COMMIT_MESSAGE) IN (Replace Conditional)
|
201
|
+
env(TRAVIS_COMMIT_MESSAGE) = Replace conditional
|
202
|
+
strs
|
203
|
+
|
204
|
+
strs = used + fixed
|
205
|
+
|
206
|
+
strs.each do |str|
|
207
|
+
context do
|
208
|
+
let(:subject) { described_class.parse(str) }
|
209
|
+
it(str) { expect { subject }.to_not raise_error }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context do
|
214
|
+
let(:str) do
|
215
|
+
%(
|
216
|
+
repo = iribeyri/travis-experiments
|
217
|
+
AND type != pull_request
|
218
|
+
AND (branch = master OR tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$)
|
219
|
+
)
|
220
|
+
end
|
221
|
+
it { expect { described_class.parse(str) }.to_not raise_error }
|
222
|
+
end
|
223
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: travis-conditions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Travis CI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -26,23 +26,62 @@ dependencies:
|
|
26
26
|
version: '1.8'
|
27
27
|
description:
|
28
28
|
email: contact@travis-ci.org
|
29
|
-
executables:
|
29
|
+
executables:
|
30
|
+
- travis-conditions
|
30
31
|
extensions: []
|
31
32
|
extra_rdoc_files: []
|
32
33
|
files:
|
34
|
+
- CHANGELOG.md
|
33
35
|
- Gemfile
|
34
36
|
- Gemfile.lock
|
35
37
|
- LICENSE
|
38
|
+
- NOTES.md
|
36
39
|
- README.md
|
40
|
+
- bin/travis-conditions
|
37
41
|
- lib/travis/conditions.rb
|
38
|
-
- lib/travis/conditions/
|
39
|
-
- lib/travis/conditions/
|
40
|
-
- lib/travis/conditions/
|
42
|
+
- lib/travis/conditions/v0.rb
|
43
|
+
- lib/travis/conditions/v0/data.rb
|
44
|
+
- lib/travis/conditions/v0/eval.rb
|
45
|
+
- lib/travis/conditions/v0/parser.rb
|
46
|
+
- lib/travis/conditions/v1.rb
|
47
|
+
- lib/travis/conditions/v1/boolean.rb
|
48
|
+
- lib/travis/conditions/v1/data.rb
|
49
|
+
- lib/travis/conditions/v1/eval.rb
|
50
|
+
- lib/travis/conditions/v1/helper.rb
|
51
|
+
- lib/travis/conditions/v1/parser.rb
|
41
52
|
- lib/travis/conditions/version.rb
|
42
|
-
- spec/
|
43
|
-
- spec/eval_spec.rb
|
44
|
-
- spec/parser_spec.rb
|
53
|
+
- spec/conditions_spec.rb
|
45
54
|
- spec/spec_helper.rb
|
55
|
+
- spec/v0/conditions_spec.rb
|
56
|
+
- spec/v0/data_spec.rb
|
57
|
+
- spec/v0/eval_spec.rb
|
58
|
+
- spec/v0/fixtures/failures.txt
|
59
|
+
- spec/v0/fixtures/passes.txt
|
60
|
+
- spec/v0/parser_spec.rb
|
61
|
+
- spec/v1/conditions_spec.rb
|
62
|
+
- spec/v1/data_spec.rb
|
63
|
+
- spec/v1/eval_spec.rb
|
64
|
+
- spec/v1/fixtures/failures.txt
|
65
|
+
- spec/v1/fixtures/passes.txt
|
66
|
+
- spec/v1/parser/boolean_spec.rb
|
67
|
+
- spec/v1/parser/call_spec.rb
|
68
|
+
- spec/v1/parser/comma_spec.rb
|
69
|
+
- spec/v1/parser/cont_spec.rb
|
70
|
+
- spec/v1/parser/eq_spec.rb
|
71
|
+
- spec/v1/parser/in_list_spec.rb
|
72
|
+
- spec/v1/parser/is_pred_spec.rb
|
73
|
+
- spec/v1/parser/list_spec.rb
|
74
|
+
- spec/v1/parser/operand_spec.rb
|
75
|
+
- spec/v1/parser/parens_spec.rb
|
76
|
+
- spec/v1/parser/quoted_spec.rb
|
77
|
+
- spec/v1/parser/re_spec.rb
|
78
|
+
- spec/v1/parser/regex_spec.rb
|
79
|
+
- spec/v1/parser/space_spec.rb
|
80
|
+
- spec/v1/parser/term_spec.rb
|
81
|
+
- spec/v1/parser/val_spec.rb
|
82
|
+
- spec/v1/parser/var_spec.rb
|
83
|
+
- spec/v1/parser_spec.rb
|
84
|
+
- spec/v1/user_spec.rb
|
46
85
|
homepage: https://github.com/travis-ci/travis-conditions
|
47
86
|
licenses:
|
48
87
|
- MIT
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Travis
|
2
|
-
module Conditions
|
3
|
-
class Data < Struct.new(:data)
|
4
|
-
def initialize(data)
|
5
|
-
data = symbolize(data)
|
6
|
-
data[:env] = symbolize(to_h(data[:env] || {}))
|
7
|
-
super(data)
|
8
|
-
end
|
9
|
-
|
10
|
-
def [](key)
|
11
|
-
data[key.to_sym]
|
12
|
-
end
|
13
|
-
|
14
|
-
def env(key)
|
15
|
-
data.fetch(:env, {})[key.to_sym]
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def to_h(obj)
|
21
|
-
case obj
|
22
|
-
when Hash
|
23
|
-
obj
|
24
|
-
else
|
25
|
-
Array(obj).map { |value| split(value.to_s) }.to_h
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def split(str)
|
30
|
-
str.split('=', 2)
|
31
|
-
end
|
32
|
-
|
33
|
-
def symbolize(value)
|
34
|
-
case value
|
35
|
-
when Hash
|
36
|
-
value.map { |key, value| [key.to_sym, symbolize(value)] }.to_h
|
37
|
-
when Array
|
38
|
-
value.map { |value| symbolize(value) }
|
39
|
-
else
|
40
|
-
value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module Travis
|
2
|
-
module Conditions
|
3
|
-
class Eval < Struct.new(:sexp, :data)
|
4
|
-
def apply
|
5
|
-
!!evl(sexp)
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def evl(value)
|
11
|
-
case value
|
12
|
-
when Array
|
13
|
-
send(*value)
|
14
|
-
else
|
15
|
-
data[value]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def not(lft)
|
20
|
-
!evl(lft)
|
21
|
-
end
|
22
|
-
|
23
|
-
def or(lft, rgt)
|
24
|
-
evl(lft) || evl(rgt)
|
25
|
-
end
|
26
|
-
|
27
|
-
def and(lft, rgt)
|
28
|
-
evl(lft) && evl(rgt)
|
29
|
-
end
|
30
|
-
|
31
|
-
def eq(lft, rgt)
|
32
|
-
evl(lft) == rgt
|
33
|
-
end
|
34
|
-
|
35
|
-
def not_eq(lft, rgt)
|
36
|
-
not eq(lft, rgt)
|
37
|
-
end
|
38
|
-
|
39
|
-
def match(lft, rgt)
|
40
|
-
evl(lft) =~ Regexp.new(rgt)
|
41
|
-
end
|
42
|
-
|
43
|
-
def not_match(lft, rgt)
|
44
|
-
not match(lft, rgt)
|
45
|
-
end
|
46
|
-
|
47
|
-
def in(lft, rgt)
|
48
|
-
rgt.include?(evl(lft))
|
49
|
-
end
|
50
|
-
|
51
|
-
def is(lft, rgt)
|
52
|
-
send(rgt, evl(lft))
|
53
|
-
end
|
54
|
-
|
55
|
-
def env(key)
|
56
|
-
data.env(key)
|
57
|
-
end
|
58
|
-
|
59
|
-
def present(value)
|
60
|
-
value.respond_to?(:empty?) && !value.empty?
|
61
|
-
end
|
62
|
-
|
63
|
-
def blank(value)
|
64
|
-
!present(value)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,202 +0,0 @@
|
|
1
|
-
require 'parslet'
|
2
|
-
|
3
|
-
module Travis
|
4
|
-
module Conditions
|
5
|
-
class Parser < Struct.new(:opts)
|
6
|
-
FUNCS = %w(env)
|
7
|
-
PRESENCE = %w(present blank)
|
8
|
-
|
9
|
-
def parse(str)
|
10
|
-
parser.parse(str)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def parser
|
16
|
-
@parser ||= define_parser(opts[:keys]).new
|
17
|
-
end
|
18
|
-
|
19
|
-
def define_parser(keywords)
|
20
|
-
Class.new(Parslet::Parser) do
|
21
|
-
root :expr_or
|
22
|
-
|
23
|
-
rule :expr_or do
|
24
|
-
spaced(expr_and.as(:lft), op_or, expr_or.as(:rgt)).as(:or) | expr_and
|
25
|
-
end
|
26
|
-
|
27
|
-
rule :expr_and do
|
28
|
-
spaced(expr_inner.as(:lft), op_and, expr_and.as(:rgt)).as(:and) | expr_inner
|
29
|
-
end
|
30
|
-
|
31
|
-
rule :expr_inner do
|
32
|
-
lnot(parens(expr_or) | expr_incl | expr_is | expr_regex | expr_cmp)
|
33
|
-
end
|
34
|
-
|
35
|
-
rule :expr_cmp do
|
36
|
-
spaced(lhs.as(:lft), op_cmp.as(:op), value.as(:rgt)).as(:cmp)
|
37
|
-
end
|
38
|
-
|
39
|
-
rule :expr_regex do
|
40
|
-
spaced(lhs.as(:lft), op_regex.as(:op), regex.as(:rgt)).as(:cmp)
|
41
|
-
end
|
42
|
-
|
43
|
-
rule :expr_incl do
|
44
|
-
spaced(lhs.as(:lft), op_incl, parens(list).as(:rgt)).as(:incl)
|
45
|
-
end
|
46
|
-
|
47
|
-
rule :expr_is do
|
48
|
-
spaced(lhs.as(:lft), op_is, presence.as(:rgt)).as(:is)
|
49
|
-
end
|
50
|
-
|
51
|
-
def lnot(node)
|
52
|
-
(stri('not').maybe >> space >> node.as(:rgt)).as(:not) | node
|
53
|
-
end
|
54
|
-
|
55
|
-
rule :list do
|
56
|
-
(value >> (ts(str(',')) >> value).repeat)
|
57
|
-
end
|
58
|
-
|
59
|
-
rule :lhs do
|
60
|
-
func | keyword
|
61
|
-
end
|
62
|
-
|
63
|
-
rule :keyword do
|
64
|
-
stris(*keywords)
|
65
|
-
end
|
66
|
-
|
67
|
-
rule :func do
|
68
|
-
(stris(*FUNCS).as(:name) >> parens(word)).as(:func)
|
69
|
-
end
|
70
|
-
|
71
|
-
rule :word do
|
72
|
-
match('[\w_\-]').repeat(1).as(:str)
|
73
|
-
end
|
74
|
-
|
75
|
-
rule :regex do
|
76
|
-
quoted('/') | match('[\S]').repeat(1).as(:str)
|
77
|
-
end
|
78
|
-
|
79
|
-
rule :value do
|
80
|
-
unquoted | quoted('"') | quoted("'")
|
81
|
-
end
|
82
|
-
|
83
|
-
rule :unquoted do
|
84
|
-
match('[^\s\"\'\(\),]').repeat(1).as(:str)
|
85
|
-
end
|
86
|
-
|
87
|
-
def quoted(chr)
|
88
|
-
str(chr) >> match("[^#{chr}]").repeat.as(:str) >> str(chr)
|
89
|
-
end
|
90
|
-
|
91
|
-
rule :presence do
|
92
|
-
(stris(*PRESENCE)).as(:str)
|
93
|
-
end
|
94
|
-
|
95
|
-
rule :op_is do
|
96
|
-
stri('is')
|
97
|
-
end
|
98
|
-
|
99
|
-
rule :op_cmp do
|
100
|
-
str('=') | str('!=')
|
101
|
-
end
|
102
|
-
|
103
|
-
rule :op_regex do
|
104
|
-
str('=~') | str('!~')
|
105
|
-
end
|
106
|
-
|
107
|
-
rule :op_incl do
|
108
|
-
stri('in')
|
109
|
-
end
|
110
|
-
|
111
|
-
rule :op_or do
|
112
|
-
stri('or')
|
113
|
-
end
|
114
|
-
|
115
|
-
rule :op_and do
|
116
|
-
stri('and')
|
117
|
-
end
|
118
|
-
|
119
|
-
rule :space do
|
120
|
-
match('\s').repeat(1)
|
121
|
-
end
|
122
|
-
|
123
|
-
rule :space? do
|
124
|
-
space.maybe
|
125
|
-
end
|
126
|
-
|
127
|
-
def stris(*strs)
|
128
|
-
strs.inject(stri(strs.shift)) { |node, str| node | stri(str) }
|
129
|
-
end
|
130
|
-
|
131
|
-
def stri(str)
|
132
|
-
str(str) | str(str.upcase)
|
133
|
-
end
|
134
|
-
|
135
|
-
def parens?(node)
|
136
|
-
spaced?(str('(').maybe, node, str(')').maybe)
|
137
|
-
end
|
138
|
-
|
139
|
-
def parens(node)
|
140
|
-
spaced?(str('('), node, str(')'))
|
141
|
-
end
|
142
|
-
|
143
|
-
def spaced?(*nodes)
|
144
|
-
nodes.zip([space?] * nodes.size).flatten[0..-2].inject(&:>>)
|
145
|
-
end
|
146
|
-
|
147
|
-
def spaced(*nodes)
|
148
|
-
# nodes.zip([space] * nodes.size).flatten[0..-2].inject(&:>>)
|
149
|
-
nodes.zip([space?] * nodes.size).flatten[0..-2].inject(&:>>)
|
150
|
-
end
|
151
|
-
|
152
|
-
def ls(node)
|
153
|
-
space? >> node
|
154
|
-
end
|
155
|
-
|
156
|
-
def ts(node)
|
157
|
-
node >> space?
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
class Transform < Parslet::Transform
|
164
|
-
OP = {
|
165
|
-
'=' => :eq,
|
166
|
-
'!=' => :not_eq,
|
167
|
-
'=~' => :match,
|
168
|
-
'!~' => :not_match,
|
169
|
-
}
|
170
|
-
|
171
|
-
str = ->(node) { node.is_a?(Hash) ? node[:str].to_s : node.to_s }
|
172
|
-
sym = ->(node) { str.(node).downcase.to_sym }
|
173
|
-
func = ->(node) { [sym.(node[:func][:name]), str.(node[:func])] }
|
174
|
-
list = ->(node) { node.is_a?(Array) ? node.map { |v| str.(v) } : [str.(node)] }
|
175
|
-
lhs = ->(node) { node.is_a?(Hash) && node.key?(:func) ? func.(node) : str.(node) }
|
176
|
-
|
177
|
-
rule not: { rgt: subtree(:rgt) } do
|
178
|
-
[:not, rgt]
|
179
|
-
end
|
180
|
-
|
181
|
-
rule or: { lft: subtree(:lft), rgt: subtree(:rgt) } do
|
182
|
-
[:or, lft, rgt]
|
183
|
-
end
|
184
|
-
|
185
|
-
rule and: { lft: subtree(:lft), rgt: subtree(:rgt) } do
|
186
|
-
[:and, lft, rgt]
|
187
|
-
end
|
188
|
-
|
189
|
-
rule cmp: { op: simple(:op), lft: subtree(:lft), rgt: subtree(:rgt) } do
|
190
|
-
[OP[op.to_s], lhs.(lft), str.(rgt)]
|
191
|
-
end
|
192
|
-
|
193
|
-
rule incl: { lft: subtree(:lft), rgt: subtree(:rgt) } do
|
194
|
-
[:in, lhs.(lft), list.(rgt)]
|
195
|
-
end
|
196
|
-
|
197
|
-
rule is: { lft: subtree(:lft), rgt: subtree(:rgt) } do
|
198
|
-
[:is, lhs.(lft), sym.(rgt)]
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|