travis-conditions 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|