evrone-ci-build_configuration 0.2.0.pre23
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +16 -0
- data/evrone-ci-build_configuration.gemspec +25 -0
- data/lib/evrone/ci/build_configuration/constants.rb +11 -0
- data/lib/evrone/ci/build_configuration/matrix.rb +113 -0
- data/lib/evrone/ci/build_configuration/serializable.rb +43 -0
- data/lib/evrone/ci/build_configuration/version.rb +7 -0
- data/lib/evrone/ci/build_configuration.rb +108 -0
- data/spec/fixtures/travis.yml +5 -0
- data/spec/lib/build_configuration_spec.rb +177 -0
- data/spec/lib/matrix_spec.rb +189 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/fixture.rb +7 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4366f9647f0cdb1163620984d202addeca8d3ab6
|
4
|
+
data.tar.gz: 63e78b9753c28f48ab3228495722fd5871cb70cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce8c6d17b1f85fd11969495d00a5afea9bf27078432f54693004d48ae1838563c954f5c97c1692d5c6ba041479fef83b67530969ef66f50c25d882bd04f139ff
|
7
|
+
data.tar.gz: 7a9cecdad1d78335337e2f1903879873efa728a97f6bcc545a251b6b6833294ed60213fa10910fd237a3b85d138628c8dae33d718caacb2b6f2345753cb9d8ce
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dmitry Galinsky
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Evrone::Ci::BuildConfiguration
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'evrone-ci-build_configuration'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install evrone-ci-build_configuration
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.require
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require "bundler/gem_tasks"
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
desc "run spec"
|
10
|
+
task :default => [:spec]
|
11
|
+
|
12
|
+
desc "run travis build"
|
13
|
+
task :travis do
|
14
|
+
exec "bundle exec rake SPEC_OPTS='--format documentation'"
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require File.expand_path('../lib/evrone/ci/build_configuration/version.rb', __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "evrone-ci-build_configuration"
|
8
|
+
spec.version = Evrone::CI::BuildConfiguration::VERSION
|
9
|
+
spec.authors = ["Dmitry Galinsky"]
|
10
|
+
spec.email = ["dima.exe@gmail.com"]
|
11
|
+
spec.description = %q{ description }
|
12
|
+
spec.summary = %q{ summary }
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "rr"
|
25
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Evrone
|
2
|
+
module CI
|
3
|
+
class BuildConfiguration
|
4
|
+
class Matrix
|
5
|
+
|
6
|
+
KEYS = (BuildConfiguration::LANGS + %w{ matrix_env:env }).freeze
|
7
|
+
NOT_MATRIX_KEYS = %w{ script before_script }
|
8
|
+
|
9
|
+
attr_reader :source
|
10
|
+
|
11
|
+
def initialize(build_configuration)
|
12
|
+
@source = build_configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def keys
|
16
|
+
extract_pair_of_key_and_values.map(&:first).sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def configurations
|
20
|
+
attributes_for_new_configurations_with_merged_env.map do |attrs|
|
21
|
+
attrs = attrs.merge(
|
22
|
+
NOT_MATRIX_KEYS.inject({}) do |a,v|
|
23
|
+
a[v] = source.public_send(v)
|
24
|
+
a
|
25
|
+
end
|
26
|
+
)
|
27
|
+
BuildConfiguration.new attrs
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def attributes_for_new_configurations_with_merged_env
|
32
|
+
attrs = attributes_for_new_configurations
|
33
|
+
attrs = [{}] if attrs.empty?
|
34
|
+
attrs.map do |a|
|
35
|
+
e = a["env"]
|
36
|
+
a["env"] = {
|
37
|
+
"global" => Array(e) + source.global_env,
|
38
|
+
"matrix" => e
|
39
|
+
}
|
40
|
+
a
|
41
|
+
end
|
42
|
+
attrs
|
43
|
+
end
|
44
|
+
|
45
|
+
def attributes_for_new_configurations
|
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 = source[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
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Evrone
|
5
|
+
module CI
|
6
|
+
class BuildConfiguration
|
7
|
+
|
8
|
+
module Serializable
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_yaml
|
15
|
+
YAML.dump(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_hash
|
19
|
+
attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
def from_file(file)
|
25
|
+
if File.readable? file
|
26
|
+
from_yaml File.read(file)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def from_yaml(yaml)
|
31
|
+
from_attributes YAML.load(yaml)
|
32
|
+
end
|
33
|
+
|
34
|
+
def from_attributes(attrs)
|
35
|
+
BuildConfiguration.new attrs
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require File.expand_path("../build_configuration/version", __FILE__)
|
2
|
+
require File.expand_path("../build_configuration/constants", __FILE__)
|
3
|
+
require File.expand_path("../build_configuration/serializable", __FILE__)
|
4
|
+
require File.expand_path("../build_configuration/matrix", __FILE__)
|
5
|
+
|
6
|
+
module Evrone
|
7
|
+
module CI
|
8
|
+
class BuildConfiguration
|
9
|
+
|
10
|
+
include BuildConfiguration::Serializable
|
11
|
+
|
12
|
+
attr_reader :attributes
|
13
|
+
alias_method :to_hash, :attributes
|
14
|
+
|
15
|
+
def initialize(attrs = {})
|
16
|
+
@attributes = normalize_attributes attrs
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](val)
|
20
|
+
public_send(val)
|
21
|
+
end
|
22
|
+
|
23
|
+
def matrix_keys
|
24
|
+
@matrix_keys ||=
|
25
|
+
Matrix::KEYS.inject([]) do |a,k|
|
26
|
+
k_method, k_name = k.split(":")
|
27
|
+
k_name ||= k_method
|
28
|
+
val = send(k_method)
|
29
|
+
unless val.empty?
|
30
|
+
a << val.map{|v| "#{k_name}:#{v}" }
|
31
|
+
end
|
32
|
+
a
|
33
|
+
end.flatten.sort
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_matrix_s
|
37
|
+
@to_matrix_s ||= matrix_keys.join(", ")
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_script_builder(build)
|
41
|
+
ScriptBuilder.new(build, self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def env
|
45
|
+
attributes["env"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def matrix_env
|
49
|
+
attributes["env"]["matrix"]
|
50
|
+
end
|
51
|
+
|
52
|
+
def global_env
|
53
|
+
attributes["env"]["global"]
|
54
|
+
end
|
55
|
+
|
56
|
+
AS_ARRAY.each do |m|
|
57
|
+
define_method m do
|
58
|
+
@attributes[m] || []
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def merge(attrs = {})
|
63
|
+
self.class.from_attributes self.attributes.merge(attrs)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def normalize_attributes(attributes)
|
69
|
+
attributes = attributes.inject({}) do |a,row|
|
70
|
+
k,v = row
|
71
|
+
if AS_ARRAY.include?(k.to_s)
|
72
|
+
v = Array(v)
|
73
|
+
end
|
74
|
+
a[k.to_s] = v
|
75
|
+
a
|
76
|
+
end
|
77
|
+
normalize_env_attribute attributes
|
78
|
+
end
|
79
|
+
|
80
|
+
def normalize_env_attribute(attributes)
|
81
|
+
env = (attributes['env'] || {}) .dup
|
82
|
+
case env
|
83
|
+
when Hash
|
84
|
+
attributes["env"] = {
|
85
|
+
"matrix" => Array(env['matrix']),
|
86
|
+
"global" => Array(env['global'])
|
87
|
+
}
|
88
|
+
else
|
89
|
+
attributes['env'] = {
|
90
|
+
"matrix" => Array(env).map(&:to_s),
|
91
|
+
"global" => []
|
92
|
+
}
|
93
|
+
end
|
94
|
+
freeze_normalized_attributes attributes
|
95
|
+
end
|
96
|
+
|
97
|
+
def freeze_normalized_attributes(attributes)
|
98
|
+
attributes.freeze
|
99
|
+
attributes['env'].freeze
|
100
|
+
attributes['env']['global'].freeze
|
101
|
+
attributes['env']['matrix'].freeze
|
102
|
+
attributes
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Evrone::CI::BuildConfiguration do
|
4
|
+
let(:content) { YAML.load fixture('travis.yml') }
|
5
|
+
let(:config) { described_class.from_attributes content }
|
6
|
+
subject { config }
|
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{ config.merge new_attrs }
|
16
|
+
|
17
|
+
it "should build a new BuildConfiguration 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('spec/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 { config.to_yaml }
|
62
|
+
it { should eq config.attributes.to_yaml }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "to_matrix_s" do
|
67
|
+
subject { config.to_matrix_s }
|
68
|
+
it { should eq 'rvm:2.0.0' }
|
69
|
+
|
70
|
+
context "when many items" do
|
71
|
+
before do
|
72
|
+
mock(config).rvm { %w{ 1.9.3 2.0.0 } }
|
73
|
+
mock(config).scala { %w{ 2.10.1 } }
|
74
|
+
end
|
75
|
+
it { should eq "rvm:1.9.3, rvm:2.0.0, scala:2.10.1" }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "matrix_keys" do
|
80
|
+
subject { config.matrix_keys }
|
81
|
+
it { should eq %w{ rvm:2.0.0 } }
|
82
|
+
|
83
|
+
context "when many items" do
|
84
|
+
before do
|
85
|
+
mock(config).rvm { %w{ 1.9.3 2.0.0 } }
|
86
|
+
mock(config).scala { %w{ 2.10.1 } }
|
87
|
+
end
|
88
|
+
it { should eq %w{ rvm:1.9.3 rvm:2.0.0 scala:2.10.1 }}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "empty attributes must be empty Array" do
|
94
|
+
expect(config.scala).to eq([])
|
95
|
+
end
|
96
|
+
|
97
|
+
context "normalize_attributes" do
|
98
|
+
described_class::AS_ARRAY.each do |m|
|
99
|
+
context "convert #{m} attribute to Array" do
|
100
|
+
let(:content) { { m => m } }
|
101
|
+
subject { config.__send__(m) }
|
102
|
+
it { should eq([m]) }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "convert hash keys to strings" do
|
107
|
+
let(:content) { { rvm: "rvm" } }
|
108
|
+
subject { config.attributes }
|
109
|
+
it { should include("rvm" => %w{rvm}) }
|
110
|
+
end
|
111
|
+
|
112
|
+
context "build env hash" do
|
113
|
+
subject { config.attributes["env"] }
|
114
|
+
|
115
|
+
context "from String" do
|
116
|
+
let(:content) { { env: "FOO" } }
|
117
|
+
it { should eq( "global" => [], "matrix" => %w{ FOO } ) }
|
118
|
+
end
|
119
|
+
|
120
|
+
context "from Array" do
|
121
|
+
let(:content) { { env: %w{ FOO BAR } } }
|
122
|
+
it { should eq( 'global' => [], 'matrix' => %w{ FOO BAR } ) }
|
123
|
+
end
|
124
|
+
|
125
|
+
context "from empty Hash" do
|
126
|
+
let(:content) { { env: {} } }
|
127
|
+
it { should eq( 'global' => [], 'matrix' => [] ) }
|
128
|
+
end
|
129
|
+
|
130
|
+
context "from Hash" do
|
131
|
+
let(:content) { { env: { "global" => "1", 'matrix' => '2' } } }
|
132
|
+
it { should eq( 'global' => %w{1}, 'matrix' => %w{2} ) }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "env" do
|
138
|
+
let(:content) { { env: env } }
|
139
|
+
subject { config.env }
|
140
|
+
|
141
|
+
context "when attributes[env] is Array" do
|
142
|
+
let(:env) { %w{ FOO=1 BAR=2 } }
|
143
|
+
it { should eq("matrix"=>["FOO=1", "BAR=2"], "global"=>[]) }
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when attributes[env] is Hash" do
|
147
|
+
let(:env) { { "matrix" => %w{ BAZ=1 } } }
|
148
|
+
it { should eq("matrix"=>["BAZ=1"], "global"=>[]) }
|
149
|
+
end
|
150
|
+
|
151
|
+
context "when attributes[env] is empty" do
|
152
|
+
let(:env) { {} }
|
153
|
+
it { should eq("matrix"=>[], "global"=>[]) }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context "global_env" do
|
158
|
+
let(:content) { { env: env } }
|
159
|
+
subject { config.global_env }
|
160
|
+
|
161
|
+
context "when attributes[env] is Array" do
|
162
|
+
let(:env) { %w{ FOO=1 } }
|
163
|
+
it { should eq([]) }
|
164
|
+
end
|
165
|
+
|
166
|
+
context "when attributes[env] is Hash" do
|
167
|
+
let(:env) { { "global" => %w{ FOO=1 } } }
|
168
|
+
it { should eq %w{ FOO=1 } }
|
169
|
+
end
|
170
|
+
|
171
|
+
context "when attributes[env] is empty" do
|
172
|
+
let(:env) { {} }
|
173
|
+
it { should eq([]) }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe Evrone::CI::BuildConfiguration::Matrix 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(:config) { Evrone::CI::BuildConfiguration.from_attributes attributes }
|
13
|
+
let(:matrix) { described_class.new config }
|
14
|
+
|
15
|
+
subject { matrix }
|
16
|
+
|
17
|
+
context "just created" do
|
18
|
+
its(:source) { should eq config }
|
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 'configurations' do
|
32
|
+
subject { matrix.configurations }
|
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.configurations.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_confgurations_with_merged_env" do
|
92
|
+
subject { matrix.attributes_for_new_configurations_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_configurations' do
|
111
|
+
subject { matrix.attributes_for_new_configurations }
|
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/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path '../../lib/evrone/ci/build_configuration', __FILE__
|
2
|
+
|
3
|
+
Bundler.require(:test)
|
4
|
+
require 'rspec/autorun'
|
5
|
+
|
6
|
+
Dir[File.expand_path("../..", __FILE__) + "/spec/support/**/*.rb"].each {|f| require f}
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.mock_with :rr
|
10
|
+
|
11
|
+
config.before(:each) do
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evrone-ci-build_configuration
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0.pre23
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dmitry Galinsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ' description '
|
70
|
+
email:
|
71
|
+
- dima.exe@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- evrone-ci-build_configuration.gemspec
|
83
|
+
- lib/evrone/ci/build_configuration.rb
|
84
|
+
- lib/evrone/ci/build_configuration/constants.rb
|
85
|
+
- lib/evrone/ci/build_configuration/matrix.rb
|
86
|
+
- lib/evrone/ci/build_configuration/serializable.rb
|
87
|
+
- lib/evrone/ci/build_configuration/version.rb
|
88
|
+
- spec/fixtures/travis.yml
|
89
|
+
- spec/lib/build_configuration_spec.rb
|
90
|
+
- spec/lib/matrix_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
- spec/support/fixture.rb
|
93
|
+
homepage: ''
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>'
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.3.1
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.1.11
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: summary
|
117
|
+
test_files:
|
118
|
+
- spec/fixtures/travis.yml
|
119
|
+
- spec/lib/build_configuration_spec.rb
|
120
|
+
- spec/lib/matrix_spec.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
- spec/support/fixture.rb
|