travis-config 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/lib/travis/config/docker.rb +35 -0
- data/lib/travis/config/env.rb +11 -0
- data/lib/travis/config/files.rb +31 -0
- data/lib/travis/config/helpers.rb +51 -0
- data/lib/travis/config/heroku.rb +26 -0
- data/lib/travis/config/version.rb +5 -0
- data/lib/travis/config.rb +40 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/travis/config_spec.rb +147 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8fb7abc33d4b387f6619d373e40015d812ea4308
|
4
|
+
data.tar.gz: 2a5e1f82e557946189dc1b5ab4b793ff7130d235
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f859a30538499361ccf47e8b930f3006fceece03cd3a59286a1401ecbb0c1fd59c0b242befcf3397bfcc4bcd2ddb9e34d2efd0522890b3479cd5fc4722c8f8c8
|
7
|
+
data.tar.gz: a4ed8459bff5ec0c35cd1535959c771a1c4d189e80f2eceadc5c2885c0161c951bb9cb112a896b19add6fddffdb101070482bf47f9e3e7c2f84891a9181e1cf4
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) Travis CI <contact@travis-ci.org>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'hashr'
|
2
|
+
require 'travis/config/helpers'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
class Config < Hashr
|
6
|
+
class Docker
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
PATTERN = %r(tcp://(?<host>[^:]+):?(?<port>.*))
|
10
|
+
|
11
|
+
def load
|
12
|
+
compact(redis: redis, database: database, amqp: amqp)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def database
|
18
|
+
parse(ENV['POSTGRESQL_PORT']) if ENV['POSTGRESQL_PORT']
|
19
|
+
end
|
20
|
+
|
21
|
+
def amqp
|
22
|
+
parse(ENV['RABBITMQ_PORT']) if ENV['RABBITMQ_PORT']
|
23
|
+
end
|
24
|
+
|
25
|
+
def redis
|
26
|
+
{ url: ENV['REDIS_PORT'] } if ENV['REDIS_PORT']
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse(url)
|
30
|
+
matches = PATTERN.match(url.to_s)
|
31
|
+
compact(Hash[matches.names.zip(matches.captures)]) if matches
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'hashr'
|
3
|
+
require 'travis/config/helpers'
|
4
|
+
|
5
|
+
module Travis
|
6
|
+
class Config < Hashr
|
7
|
+
class Files
|
8
|
+
include Helpers
|
9
|
+
|
10
|
+
def load
|
11
|
+
filenames.inject({}) do |config, filename|
|
12
|
+
deep_merge(config, load_file(filename)[env] || {})
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def env
|
19
|
+
ENV['ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_file(filename)
|
23
|
+
YAML.load_file(filename) || {} rescue {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def filenames
|
27
|
+
@filenames ||= Dir['config/{travis.yml,travis/*.yml}'].sort
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'hashr'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
class Config < Hashr
|
5
|
+
module Helpers
|
6
|
+
def deep_symbolize_keys(hash)
|
7
|
+
hash.inject({}) do |result, (key, value)|
|
8
|
+
key = key.to_sym if key.respond_to?(:to_sym)
|
9
|
+
result[key] = case value
|
10
|
+
when Array
|
11
|
+
value.map { |value| value.is_a?(Hash) ? value.deep_symbolize_keys : value }
|
12
|
+
when Hash
|
13
|
+
value.deep_symbolize_keys
|
14
|
+
else
|
15
|
+
value
|
16
|
+
end
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def deep_merge(hash, other)
|
22
|
+
merger = proc { |key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2 || v1 }
|
23
|
+
hash.merge(other, &merger)
|
24
|
+
end
|
25
|
+
|
26
|
+
def compact(obj)
|
27
|
+
case obj
|
28
|
+
when Array
|
29
|
+
obj.reject { |obj| blank?(obj) }
|
30
|
+
when Hash
|
31
|
+
obj.keys.each { |key| obj.delete(key) if blank?(obj[key]) }
|
32
|
+
obj
|
33
|
+
else
|
34
|
+
obj
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def blank?(obj)
|
39
|
+
obj.respond_to?(:empty?) ? !!obj.empty? : !obj
|
40
|
+
end
|
41
|
+
|
42
|
+
def camelize(string)
|
43
|
+
string = string.to_s
|
44
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
45
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
46
|
+
string.gsub!('/', '::')
|
47
|
+
string
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'hashr'
|
2
|
+
require 'travis/config/helpers'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
class Config < Hashr
|
6
|
+
class Heroku
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
def load
|
10
|
+
{ database: parse_database_url(database_url) || {} }
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def database_url
|
16
|
+
ENV.values_at('DATABASE_URL', 'SHARED_DATABASE_URL').first
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_database_url(url)
|
20
|
+
pattern = %r((?:.+?)://(?<username>.+):(?<password>.+)@(?<host>[^:]+):?(?<port>.*)/(?<database>.+))
|
21
|
+
matches = pattern.match(url.to_s)
|
22
|
+
compact(Hash[matches.names.zip(matches.captures)]) if matches
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'hashr'
|
2
|
+
require 'travis/config/docker'
|
3
|
+
require 'travis/config/env'
|
4
|
+
require 'travis/config/files'
|
5
|
+
require 'travis/config/heroku'
|
6
|
+
|
7
|
+
# patch Hashr to merge with existing definitions and defaults
|
8
|
+
class Hashr < Hash
|
9
|
+
class << self
|
10
|
+
def define(definition)
|
11
|
+
definition = self.definition.merge(definition.deep_symbolize_keys)
|
12
|
+
@definition = deep_accessorize(definition)
|
13
|
+
end
|
14
|
+
|
15
|
+
def default(defaults)
|
16
|
+
defaults = self.defaults.merge(defaults)
|
17
|
+
@defaults = deep_accessorize(defaults)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Travis
|
23
|
+
class Config < Hashr
|
24
|
+
class << self
|
25
|
+
include Helpers
|
26
|
+
|
27
|
+
def load(*loaders)
|
28
|
+
loaders = [:files, :env, :heroku, :docker] if loaders.empty?
|
29
|
+
|
30
|
+
data = loaders.inject({}) do |data, name|
|
31
|
+
const = const_get(camelize(name)).new
|
32
|
+
other = deep_symbolize_keys(const.load)
|
33
|
+
deep_merge(data, other)
|
34
|
+
end
|
35
|
+
|
36
|
+
new(data)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Travis::Test
|
4
|
+
class Config < Travis::Config
|
5
|
+
define amqp: { username: 'guest', password: 'guest', host: 'localhost', prefetch: 1 }
|
6
|
+
define database: { adapter: 'postgresql', database: 'test', encoding: 'unicode' }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Travis::Config do
|
11
|
+
let(:config) { Travis::Test::Config.load(:files, :env, :heroku, :docker) }
|
12
|
+
|
13
|
+
describe 'Hashr behaviour' do
|
14
|
+
after :each do
|
15
|
+
ENV.delete('travis_config')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'is a Hashr instance' do
|
19
|
+
expect(config).to be_kind_of(Hashr)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns Hashr instances on subkeys' do
|
23
|
+
ENV['travis_config'] = YAML.dump('redis' => { 'url' => 'redis://localhost:6379' })
|
24
|
+
expect(config.redis).to be_kind_of(Hashr)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns Hashr instances on subkeys that were set to Ruby Hashes' do
|
28
|
+
config.foo = { :bar => { :baz => 'baz' } }
|
29
|
+
expect(config.foo.bar).to be_kind_of(Hashr)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'using DATABASE_URL for database configuration if present' do
|
34
|
+
after :each do
|
35
|
+
ENV.delete('DATABASE_URL')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'works when given a url with a port' do
|
39
|
+
ENV['DATABASE_URL'] = 'postgres://username:password@hostname:port/database'
|
40
|
+
|
41
|
+
expect(config.database.to_hash).to eq(
|
42
|
+
:adapter => 'postgresql',
|
43
|
+
:host => 'hostname',
|
44
|
+
:port => 'port',
|
45
|
+
:database => 'database',
|
46
|
+
:username => 'username',
|
47
|
+
:password => 'password',
|
48
|
+
:encoding => 'unicode'
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'works when given a url without a port' do
|
53
|
+
ENV['DATABASE_URL'] = 'postgres://username:password@hostname/database'
|
54
|
+
|
55
|
+
expect(config.database.to_hash).to eq(
|
56
|
+
:adapter => 'postgresql',
|
57
|
+
:host => 'hostname',
|
58
|
+
:database => 'database',
|
59
|
+
:username => 'username',
|
60
|
+
:password => 'password',
|
61
|
+
:encoding => 'unicode'
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'the example config file' do
|
67
|
+
let(:data) { {} }
|
68
|
+
|
69
|
+
it 'can access all keys recursively' do
|
70
|
+
nested_access = lambda do |config, data|
|
71
|
+
data.keys.each do |key|
|
72
|
+
expect(-> { config.send(key) }).to_not raise_error
|
73
|
+
nested_access.call(config.send(key), data[key]) if data[key].is_a?(Hash)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
nested_access.call(config, data)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'reads custom config files' do
|
81
|
+
before :each do
|
82
|
+
Dir.stubs(:[]).returns ['config/travis.yml', 'config/travis/foo.yml', 'config/travis/bar.yml']
|
83
|
+
YAML.stubs(:load_file).with('config/travis.yml').returns('test' => { 'travis' => 'travis', 'shared' => 'travis' })
|
84
|
+
YAML.stubs(:load_file).with('config/travis/foo.yml').returns('test' => { 'foo' => 'foo' })
|
85
|
+
YAML.stubs(:load_file).with('config/travis/bar.yml').returns('test' => { 'bar' => 'bar', 'shared' => 'bar' })
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'still reads the default config file' do
|
89
|
+
expect(config.travis).to eq('travis')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'merges custom files' do
|
93
|
+
expect(config.foo).to eq('foo')
|
94
|
+
expect(config.bar).to eq('bar')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'overwrites previously set values with values loaded later' do
|
98
|
+
expect(config.shared).to eq('bar')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'loads docker-style env vars' do
|
103
|
+
after :each do
|
104
|
+
%w(POSTGRESQL_PORT RABBITMQ_PORT REDIS_PORT).each do |key|
|
105
|
+
ENV.delete(key)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'loads POSTGRESQL_PORT to config.database' do
|
110
|
+
before :each do
|
111
|
+
ENV['POSTGRESQL_PORT'] = 'tcp://172.17.0.11:5432'
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'loads host and port from the env var' do
|
115
|
+
expect(config.database.values_at(:host, :port)).to eq(['172.17.0.11', '5432'])
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'keeps adapter, database, encoding from the regular config' do
|
119
|
+
expect(config.database.values_at(:adapter, :database, :encoding)).to eq(['postgresql', 'test', 'unicode'])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'loads RABBITMQ_PORT to config.amqp' do
|
124
|
+
before :each do
|
125
|
+
ENV['RABBITMQ_PORT'] = 'tcp://172.17.0.11:5672'
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'loads host and port from the env var' do
|
129
|
+
expect(config.amqp.values_at(:host, :port)).to eq(['172.17.0.11', '5672'])
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'keeps username, password, prefetch from the regular config' do
|
133
|
+
expect(config.amqp.values_at(:username, :password, :prefetch)).to eq(['guest', 'guest', 1])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'loads REDIS_PORT' do
|
138
|
+
ENV['REDIS_PORT'] = 'tcp://172.17.0.7:6379'
|
139
|
+
expect(config.redis).to eq({ url: 'tcp://172.17.0.7:6379' })
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'deep symbolizes arrays, too' do
|
144
|
+
config = Travis::Config.new('queues' => [{ 'slug' => 'rails/rails', 'queue' => 'rails' }])
|
145
|
+
expect(config.queues.first.values_at(:slug, :queue)).to eq(['rails/rails', 'rails'])
|
146
|
+
end
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: travis-config
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Travis CI
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashr
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
description: Travis CI config.
|
42
|
+
email: contact@travis-ci.org
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- Gemfile
|
48
|
+
- LICENSE
|
49
|
+
- lib/travis/config.rb
|
50
|
+
- lib/travis/config/docker.rb
|
51
|
+
- lib/travis/config/env.rb
|
52
|
+
- lib/travis/config/files.rb
|
53
|
+
- lib/travis/config/helpers.rb
|
54
|
+
- lib/travis/config/heroku.rb
|
55
|
+
- lib/travis/config/version.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
- spec/travis/config_spec.rb
|
58
|
+
homepage: https://github.com/travis-ci/travis-core
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project: "[none]"
|
78
|
+
rubygems_version: 2.2.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Travis CI config
|
82
|
+
test_files: []
|
83
|
+
has_rdoc:
|