evrone-ci-router 0.2.0.pre22 → 0.2.0.pre23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/evrone-ci-router.gemspec +4 -2
- data/lib/evrone/ci/router.rb +14 -15
- data/lib/evrone/ci/router/build.rb +3 -3
- data/lib/evrone/ci/router/script_builder.rb +5 -5
- data/lib/evrone/ci/router/script_builder/env.rb +1 -1
- data/lib/evrone/ci/router/script_builder/ruby.rb +1 -1
- data/lib/evrone/ci/router/script_builder/script.rb +2 -2
- data/lib/evrone/ci/router/script_builder/webdav_cache.rb +4 -4
- data/lib/evrone/ci/router/version.rb +1 -1
- data/spec/lib/build_spec.rb +2 -2
- data/spec/lib/router_spec.rb +7 -7
- data/spec/lib/script_builder/webdav_cache_spec.rb +2 -2
- data/spec/lib/script_builder_spec.rb +4 -4
- data/spec/support/create.rb +5 -5
- metadata +20 -13
- data/lib/evrone/ci/router/build_matrix.rb +0 -113
- data/lib/evrone/ci/router/travis.rb +0 -110
- data/lib/evrone/ci/router/travis/serializable.rb +0 -45
- data/spec/lib/build_matrix_spec.rb +0 -189
- data/spec/lib/travis_spec.rb +0 -183
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 857440d03ba3e8bf50be6caf1aa03368060c200a
|
4
|
+
data.tar.gz: ce9fd7abad14ebbdbb62c6249e6c1a5e034edcee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0e47b15e14ad3e615868ceb7e8b8ac90ca3696b42ff29e21a8ff7ab52ec455961f2182ad4cbef320e5653fea86979d0f36bd0a6ad221b3df28457958cf6cf13
|
7
|
+
data.tar.gz: 788a8ebb7646b4c4b00d62dc8502f7a01353c5f5b24a772685177c5e84144fce21069b6921ea70a8383ad4934a06e7b36495eebc35a8a81acab2f5abf33b2ae0
|
data/Gemfile
CHANGED
data/evrone-ci-router.gemspec
CHANGED
@@ -18,8 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_runtime_dependency 'evrone-ci-common',
|
22
|
-
spec.add_runtime_dependency 'evrone-ci-message',
|
21
|
+
spec.add_runtime_dependency 'evrone-ci-common', "= #{Evrone::CI::Router::VERSION}"
|
22
|
+
spec.add_runtime_dependency 'evrone-ci-message', "= #{Evrone::CI::Router::VERSION}"
|
23
|
+
spec.add_runtime_dependency 'evrone-ci-build_configuration', "= #{Evrone::CI::Router::VERSION}"
|
24
|
+
|
23
25
|
spec.add_runtime_dependency 'evrone-common-amqp', '~> 0.2.5'
|
24
26
|
spec.add_runtime_dependency 'hashr', '= 0.0.22'
|
25
27
|
|
data/lib/evrone/ci/router.rb
CHANGED
@@ -4,6 +4,7 @@ require 'fileutils'
|
|
4
4
|
require 'thread'
|
5
5
|
|
6
6
|
require 'evrone/ci/common/error_notifier'
|
7
|
+
require 'evrone/ci/build_configuration'
|
7
8
|
|
8
9
|
require File.expand_path("../..", __FILE__) + "/ci/router/ext/string.rb"
|
9
10
|
require File.expand_path("../..", __FILE__) + "/ci/router/ext/array.rb"
|
@@ -14,9 +15,7 @@ module Evrone
|
|
14
15
|
|
15
16
|
autoload :Configuration, File.expand_path("../router/configuration", __FILE__)
|
16
17
|
autoload :Build, File.expand_path("../router/build", __FILE__)
|
17
|
-
autoload :BuildMatrix, File.expand_path("../router/build_matrix", __FILE__)
|
18
18
|
autoload :ScriptBuilder, File.expand_path("../router/script_builder", __FILE__)
|
19
|
-
autoload :Travis, File.expand_path("../router/travis", __FILE__)
|
20
19
|
autoload :CLI, File.expand_path("../router/cli", __FILE__)
|
21
20
|
|
22
21
|
autoload :BuildLogsConsumer, File.expand_path("../router/consumers/build_logs_consumer", __FILE__)
|
@@ -70,17 +69,17 @@ module Evrone
|
|
70
69
|
include Helper::Logger
|
71
70
|
include Helper::Config
|
72
71
|
|
73
|
-
attr_reader :build, :
|
72
|
+
attr_reader :build, :configuration
|
74
73
|
|
75
74
|
def initialize(build)
|
76
|
-
@build
|
77
|
-
@
|
75
|
+
@build = build
|
76
|
+
@configuration = nil
|
78
77
|
end
|
79
78
|
|
80
79
|
def perform
|
81
80
|
log_build do
|
82
81
|
update_build_status do
|
83
|
-
|
82
|
+
load_configuration &&
|
84
83
|
create_and_delivery_build_matrix
|
85
84
|
end
|
86
85
|
end
|
@@ -88,24 +87,24 @@ module Evrone
|
|
88
87
|
end
|
89
88
|
|
90
89
|
def create_and_delivery_build_matrix
|
91
|
-
matrix =
|
92
|
-
build.jobs_count = matrix.
|
90
|
+
matrix = BuildConfiguration::Matrix.new configuration
|
91
|
+
build.jobs_count = matrix.configurations.size
|
93
92
|
|
94
|
-
matrix.
|
93
|
+
matrix.configurations.each_with_index do |c, idx|
|
95
94
|
number = idx + 1
|
96
|
-
message = build.to_perform_job_message
|
97
|
-
logger.info "delivery job #{message.id}.#{number} #{
|
95
|
+
message = build.to_perform_job_message c, number
|
96
|
+
logger.info "delivery job #{message.id}.#{number} #{c.to_matrix_s}"
|
98
97
|
JobsConsumer.publish message
|
99
98
|
|
100
|
-
publish_job_status_message build,
|
99
|
+
publish_job_status_message build, c, number
|
101
100
|
end
|
102
101
|
|
103
102
|
true
|
104
103
|
end
|
105
104
|
|
106
|
-
def
|
107
|
-
@
|
108
|
-
@
|
105
|
+
def load_configuration
|
106
|
+
@configuration = BuildConfiguration.from_yaml build.message.travis
|
107
|
+
@configuration
|
109
108
|
end
|
110
109
|
|
111
110
|
def log_build
|
@@ -27,8 +27,8 @@ module Evrone
|
|
27
27
|
output.close
|
28
28
|
end
|
29
29
|
|
30
|
-
def to_perform_job_message(
|
31
|
-
script_builder =
|
30
|
+
def to_perform_job_message(configuration, job_id)
|
31
|
+
script_builder = ScriptBuilder.new self, configuration
|
32
32
|
job_message = Message::PerformJob.new(
|
33
33
|
id: message.id,
|
34
34
|
name: message.name,
|
@@ -36,7 +36,7 @@ module Evrone
|
|
36
36
|
before_script: script_builder.to_before_script,
|
37
37
|
script: script_builder.to_script,
|
38
38
|
after_script: script_builder.to_after_script,
|
39
|
-
matrix_keys:
|
39
|
+
matrix_keys: configuration.matrix_keys,
|
40
40
|
)
|
41
41
|
job_message
|
42
42
|
end
|
@@ -24,11 +24,11 @@ module Evrone
|
|
24
24
|
use ScriptBuilder::Script
|
25
25
|
end
|
26
26
|
|
27
|
-
attr_reader :
|
27
|
+
attr_reader :configuration, :build
|
28
28
|
|
29
|
-
def initialize(build,
|
30
|
-
@
|
31
|
-
@build
|
29
|
+
def initialize(build, configuration)
|
30
|
+
@configuration = configuration
|
31
|
+
@build = build
|
32
32
|
end
|
33
33
|
|
34
34
|
def to_before_script
|
@@ -88,7 +88,7 @@ module Evrone
|
|
88
88
|
script: [],
|
89
89
|
after_script: [],
|
90
90
|
|
91
|
-
|
91
|
+
configuration: configuration,
|
92
92
|
build: build,
|
93
93
|
)
|
94
94
|
end
|
@@ -8,10 +8,10 @@ module Evrone
|
|
8
8
|
include Helper::TraceShCommand
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
env.
|
11
|
+
env.configuration.before_script.each do |c|
|
12
12
|
env.before_script << trace_sh_command(c)
|
13
13
|
end
|
14
|
-
env.
|
14
|
+
env.configuration.script.each do |c|
|
15
15
|
env.script << trace_sh_command(c)
|
16
16
|
end
|
17
17
|
app.call(env)
|
@@ -8,7 +8,7 @@ module Evrone
|
|
8
8
|
include Helper::Config
|
9
9
|
include Helper::Logger
|
10
10
|
|
11
|
-
CASHER_URL = "https://raw.github.com/travis-ci/casher/
|
11
|
+
CASHER_URL = "https://raw.github.com/travis-ci/casher/production/bin/casher"
|
12
12
|
CASHER_BIN = "$HOME/.casher/bin/casher"
|
13
13
|
|
14
14
|
def call(env)
|
@@ -29,7 +29,7 @@ module Evrone
|
|
29
29
|
name << env.build.message.name.dup
|
30
30
|
|
31
31
|
# convert keys from ["rvm:2.0.0"] to "rvm 2.0.0"
|
32
|
-
name += env.
|
32
|
+
name += env.configuration.matrix_keys.map{|i| i.split(":").join(" ") }
|
33
33
|
# replace non word chars to ' '
|
34
34
|
name = name.join("-").gsub(/[^a-z0-9_\-.]/, ' ')
|
35
35
|
|
@@ -52,11 +52,11 @@ module Evrone
|
|
52
52
|
|
53
53
|
def fetch(env)
|
54
54
|
env.init << "echo fetch cached content"
|
55
|
-
env.init << "#{CASHER_BIN} fetch #{env.webdav_cache_url}
|
55
|
+
env.init << "#{CASHER_BIN} fetch #{env.webdav_cache_url} || true"
|
56
56
|
end
|
57
57
|
|
58
58
|
def add(env)
|
59
|
-
env.init << "#{CASHER_BIN} add $HOME/cached
|
59
|
+
env.init << "#{CASHER_BIN} add $HOME/cached || true"
|
60
60
|
env.init << "unset CASHER_DIR"
|
61
61
|
end
|
62
62
|
|
data/spec/lib/build_spec.rb
CHANGED
@@ -98,9 +98,9 @@ describe Evrone::CI::Router::Build do
|
|
98
98
|
end
|
99
99
|
|
100
100
|
context ".to_perform_job_message" do
|
101
|
-
let(:
|
101
|
+
let(:config) { create :configuration }
|
102
102
|
let(:job_id) { 2 }
|
103
|
-
subject { build.to_perform_job_message
|
103
|
+
subject { build.to_perform_job_message config, job_id }
|
104
104
|
|
105
105
|
it { should be_an_instance_of Evrone::CI::Message::PerformJob }
|
106
106
|
|
data/spec/lib/router_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Evrone::CI::Router do
|
|
8
8
|
subject { router }
|
9
9
|
|
10
10
|
context "just created" do
|
11
|
-
its(:build)
|
11
|
+
its(:build) { should eq build }
|
12
12
|
end
|
13
13
|
|
14
14
|
context "#perform" do
|
@@ -43,12 +43,12 @@ describe Evrone::CI::Router do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
context "#
|
47
|
-
subject { router.
|
46
|
+
context "#load_configuration" do
|
47
|
+
subject { router.load_configuration }
|
48
48
|
|
49
|
-
it "should build new
|
49
|
+
it "should build new BuildConfiguration instance from message" do
|
50
50
|
expect(subject).to be_true
|
51
|
-
expect(router.
|
51
|
+
expect(router.configuration).to be
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -57,10 +57,10 @@ describe Evrone::CI::Router do
|
|
57
57
|
let(:message) { messages.first }
|
58
58
|
subject { router.create_and_delivery_build_matrix }
|
59
59
|
before do
|
60
|
-
stub(router).
|
60
|
+
stub(router).configuration { create :configuration }
|
61
61
|
end
|
62
62
|
|
63
|
-
it "should create build matrix from source
|
63
|
+
it "should create build matrix from source configuration and delivery its to jobs" do
|
64
64
|
expect(subject).to be_true
|
65
65
|
expect(messages).to have(1).item
|
66
66
|
expect(message.job_id).to eq 1
|
@@ -6,8 +6,8 @@ describe Evrone::CI::Router::ScriptBuilder::WebdavCache do
|
|
6
6
|
let(:path) { '/tmp/.test' }
|
7
7
|
let(:app) { ->(_) { _ } }
|
8
8
|
let(:build) { create :build }
|
9
|
-
let(:
|
10
|
-
let(:env) { OpenStruct.new build: build, init: [],
|
9
|
+
let(:config) { create :configuration }
|
10
|
+
let(:env) { OpenStruct.new build: build, init: [], configuration: config, after_script: [] }
|
11
11
|
let(:mid) { described_class.new app }
|
12
12
|
|
13
13
|
subject { mid.call env }
|
@@ -2,13 +2,13 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Evrone::CI::Router::ScriptBuilder do
|
4
4
|
let(:build) { create :build }
|
5
|
-
let(:
|
6
|
-
let(:script_builder) { described_class.new build,
|
5
|
+
let(:config) { create :configuration }
|
6
|
+
let(:script_builder) { described_class.new build, config }
|
7
7
|
subject { script_builder }
|
8
8
|
|
9
9
|
context "just created" do
|
10
|
-
its(:
|
11
|
-
its(:build)
|
10
|
+
its(:configuration) { should eq config }
|
11
|
+
its(:build) { should eq build }
|
12
12
|
end
|
13
13
|
|
14
14
|
context "to_before_script" do
|
data/spec/support/create.rb
CHANGED
@@ -9,13 +9,13 @@ def create(who, *args)
|
|
9
9
|
when :local_repo
|
10
10
|
Evrone::CI::Router.root.join("fixtures/repo").to_s
|
11
11
|
|
12
|
-
when :
|
13
|
-
klass = Evrone::CI::
|
14
|
-
|
12
|
+
when :configuration
|
13
|
+
klass = Evrone::CI::BuildConfiguration
|
14
|
+
configuration = nil
|
15
15
|
if options[:yaml]
|
16
|
-
|
16
|
+
configuration = klass.from_yaml options[:yaml]
|
17
17
|
elsif options[:attributes]
|
18
|
-
|
18
|
+
configuration = klass.from_attributes options[:attributes]
|
19
19
|
else
|
20
20
|
klass.from_yaml fixture("travis.yml")
|
21
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evrone-ci-router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.pre23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Galinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: evrone-ci-common
|
@@ -16,28 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.2.0.
|
19
|
+
version: 0.2.0.pre23
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.2.0.
|
26
|
+
version: 0.2.0.pre23
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: evrone-ci-message
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.2.0.
|
33
|
+
version: 0.2.0.pre23
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.2.0.
|
40
|
+
version: 0.2.0.pre23
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: evrone-ci-build_configuration
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.0.pre23
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0.pre23
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: evrone-common-amqp
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,7 +155,6 @@ files:
|
|
141
155
|
- fixtures/travis.yml
|
142
156
|
- lib/evrone/ci/router.rb
|
143
157
|
- lib/evrone/ci/router/build.rb
|
144
|
-
- lib/evrone/ci/router/build_matrix.rb
|
145
158
|
- lib/evrone/ci/router/cli.rb
|
146
159
|
- lib/evrone/ci/router/configuration.rb
|
147
160
|
- lib/evrone/ci/router/consumers/build_logs_consumer.rb
|
@@ -162,17 +175,13 @@ files:
|
|
162
175
|
- lib/evrone/ci/router/script_builder/ruby.rb
|
163
176
|
- lib/evrone/ci/router/script_builder/script.rb
|
164
177
|
- lib/evrone/ci/router/script_builder/webdav_cache.rb
|
165
|
-
- lib/evrone/ci/router/travis.rb
|
166
|
-
- lib/evrone/ci/router/travis/serializable.rb
|
167
178
|
- lib/evrone/ci/router/version.rb
|
168
|
-
- spec/lib/build_matrix_spec.rb
|
169
179
|
- spec/lib/build_spec.rb
|
170
180
|
- spec/lib/configuration_spec.rb
|
171
181
|
- spec/lib/router_spec.rb
|
172
182
|
- spec/lib/script_builder/prepare_spec.rb
|
173
183
|
- spec/lib/script_builder/webdav_cache_spec.rb
|
174
184
|
- spec/lib/script_builder_spec.rb
|
175
|
-
- spec/lib/travis_spec.rb
|
176
185
|
- spec/spec_helper.rb
|
177
186
|
- spec/support/create.rb
|
178
187
|
- spec/support/fixture.rb
|
@@ -203,14 +212,12 @@ signing_key:
|
|
203
212
|
specification_version: 4
|
204
213
|
summary: ci router
|
205
214
|
test_files:
|
206
|
-
- spec/lib/build_matrix_spec.rb
|
207
215
|
- spec/lib/build_spec.rb
|
208
216
|
- spec/lib/configuration_spec.rb
|
209
217
|
- spec/lib/router_spec.rb
|
210
218
|
- spec/lib/script_builder/prepare_spec.rb
|
211
219
|
- spec/lib/script_builder/webdav_cache_spec.rb
|
212
220
|
- spec/lib/script_builder_spec.rb
|
213
|
-
- spec/lib/travis_spec.rb
|
214
221
|
- spec/spec_helper.rb
|
215
222
|
- spec/support/create.rb
|
216
223
|
- spec/support/fixture.rb
|
@@ -1,113 +0,0 @@
|
|
1
|
-
module Evrone
|
2
|
-
module CI
|
3
|
-
class Router
|
4
|
-
class BuildMatrix
|
5
|
-
|
6
|
-
KEYS = (Travis::LANGS + %w{ matrix_env:env }).freeze
|
7
|
-
NOT_MATRIX_KEYS = %w{ script before_script }
|
8
|
-
|
9
|
-
attr_reader :travis
|
10
|
-
|
11
|
-
def initialize(travis)
|
12
|
-
@travis = travis
|
13
|
-
end
|
14
|
-
|
15
|
-
def keys
|
16
|
-
extract_pair_of_key_and_values.map(&:first).sort
|
17
|
-
end
|
18
|
-
|
19
|
-
def travises
|
20
|
-
attributes_for_new_travises_with_merged_env.map do |attrs|
|
21
|
-
attrs = attrs.merge(
|
22
|
-
NOT_MATRIX_KEYS.inject({}) do |a,v|
|
23
|
-
a[v] = travis.public_send(v)
|
24
|
-
a
|
25
|
-
end
|
26
|
-
)
|
27
|
-
Travis.new attrs
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def attributes_for_new_travises_with_merged_env
|
32
|
-
attrs = attributes_for_new_travises
|
33
|
-
attrs = [{}] if attrs.empty?
|
34
|
-
attrs.map do |a|
|
35
|
-
e = a["env"]
|
36
|
-
a["env"] = {
|
37
|
-
"global" => Array(e) + travis.global_env,
|
38
|
-
"matrix" => e
|
39
|
-
}
|
40
|
-
a
|
41
|
-
end
|
42
|
-
attrs
|
43
|
-
end
|
44
|
-
|
45
|
-
def attributes_for_new_travises
|
46
|
-
permutate_and_build_values.inject([]) do |ac, values|
|
47
|
-
ac << values.inject({}) do |a,val|
|
48
|
-
a[val.key] = val.value
|
49
|
-
a
|
50
|
-
end
|
51
|
-
ac
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def permutate_and_build_values
|
56
|
-
values = extract_pair_of_key_and_values.map do |key, vals|
|
57
|
-
vals.map{|it| Value.new(key, it) }
|
58
|
-
end
|
59
|
-
if matrix_values?(values)
|
60
|
-
array_permutations(values).map do |it|
|
61
|
-
if it.is_a?(Array)
|
62
|
-
it.flatten
|
63
|
-
else
|
64
|
-
[it]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
else
|
68
|
-
values
|
69
|
-
end.sort_by(&:to_s)
|
70
|
-
end
|
71
|
-
|
72
|
-
def extract_pair_of_key_and_values
|
73
|
-
KEYS.map.inject([]) do |a, k|
|
74
|
-
k_method, k_name = k.split(":")
|
75
|
-
k_name ||= k_method
|
76
|
-
|
77
|
-
if (val = travis[k_method]) && !val.empty?
|
78
|
-
a << [k_name, val]
|
79
|
-
end
|
80
|
-
a
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def matrix_values?(values)
|
87
|
-
!values.all?{|i| i.size == 1 }
|
88
|
-
end
|
89
|
-
|
90
|
-
def array_permutations array, index=0
|
91
|
-
# index is 0 by default : start at the beginning, more elegant.
|
92
|
-
return array[-1] if index == array.size - 1 # Return last element if at end.
|
93
|
-
|
94
|
-
result = []
|
95
|
-
|
96
|
-
array[index].each do |element| # For each array
|
97
|
-
array_permutations(array, index + 1).each do |x| # Permute permute permute
|
98
|
-
result << [element, x]
|
99
|
-
end
|
100
|
-
end
|
101
|
-
result
|
102
|
-
end
|
103
|
-
|
104
|
-
Value = Struct.new(:key, :value) do
|
105
|
-
def to_s
|
106
|
-
[key, value].join(":")
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
require File.expand_path("../travis/serializable", __FILE__)
|
2
|
-
|
3
|
-
module Evrone
|
4
|
-
module CI
|
5
|
-
class Router
|
6
|
-
class Travis
|
7
|
-
|
8
|
-
include Travis::Serializable
|
9
|
-
|
10
|
-
LANGS = %w{ rvm scala java go }.freeze
|
11
|
-
KEYS = %w{ before_script script }.freeze
|
12
|
-
AS_ARRAY = (KEYS + LANGS).freeze
|
13
|
-
|
14
|
-
attr_reader :attributes
|
15
|
-
alias_method :to_hash, :attributes
|
16
|
-
|
17
|
-
def initialize(attrs = {})
|
18
|
-
@attributes = normalize_attributes attrs
|
19
|
-
end
|
20
|
-
|
21
|
-
def [](val)
|
22
|
-
public_send(val)
|
23
|
-
end
|
24
|
-
|
25
|
-
def matrix_keys
|
26
|
-
@matrix_keys ||=
|
27
|
-
BuildMatrix::KEYS.inject([]) do |a,k|
|
28
|
-
k_method, k_name = k.split(":")
|
29
|
-
k_name ||= k_method
|
30
|
-
val = send(k_method)
|
31
|
-
unless val.empty?
|
32
|
-
a << val.map{|v| "#{k_name}:#{v}" }
|
33
|
-
end
|
34
|
-
a
|
35
|
-
end.flatten.sort
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_matrix_s
|
39
|
-
@to_matrix_s ||= matrix_keys.join(", ")
|
40
|
-
end
|
41
|
-
|
42
|
-
def to_script_builder(build)
|
43
|
-
ScriptBuilder.new(build, self)
|
44
|
-
end
|
45
|
-
|
46
|
-
def env
|
47
|
-
attributes["env"]
|
48
|
-
end
|
49
|
-
|
50
|
-
def matrix_env
|
51
|
-
attributes["env"]["matrix"]
|
52
|
-
end
|
53
|
-
|
54
|
-
def global_env
|
55
|
-
attributes["env"]["global"]
|
56
|
-
end
|
57
|
-
|
58
|
-
AS_ARRAY.each do |m|
|
59
|
-
define_method m do
|
60
|
-
@attributes[m] || []
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def merge(attrs = {})
|
65
|
-
self.class.from_attributes self.attributes.merge(attrs)
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def normalize_attributes(attributes)
|
71
|
-
attributes = attributes.inject({}) do |a,row|
|
72
|
-
k,v = row
|
73
|
-
if AS_ARRAY.include?(k.to_s)
|
74
|
-
v = Array(v)
|
75
|
-
end
|
76
|
-
a[k.to_s] = v
|
77
|
-
a
|
78
|
-
end
|
79
|
-
normalize_env_attribute attributes
|
80
|
-
end
|
81
|
-
|
82
|
-
def normalize_env_attribute(attributes)
|
83
|
-
env = (attributes['env'] || {}) .dup
|
84
|
-
case env
|
85
|
-
when Hash
|
86
|
-
attributes["env"] = {
|
87
|
-
"matrix" => Array(env['matrix']),
|
88
|
-
"global" => Array(env['global'])
|
89
|
-
}
|
90
|
-
else
|
91
|
-
attributes['env'] = {
|
92
|
-
"matrix" => Array(env).map(&:to_s),
|
93
|
-
"global" => []
|
94
|
-
}
|
95
|
-
end
|
96
|
-
freeze_normalized_attributes attributes
|
97
|
-
end
|
98
|
-
|
99
|
-
def freeze_normalized_attributes(attributes)
|
100
|
-
attributes.freeze
|
101
|
-
attributes['env'].freeze
|
102
|
-
attributes['env']['global'].freeze
|
103
|
-
attributes['env']['matrix'].freeze
|
104
|
-
attributes
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module Evrone
|
5
|
-
module CI
|
6
|
-
class Router
|
7
|
-
class Travis
|
8
|
-
|
9
|
-
module Serializable
|
10
|
-
|
11
|
-
def self.included(base)
|
12
|
-
base.extend ClassMethods
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_yaml
|
16
|
-
YAML.dump(attributes)
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_hash
|
20
|
-
attributes
|
21
|
-
end
|
22
|
-
|
23
|
-
module ClassMethods
|
24
|
-
|
25
|
-
def from_file(file)
|
26
|
-
if File.readable? file
|
27
|
-
from_yaml File.read(file)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def from_yaml(yaml)
|
32
|
-
from_attributes YAML.load(yaml)
|
33
|
-
end
|
34
|
-
|
35
|
-
def from_attributes(attrs)
|
36
|
-
Travis.new attrs
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,189 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
describe Evrone::CI::Router::BuildMatrix do
|
5
|
-
let(:attributes) { {
|
6
|
-
env: %w{ FOO=1 BAR=2 },
|
7
|
-
rvm: %w{ 1.8.7 1.9.3 2.0.0 },
|
8
|
-
scala: %w{ 2.9.2 2.10.1 },
|
9
|
-
before_script: "echo before_script",
|
10
|
-
script: "echo script"
|
11
|
-
} }
|
12
|
-
let(:travis) { create :travis, attributes: attributes }
|
13
|
-
let(:matrix) { described_class.new travis }
|
14
|
-
|
15
|
-
subject { matrix }
|
16
|
-
|
17
|
-
context "just created" do
|
18
|
-
its(:travis) { should eq travis }
|
19
|
-
end
|
20
|
-
|
21
|
-
context "keys" do
|
22
|
-
subject { matrix.keys }
|
23
|
-
it { should eq %w{ env rvm scala } }
|
24
|
-
context "without matrix" do
|
25
|
-
let(:attributes) { {} }
|
26
|
-
|
27
|
-
it { should eq [] }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'travises' do
|
32
|
-
subject { matrix.travises }
|
33
|
-
|
34
|
-
it "should copy script from source" do
|
35
|
-
expect(subject.map(&:script).uniq).to eq [["echo script"]]
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should copy before_script from source" do
|
39
|
-
expect(subject.map(&:before_script).uniq).to eq [["echo before_script"]]
|
40
|
-
end
|
41
|
-
|
42
|
-
context "without any matrix keys" do
|
43
|
-
let(:attributes) { {
|
44
|
-
script: %w{ /bin/true },
|
45
|
-
} }
|
46
|
-
|
47
|
-
it { should have(1).item }
|
48
|
-
its("first.attributes") { should eq(
|
49
|
-
"env"=>{"matrix"=>[], "global"=>[]},
|
50
|
-
"script"=>["/bin/true"],
|
51
|
-
"before_script"=>[]
|
52
|
-
)}
|
53
|
-
end
|
54
|
-
|
55
|
-
context "values" do
|
56
|
-
|
57
|
-
it { should have(12).items }
|
58
|
-
|
59
|
-
context "attributes" do
|
60
|
-
subject { matrix.travises.map(&:to_matrix_s) }
|
61
|
-
|
62
|
-
it do
|
63
|
-
should eq [
|
64
|
-
"env:BAR=2, rvm:1.8.7, scala:2.10.1",
|
65
|
-
"env:FOO=1, rvm:1.8.7, scala:2.10.1",
|
66
|
-
"env:BAR=2, rvm:1.8.7, scala:2.9.2",
|
67
|
-
"env:FOO=1, rvm:1.8.7, scala:2.9.2",
|
68
|
-
"env:BAR=2, rvm:1.9.3, scala:2.10.1",
|
69
|
-
"env:FOO=1, rvm:1.9.3, scala:2.10.1",
|
70
|
-
"env:BAR=2, rvm:1.9.3, scala:2.9.2",
|
71
|
-
"env:FOO=1, rvm:1.9.3, scala:2.9.2",
|
72
|
-
"env:BAR=2, rvm:2.0.0, scala:2.10.1",
|
73
|
-
"env:FOO=1, rvm:2.0.0, scala:2.10.1",
|
74
|
-
"env:BAR=2, rvm:2.0.0, scala:2.9.2",
|
75
|
-
"env:FOO=1, rvm:2.0.0, scala:2.9.2"
|
76
|
-
]
|
77
|
-
end
|
78
|
-
|
79
|
-
context "without matrix" do
|
80
|
-
let(:attributes) { {
|
81
|
-
rvm: %w{ 2.0.0 },
|
82
|
-
} }
|
83
|
-
|
84
|
-
it { should eq ['rvm:2.0.0'] }
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context "attributes_for_new_travises_with_merged_env" do
|
92
|
-
subject { matrix.attributes_for_new_travises_with_merged_env }
|
93
|
-
|
94
|
-
before do
|
95
|
-
attributes.merge!(
|
96
|
-
env: {
|
97
|
-
"global" => "FOO=1",
|
98
|
-
"matrix" => %w{ BAR=1 BAR=2 }
|
99
|
-
}
|
100
|
-
)
|
101
|
-
end
|
102
|
-
|
103
|
-
it { should have(12).items }
|
104
|
-
|
105
|
-
it "should merge matrix env to global env" do
|
106
|
-
expect(subject.map{|i| i["env"]["global"] }.uniq.sort).to eq([["BAR=1", "FOO=1"], ["BAR=2", "FOO=1"]])
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'attributes_for_new_travises' do
|
111
|
-
subject { matrix.attributes_for_new_travises }
|
112
|
-
|
113
|
-
it { should have(12).items }
|
114
|
-
|
115
|
-
its(:first) { should eq("rvm" => "1.8.7",
|
116
|
-
"scala" => "2.10.1",
|
117
|
-
"env" => "BAR=2") }
|
118
|
-
its(:last) { should eq("rvm" => "2.0.0",
|
119
|
-
"scala" => "2.9.2",
|
120
|
-
"env" => "FOO=1") }
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'extract_pair_of_key_and_values' do
|
124
|
-
subject { matrix.extract_pair_of_key_and_values }
|
125
|
-
it {
|
126
|
-
should eq [
|
127
|
-
["rvm", %w{ 1.8.7 1.9.3 2.0.0 }],
|
128
|
-
["scala", %w{ 2.9.2 2.10.1 }],
|
129
|
-
["env", %w{ FOO=1 BAR=2 }]
|
130
|
-
]
|
131
|
-
}
|
132
|
-
end
|
133
|
-
|
134
|
-
context "permutate_and_build_values" do
|
135
|
-
subject { format_values matrix.permutate_and_build_values }
|
136
|
-
let(:expected) { [
|
137
|
-
%w{env:BAR=2 rvm:1.8.7 scala:2.10.1},
|
138
|
-
%w{env:BAR=2 rvm:1.8.7 scala:2.9.2},
|
139
|
-
%w{env:BAR=2 rvm:1.9.3 scala:2.10.1},
|
140
|
-
%w{env:BAR=2 rvm:1.9.3 scala:2.9.2},
|
141
|
-
%w{env:BAR=2 rvm:2.0.0 scala:2.10.1},
|
142
|
-
%w{env:BAR=2 rvm:2.0.0 scala:2.9.2},
|
143
|
-
%w{env:FOO=1 rvm:1.8.7 scala:2.10.1},
|
144
|
-
%w{env:FOO=1 rvm:1.8.7 scala:2.9.2},
|
145
|
-
%w{env:FOO=1 rvm:1.9.3 scala:2.10.1},
|
146
|
-
%w{env:FOO=1 rvm:1.9.3 scala:2.9.2},
|
147
|
-
%w{env:FOO=1 rvm:2.0.0 scala:2.10.1},
|
148
|
-
%w{env:FOO=1 rvm:2.0.0 scala:2.9.2},
|
149
|
-
] }
|
150
|
-
|
151
|
-
it { should eq expected }
|
152
|
-
|
153
|
-
context "with empty keys" do
|
154
|
-
let(:attributes) { {
|
155
|
-
env: %w{ FOO=1 BAR=2 },
|
156
|
-
rvm: %w{ 1.8.7 1.9.3 2.0.0 },
|
157
|
-
scala: %w{ 2.9.2 2.10.1 },
|
158
|
-
java: [],
|
159
|
-
go: nil
|
160
|
-
} }
|
161
|
-
it { should eq expected }
|
162
|
-
end
|
163
|
-
|
164
|
-
context "with one key" do
|
165
|
-
let(:attributes) { {
|
166
|
-
rvm: %w{ 1.9.3 2.0.0 },
|
167
|
-
} }
|
168
|
-
let(:expected) {[
|
169
|
-
%w{ rvm:1.9.3 },
|
170
|
-
%w{ rvm:2.0.0 }
|
171
|
-
]}
|
172
|
-
it { should eq expected }
|
173
|
-
end
|
174
|
-
|
175
|
-
context "without matrix" do
|
176
|
-
let(:attributes) { {
|
177
|
-
rvm: %w{ 2.0.0 },
|
178
|
-
} }
|
179
|
-
let(:expected) {[
|
180
|
-
%w{ rvm:2.0.0 }
|
181
|
-
]}
|
182
|
-
it { should eq expected }
|
183
|
-
end
|
184
|
-
|
185
|
-
def format_values(values)
|
186
|
-
values.map{|i| i.map(&:to_s).sort }.sort
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
data/spec/lib/travis_spec.rb
DELETED
@@ -1,183 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Evrone::CI::Router::Travis do
|
4
|
-
let(:content) { YAML.load fixture('travis.yml') }
|
5
|
-
let(:travis) { described_class.from_attributes content }
|
6
|
-
subject { travis }
|
7
|
-
|
8
|
-
its(:attributes) { should be }
|
9
|
-
its(:rvm) { should eq %w{ 2.0.0 } }
|
10
|
-
its(:before_script) { should eq ["echo before_script"] }
|
11
|
-
its(:script) { should eq ["RAILS_ENV=test ls -1 && echo DONE!"] }
|
12
|
-
|
13
|
-
context "merge" do
|
14
|
-
let(:new_attrs) { { rvm: "replaced" } }
|
15
|
-
subject{ travis.merge new_attrs }
|
16
|
-
|
17
|
-
it "should build a new travis instance" do
|
18
|
-
expect(subject).to be_an_instance_of(described_class)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should replace attributes" do
|
22
|
-
expect(subject.attributes["rvm"]).to eq %w{ replaced }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context "(serialization)" do
|
27
|
-
|
28
|
-
context "build new instance" do
|
29
|
-
let(:expected) { {
|
30
|
-
"rvm" => ["2.0.0"],
|
31
|
-
"before_script" => ["echo before_script"],
|
32
|
-
"script" => ["RAILS_ENV=test ls -1 && echo DONE!"],
|
33
|
-
"env" => {
|
34
|
-
"matrix" => [],
|
35
|
-
"global" => []
|
36
|
-
}
|
37
|
-
} }
|
38
|
-
|
39
|
-
context "from_yaml" do
|
40
|
-
subject { described_class.from_yaml(fixture('travis.yml')).attributes }
|
41
|
-
it { should eq expected }
|
42
|
-
end
|
43
|
-
|
44
|
-
context "form_file" do
|
45
|
-
subject { described_class.from_file('fixtures/travis.yml').attributes }
|
46
|
-
it { should eq expected }
|
47
|
-
end
|
48
|
-
|
49
|
-
context "from_attributes" do
|
50
|
-
let(:attrs) {{
|
51
|
-
rvm: "2.0.0",
|
52
|
-
before_script: "echo before_script",
|
53
|
-
script: "RAILS_ENV=test ls -1 && echo DONE!"
|
54
|
-
}}
|
55
|
-
subject { described_class.from_attributes(attrs).attributes }
|
56
|
-
it { should eq expected }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context ".to_yaml" do
|
61
|
-
subject { travis.to_yaml }
|
62
|
-
it { should eq travis.attributes.to_yaml }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
context "to_script_builder" do
|
67
|
-
let(:build) { create :build }
|
68
|
-
subject { travis.to_script_builder build }
|
69
|
-
it { should be }
|
70
|
-
end
|
71
|
-
|
72
|
-
context "to_matrix_s" do
|
73
|
-
subject { travis.to_matrix_s }
|
74
|
-
it { should eq 'rvm:2.0.0' }
|
75
|
-
|
76
|
-
context "when many items" do
|
77
|
-
before do
|
78
|
-
mock(travis).rvm { %w{ 1.9.3 2.0.0 } }
|
79
|
-
mock(travis).scala { %w{ 2.10.1 } }
|
80
|
-
end
|
81
|
-
it { should eq "rvm:1.9.3, rvm:2.0.0, scala:2.10.1" }
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context "matrix_keys" do
|
86
|
-
subject { travis.matrix_keys }
|
87
|
-
it { should eq %w{ rvm:2.0.0 } }
|
88
|
-
|
89
|
-
context "when many items" do
|
90
|
-
before do
|
91
|
-
mock(travis).rvm { %w{ 1.9.3 2.0.0 } }
|
92
|
-
mock(travis).scala { %w{ 2.10.1 } }
|
93
|
-
end
|
94
|
-
it { should eq %w{ rvm:1.9.3 rvm:2.0.0 scala:2.10.1 }}
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
it "empty attributes must be empty Array" do
|
100
|
-
expect(travis.scala).to eq([])
|
101
|
-
end
|
102
|
-
|
103
|
-
context "normalize_attributes" do
|
104
|
-
described_class::AS_ARRAY.each do |m|
|
105
|
-
context "convert #{m} attribute to Array" do
|
106
|
-
let(:content) { { m => m } }
|
107
|
-
subject { travis.__send__(m) }
|
108
|
-
it { should eq([m]) }
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context "convert hash keys to strings" do
|
113
|
-
let(:content) { { rvm: "rvm" } }
|
114
|
-
subject { travis.attributes }
|
115
|
-
it { should include("rvm" => %w{rvm}) }
|
116
|
-
end
|
117
|
-
|
118
|
-
context "build env hash" do
|
119
|
-
subject { travis.attributes["env"] }
|
120
|
-
|
121
|
-
context "from String" do
|
122
|
-
let(:content) { { env: "FOO" } }
|
123
|
-
it { should eq( "global" => [], "matrix" => %w{ FOO } ) }
|
124
|
-
end
|
125
|
-
|
126
|
-
context "from Array" do
|
127
|
-
let(:content) { { env: %w{ FOO BAR } } }
|
128
|
-
it { should eq( 'global' => [], 'matrix' => %w{ FOO BAR } ) }
|
129
|
-
end
|
130
|
-
|
131
|
-
context "from empty Hash" do
|
132
|
-
let(:content) { { env: {} } }
|
133
|
-
it { should eq( 'global' => [], 'matrix' => [] ) }
|
134
|
-
end
|
135
|
-
|
136
|
-
context "from Hash" do
|
137
|
-
let(:content) { { env: { "global" => "1", 'matrix' => '2' } } }
|
138
|
-
it { should eq( 'global' => %w{1}, 'matrix' => %w{2} ) }
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
context "env" do
|
144
|
-
let(:content) { { env: env } }
|
145
|
-
subject { travis.env }
|
146
|
-
|
147
|
-
context "when attributes[env] is Array" do
|
148
|
-
let(:env) { %w{ FOO=1 BAR=2 } }
|
149
|
-
it { should eq("matrix"=>["FOO=1", "BAR=2"], "global"=>[]) }
|
150
|
-
end
|
151
|
-
|
152
|
-
context "when attributes[env] is Hash" do
|
153
|
-
let(:env) { { "matrix" => %w{ BAZ=1 } } }
|
154
|
-
it { should eq("matrix"=>["BAZ=1"], "global"=>[]) }
|
155
|
-
end
|
156
|
-
|
157
|
-
context "when attributes[env] is empty" do
|
158
|
-
let(:env) { {} }
|
159
|
-
it { should eq("matrix"=>[], "global"=>[]) }
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context "global_env" do
|
164
|
-
let(:content) { { env: env } }
|
165
|
-
subject { travis.global_env }
|
166
|
-
|
167
|
-
context "when attributes[env] is Array" do
|
168
|
-
let(:env) { %w{ FOO=1 } }
|
169
|
-
it { should eq([]) }
|
170
|
-
end
|
171
|
-
|
172
|
-
context "when attributes[env] is Hash" do
|
173
|
-
let(:env) { { "global" => %w{ FOO=1 } } }
|
174
|
-
it { should eq %w{ FOO=1 } }
|
175
|
-
end
|
176
|
-
|
177
|
-
context "when attributes[env] is empty" do
|
178
|
-
let(:env) { {} }
|
179
|
-
it { should eq([]) }
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|