travis-config 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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,11 @@
1
+ require 'hashr'
2
+
3
+ module Travis
4
+ class Config < Hashr
5
+ class Env
6
+ def load
7
+ ENV['travis_config'] ? YAML.load(ENV['travis_config']) : {}
8
+ end
9
+ end
10
+ end
11
+ 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,5 @@
1
+ module Travis
2
+ class Config
3
+ VERSION = '0.0.1'
4
+ end
5
+ 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
@@ -0,0 +1,8 @@
1
+ ENV['ENV'] = 'test'
2
+
3
+ require 'mocha'
4
+ require 'travis/config'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :mocha
8
+ end
@@ -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: