travis-yaml 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -8
- data/Gemfile +3 -6
- data/Gemfile.lock +20 -50
- data/README.md +97 -2
- data/SPEC.md +116 -33
- data/lib/travis/yaml.rb +6 -3
- data/lib/travis/yaml/matrix.rb +12 -17
- data/lib/travis/yaml/nodes.rb +4 -0
- data/lib/travis/yaml/nodes/addons.rb +44 -0
- data/lib/travis/yaml/nodes/android.rb +7 -0
- data/lib/travis/yaml/nodes/cache.rb +5 -3
- data/lib/travis/yaml/nodes/deploy_conditions.rb +2 -1
- data/lib/travis/yaml/nodes/deploy_entry.rb +46 -0
- data/lib/travis/yaml/nodes/dist.rb +6 -0
- data/lib/travis/yaml/nodes/env.rb +1 -1
- data/lib/travis/yaml/nodes/group.rb +6 -0
- data/lib/travis/yaml/nodes/language.rb +3 -2
- data/lib/travis/yaml/nodes/language_specific.rb +2 -2
- data/lib/travis/yaml/nodes/mapping.rb +39 -10
- data/lib/travis/yaml/nodes/node.rb +58 -1
- data/lib/travis/yaml/nodes/notifications.rb +10 -6
- data/lib/travis/yaml/nodes/open_mapping.rb +1 -1
- data/lib/travis/yaml/nodes/os.rb +1 -1
- data/lib/travis/yaml/nodes/os_entry.rb +7 -5
- data/lib/travis/yaml/nodes/root.rb +28 -4
- data/lib/travis/yaml/nodes/scalar.rb +16 -1
- data/lib/travis/yaml/nodes/sequence.rb +38 -0
- data/lib/travis/yaml/nodes/version.rb +13 -0
- data/lib/travis/yaml/nodes/version_list.rb +4 -0
- data/lib/travis/yaml/parser/psych.rb +11 -5
- data/lib/travis/yaml/secure_string.rb +35 -2
- data/lib/travis/yaml/serializer.rb +17 -0
- data/lib/travis/yaml/serializer/generic.rb +114 -0
- data/lib/travis/yaml/serializer/json.rb +72 -0
- data/lib/travis/yaml/serializer/legacy.rb +32 -0
- data/lib/travis/yaml/serializer/ruby.rb +13 -0
- data/lib/travis/yaml/serializer/yaml.rb +41 -0
- data/lib/travis/yaml/version.rb +1 -1
- data/play/spec.rb +24 -17
- data/spec/matrix_spec.rb +57 -0
- data/spec/nodes/addons_spec.rb +63 -0
- data/spec/nodes/cache_spec.rb +4 -4
- data/spec/nodes/deploy_spec.rb +12 -0
- data/spec/nodes/dist_spec.rb +11 -0
- data/spec/nodes/env_spec.rb +48 -0
- data/spec/nodes/git_spec.rb +1 -1
- data/spec/nodes/group_spec.rb +11 -0
- data/spec/nodes/node_js_spec.rb +14 -0
- data/spec/nodes/notifications_spec.rb +7 -0
- data/spec/nodes/os_spec.rb +13 -0
- data/spec/nodes/root_spec.rb +36 -0
- data/spec/nodes/secure_spec.rb +145 -0
- data/spec/parser/psych_spec.rb +6 -0
- data/spec/parser/ruby_spec.rb +1 -1
- data/spec/serializer/json_spec.rb +30 -0
- data/spec/serializer/legacy_spec.rb +47 -0
- data/spec/serializer/ruby_spec.rb +21 -0
- data/spec/serializer/yaml_spec.rb +47 -0
- data/spec/support/coverage.rb +9 -9
- data/spec/yaml_spec.rb +23 -0
- data/travis-yaml.gemspec +2 -3
- metadata +42 -22
- data/config.ru +0 -2
- data/play/weblint.rb +0 -296
data/lib/travis/yaml.rb
CHANGED
@@ -7,17 +7,20 @@ module Travis
|
|
7
7
|
require 'travis/yaml/nodes'
|
8
8
|
require 'travis/yaml/matrix'
|
9
9
|
require 'travis/yaml/parser'
|
10
|
+
require 'travis/yaml/serializer'
|
10
11
|
|
11
12
|
extend self
|
12
13
|
|
13
14
|
def parse(value)
|
14
|
-
Parser.parse(value)
|
15
|
+
result = Parser.parse(value)
|
16
|
+
yield result if block_given?
|
17
|
+
result
|
15
18
|
end
|
16
19
|
|
17
20
|
alias_method :load, :parse
|
18
21
|
|
19
|
-
def parse!(value, file_name = '.travis.yml')
|
20
|
-
result = parse(value)
|
22
|
+
def parse!(value, file_name = '.travis.yml', &block)
|
23
|
+
result = parse(value, &block)
|
21
24
|
result.nested_warnings.each do |key, message|
|
22
25
|
warn key.empty? ? "#{file_name}: #{message}" :
|
23
26
|
"#{file_name}: #{key.join(?.)} section - #{message}"
|
data/lib/travis/yaml/matrix.rb
CHANGED
@@ -10,23 +10,18 @@ module Travis::Yaml
|
|
10
10
|
KEYS = EXPAND_KEYS + [:env]
|
11
11
|
|
12
12
|
class Entry < DelegateClass(Nodes::Root)
|
13
|
-
attr_reader :
|
14
|
-
|
13
|
+
attr_reader :matrix_attributes
|
15
14
|
def initialize(root, matrix_attributes)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def inspect
|
29
|
-
"#<#{self.class}: #{matrix_attributes}>"
|
15
|
+
@matrix_attributes = matrix_attributes
|
16
|
+
normal_attributes = matrix_attributes.select { |key| key != :env }
|
17
|
+
generated_root = root.with_value(normal_attributes)
|
18
|
+
if matrix_attributes[:env]
|
19
|
+
generated_root.env.global = Travis::Yaml::Nodes::Env::List.new(generated_root.env)
|
20
|
+
generated_root.env.global.add_value! root.env.global if root.env.global
|
21
|
+
generated_root.env.global.add_value! matrix_attributes[:env]
|
22
|
+
generated_root.env.mapping.delete "matrix"
|
23
|
+
end
|
24
|
+
super(generated_root)
|
30
25
|
end
|
31
26
|
end
|
32
27
|
|
@@ -53,7 +48,7 @@ module Travis::Yaml
|
|
53
48
|
m.include.each { |i| entries << Hash[axes.map { |k| [k, i[k]] }] } if m.include
|
54
49
|
end
|
55
50
|
entries.map! { |attributes| Entry.new(root, attributes) }
|
56
|
-
entries.any? ? entries : [root]
|
51
|
+
entries.any? ? entries : [Entry.new(root, {})]
|
57
52
|
end
|
58
53
|
end
|
59
54
|
|
data/lib/travis/yaml/nodes.rb
CHANGED
@@ -35,6 +35,10 @@ module Travis::Yaml
|
|
35
35
|
require 'travis/yaml/nodes/notifications'
|
36
36
|
require 'travis/yaml/nodes/branches'
|
37
37
|
require 'travis/yaml/nodes/cache'
|
38
|
+
require 'travis/yaml/nodes/addons'
|
39
|
+
require 'travis/yaml/nodes/android'
|
40
|
+
require 'travis/yaml/nodes/dist'
|
41
|
+
require 'travis/yaml/nodes/group'
|
38
42
|
require 'travis/yaml/nodes/root'
|
39
43
|
end
|
40
44
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Travis::Yaml
|
2
|
+
module Nodes
|
3
|
+
class Addons < Mapping
|
4
|
+
class Addon < Mapping
|
5
|
+
def self.[](*keys)
|
6
|
+
Class.new(self) { map(*keys, to: Scalar[:str, :secure])}
|
7
|
+
end
|
8
|
+
|
9
|
+
def visit_scalar(visitor, type, value, implicit = true)
|
10
|
+
return super unless type == :bool
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class CoverityScan < Addon
|
15
|
+
class Project < Mapping
|
16
|
+
map :name, to: Scalar[:str, :secure], required: true
|
17
|
+
end
|
18
|
+
|
19
|
+
map :project, to: Project
|
20
|
+
map :build_script_url, :branch_pattern, :notification_email, :build_command,
|
21
|
+
:build_command_prepend, to: Scalar[:str, :secure]
|
22
|
+
end
|
23
|
+
|
24
|
+
class Artifacts < Addon
|
25
|
+
map :bucket, to: Scalar[:str, :secure], required: true
|
26
|
+
map :key, to: Scalar[:str, :secure], required: true
|
27
|
+
map :paths, to: Sequence
|
28
|
+
map :secret, to: Scalar[:str, :secure], required: true
|
29
|
+
|
30
|
+
map :branch, :log_format, :target_paths, to: Scalar[:str, :secure]
|
31
|
+
map :debug, :concurrency, :max_size, to: Scalar[:str, :int, :secure]
|
32
|
+
end
|
33
|
+
|
34
|
+
map :artifacts, to: Artifacts, drop_empty: false
|
35
|
+
map :code_climate, to: Addon[:repo_token], drop_empty: false
|
36
|
+
map :coverity_scan, to: CoverityScan
|
37
|
+
map :firefox, to: Version
|
38
|
+
map :hosts, to: Sequence
|
39
|
+
map :postgresql, to: Version
|
40
|
+
map :sauce_connect, to: Addon[:username, :access_key], drop_empty: false
|
41
|
+
map :ssh_known_hosts, to: Sequence
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module Travis::Yaml
|
2
2
|
module Nodes
|
3
3
|
class Cache < Mapping
|
4
|
-
map :apt, :bundler, to: Scalar[:bool]
|
4
|
+
map :apt, :bundler, :cocoapods, to: Scalar[:bool]
|
5
|
+
map :edge, to: Scalar[:bool], experimental: true
|
5
6
|
map :directories, to: Sequence
|
6
7
|
|
7
8
|
def visit_scalar(visitor, type, value, implicit = true)
|
8
9
|
case type
|
9
10
|
when :bool
|
10
|
-
visit_key_value(visitor, :bundler,
|
11
|
-
visit_key_value(visitor, :apt,
|
11
|
+
visit_key_value(visitor, :bundler, value)
|
12
|
+
visit_key_value(visitor, :apt, value)
|
13
|
+
visit_key_value(visitor, :cocoapods, value)
|
12
14
|
when :str
|
13
15
|
key = visitor.generate_key(self, value)
|
14
16
|
self[key] = true
|
@@ -4,7 +4,8 @@ module Travis::Yaml
|
|
4
4
|
include LanguageSpecific
|
5
5
|
map :jdk, :node, :perl, :php, :python, :ruby, :scala, :node, to: Version
|
6
6
|
map :rvm, to: :ruby
|
7
|
-
map :repo,
|
7
|
+
map :repo, to: Scalar[:str]
|
8
|
+
map :branch, :condition, to: Sequence[:str]
|
8
9
|
map :all_branches, :tags, to: Scalar[:bool]
|
9
10
|
prefix_scalar :branch
|
10
11
|
end
|
@@ -1,10 +1,56 @@
|
|
1
1
|
module Travis::Yaml
|
2
2
|
module Nodes
|
3
3
|
class DeployEntry < OpenMapping
|
4
|
+
class Setting < OpenMapping
|
5
|
+
KEY = ''
|
6
|
+
prefix_scalar KEY
|
7
|
+
default_type Scalar[:str, :secure]
|
8
|
+
|
9
|
+
def ==(other)
|
10
|
+
return true if super
|
11
|
+
return false unless branch_specific?
|
12
|
+
generic == other
|
13
|
+
end
|
14
|
+
|
15
|
+
def __getobj__
|
16
|
+
branch_specific? ? generic : super
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
branch_specific? ? generic.inspect : super
|
21
|
+
end
|
22
|
+
|
23
|
+
def branch_specific?
|
24
|
+
@mapping.size == 1 and @mapping.include? KEY
|
25
|
+
end
|
26
|
+
|
27
|
+
def branches
|
28
|
+
@mapping.keys - [KEY]
|
29
|
+
end
|
30
|
+
|
31
|
+
def generic
|
32
|
+
@mapping[KEY]
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_branch(name)
|
36
|
+
branches.each do |branch|
|
37
|
+
next if branch.to_s == name.to_s
|
38
|
+
warning "branch %p not permitted by deploy condition, dropping", branch
|
39
|
+
@mapping.delete(branch)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
default_type Setting
|
4
45
|
prefix_scalar :provider
|
5
46
|
map :provider, to: Scalar, required: true
|
6
47
|
map :edge, to: Scalar[:bool], experimental: true
|
7
48
|
map :on, to: DeployConditions
|
49
|
+
|
50
|
+
def verify
|
51
|
+
@mapping.each_value { |v| v.verify_branch(on.branch) if v.respond_to? :verify_branch } if on and on.branch
|
52
|
+
super
|
53
|
+
end
|
8
54
|
end
|
9
55
|
end
|
10
56
|
end
|
@@ -9,10 +9,11 @@ module Travis::Yaml
|
|
9
9
|
value jvm: :java, javascript: :node_js, node: :node_js, nodejs: :node_js, golang: :go,
|
10
10
|
objective_c: :"objective-c", obj_c: :"objective-c", objc: :"objective-c"
|
11
11
|
value "c++" => :cpp, "node.js" => :node_js, "obj-c" => :"objective-c"
|
12
|
+
value :generic, bash: :generic, sh: :generic, shell: :generic
|
12
13
|
|
13
14
|
def default_os
|
14
|
-
value == "objective-c" ?
|
15
|
+
value == "objective-c" ? "osx" : OSEntry.default
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
|
-
end
|
19
|
+
end
|
@@ -24,12 +24,12 @@ module Travis::Yaml
|
|
24
24
|
gemfile: %w[ruby objective-c],
|
25
25
|
composer_args: %w[php],
|
26
26
|
npm_args: %w[node_js],
|
27
|
-
|
27
|
+
android: %w[android]
|
28
28
|
}
|
29
29
|
|
30
30
|
def verify_language(language)
|
31
31
|
LANGUAGE_SPECIFIC.each do |key, languages|
|
32
|
-
next unless include? key and not languages.include? language
|
32
|
+
next unless include? key and not languages.include? language.value
|
33
33
|
mapping.delete mapped_key(key)
|
34
34
|
warning "specified %p, but setting is not relevant for %p", key.to_s, language
|
35
35
|
end
|
@@ -42,17 +42,27 @@ module Travis::Yaml
|
|
42
42
|
prefix_scalar(key)
|
43
43
|
end
|
44
44
|
|
45
|
-
def self.prefix_sequence(key)
|
46
|
-
|
47
|
-
|
45
|
+
def self.prefix_sequence(key = nil)
|
46
|
+
@prefix_sequence ||= superclass.respond_to?(:prefix_sequence) ? superclass.prefix_sequence : nil
|
47
|
+
if key
|
48
|
+
@prefix_sequence = key.to_s
|
49
|
+
define_method(:visit_sequence) do |visitor, value|
|
50
|
+
visit_key_value(visitor, key, value)
|
51
|
+
end
|
48
52
|
end
|
53
|
+
@prefix_sequence
|
49
54
|
end
|
50
55
|
|
51
|
-
def self.prefix_scalar(key, *types)
|
52
|
-
|
53
|
-
|
54
|
-
|
56
|
+
def self.prefix_scalar(key = nil, *types)
|
57
|
+
@prefix_scalar ||= superclass.respond_to?(:prefix_scalar) ? superclass.prefix_scalar : nil
|
58
|
+
if key
|
59
|
+
@prefix_scalar = key.to_s
|
60
|
+
define_method(:visit_scalar) do |visitor, type, value, implicit = true|
|
61
|
+
return super(visitor, type, value, implicit = true) if types.any? and not types.include?(type)
|
62
|
+
visit_key_value(visitor, key, value)
|
63
|
+
end
|
55
64
|
end
|
65
|
+
@prefix_scalar
|
56
66
|
end
|
57
67
|
|
58
68
|
def self.define_map_accessor(key)
|
@@ -84,6 +94,7 @@ module Travis::Yaml
|
|
84
94
|
|
85
95
|
def visit_key_value(visitor, key, value)
|
86
96
|
return warning("unexpected key %p, dropping", key) unless node = subnode_for(key)
|
97
|
+
warning("has multiple %p entries, keeping last entry", key) if self[key]
|
87
98
|
self[key] = node
|
88
99
|
visitor.accept(node, value)
|
89
100
|
end
|
@@ -93,12 +104,12 @@ module Travis::Yaml
|
|
93
104
|
end
|
94
105
|
|
95
106
|
def []=(key, value)
|
96
|
-
if
|
107
|
+
if mapped_key = mapped_key(key)
|
97
108
|
unless value.is_a? Node
|
98
|
-
node = subnode_for(
|
109
|
+
node = subnode_for(mapped_key)
|
99
110
|
value = node if Parser::Ruby.new(value).parse(node)
|
100
111
|
end
|
101
|
-
@mapping[
|
112
|
+
@mapping[mapped_key] = value
|
102
113
|
else
|
103
114
|
warning("unexpected key %p, dropping", key)
|
104
115
|
end
|
@@ -199,6 +210,24 @@ module Travis::Yaml
|
|
199
210
|
list = value.nested_warnings(*prefix, key) + list
|
200
211
|
end
|
201
212
|
end
|
213
|
+
|
214
|
+
def with_value!(value)
|
215
|
+
value = value.mapping while value.is_a? Mapping
|
216
|
+
value.each { |key, value| self[key] = value }
|
217
|
+
end
|
218
|
+
|
219
|
+
def each_scalar(type = nil, &block)
|
220
|
+
return enum_for(:each_scalar, type) unless block
|
221
|
+
@mapping.each_value { |v| v.each_scalar(type, &block) }
|
222
|
+
end
|
223
|
+
|
224
|
+
protected
|
225
|
+
|
226
|
+
def dup_values
|
227
|
+
duped_mapping = @mapping.map { |key, value| [key.dup, value.dup] }
|
228
|
+
@mapping = Hash[duped_mapping]
|
229
|
+
self
|
230
|
+
end
|
202
231
|
end
|
203
232
|
end
|
204
233
|
end
|
@@ -5,7 +5,7 @@ module Travis::Yaml
|
|
5
5
|
false
|
6
6
|
end
|
7
7
|
|
8
|
-
attr_accessor :
|
8
|
+
attr_accessor :parent
|
9
9
|
def initialize(parent)
|
10
10
|
@nested_warnings = []
|
11
11
|
@parent = parent
|
@@ -97,6 +97,63 @@ module Travis::Yaml
|
|
97
97
|
def to_s
|
98
98
|
__getobj__.to_s
|
99
99
|
end
|
100
|
+
|
101
|
+
def decrypt(&block)
|
102
|
+
each_scalar(SecureString) { |v| v.decrypt(&block) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def encrypt(&block)
|
106
|
+
each_scalar(SecureString) { |v| v.encrypt(&block) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def decrypted?
|
110
|
+
each_scalar(SecureString).all? { |v| v.decrypted? }
|
111
|
+
end
|
112
|
+
|
113
|
+
def encrypted?
|
114
|
+
each_scalar(SecureString).all? { |v| v.encrypted? }
|
115
|
+
end
|
116
|
+
|
117
|
+
def serialize(serializer, options = nil)
|
118
|
+
Serializer[serializer].serialize(self, options)
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_yaml(options = nil)
|
122
|
+
serialize(:yaml, options)
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_json(options = nil)
|
126
|
+
serialize(:json, options)
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_ruby(options = nil)
|
130
|
+
serialize(:ruby, options)
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_legacy_ruby(options = nil)
|
134
|
+
serialize(:legacy, options)
|
135
|
+
end
|
136
|
+
|
137
|
+
def with_value(value)
|
138
|
+
node = dup
|
139
|
+
node.with_value!(value)
|
140
|
+
node
|
141
|
+
end
|
142
|
+
|
143
|
+
def dup
|
144
|
+
super.dup_values
|
145
|
+
end
|
146
|
+
|
147
|
+
protected
|
148
|
+
|
149
|
+
def dup_values
|
150
|
+
self
|
151
|
+
end
|
152
|
+
|
153
|
+
def dup_ivar(name)
|
154
|
+
instance_variable_set(name, instance_variable_get(name).dup)
|
155
|
+
rescue TypeError
|
156
|
+
end
|
100
157
|
end
|
101
158
|
end
|
102
159
|
end
|
@@ -3,6 +3,10 @@ module Travis::Yaml
|
|
3
3
|
class Notifications < Mapping
|
4
4
|
Callbacks ||= FixedValue[:always, :never, :change]
|
5
5
|
|
6
|
+
class List < Sequence
|
7
|
+
type Scalar[:str, :secure]
|
8
|
+
end
|
9
|
+
|
6
10
|
class Notification < Mapping
|
7
11
|
map :enabled, :disabled, to: Scalar[:bool]
|
8
12
|
map :on_success, :on_failure, :on_start, to: Callbacks
|
@@ -12,7 +16,7 @@ module Travis::Yaml
|
|
12
16
|
end
|
13
17
|
|
14
18
|
def self.list(name)
|
15
|
-
map name, to:
|
19
|
+
map name, to: List
|
16
20
|
prefix_sequence name
|
17
21
|
prefix_scalar name, :str, :secure
|
18
22
|
end
|
@@ -32,7 +36,7 @@ module Travis::Yaml
|
|
32
36
|
end
|
33
37
|
|
34
38
|
class Template < Sequence
|
35
|
-
VARIABLES = %w[repository_slug repository_name repository build_number branch commit author message duration compare_url build_url]
|
39
|
+
VARIABLES = %w[repository_slug repository_name repository build_number branch commit author message duration compare_url build_url commit_message]
|
36
40
|
|
37
41
|
def verify
|
38
42
|
super
|
@@ -60,18 +64,18 @@ module Travis::Yaml
|
|
60
64
|
list :rooms
|
61
65
|
end
|
62
66
|
|
63
|
-
class
|
67
|
+
class Flowdock < Notification
|
64
68
|
map :api_token, to: Scalar[:str, :secure]
|
65
|
-
prefix_scalar
|
69
|
+
prefix_scalar :api_token, :str, :secure
|
66
70
|
end
|
67
71
|
|
68
72
|
map :webhooks, to: Notification[:urls]
|
69
73
|
map :email, to: Notification[:recipients]
|
70
74
|
map :sqwiggle, :slack, :campfire, to: WithTemplate[:rooms]
|
71
|
-
map :
|
75
|
+
map :flowdock, to: Flowdock
|
72
76
|
map :hipchat, to: Hipchat
|
73
77
|
map :irc, to: IRC
|
74
78
|
map :webhook, to: :webhooks
|
75
79
|
end
|
76
80
|
end
|
77
|
-
end
|
81
|
+
end
|