travis-config 1.0.13 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0997a79b3e1da9db64c9cba5b94b5b2d51621e32
4
- data.tar.gz: 9369e30f3ff7a61fd27676c78fff5ea4dbf726f7
3
+ metadata.gz: aea576de8c27f7e41b5dfd80e34006f1f19295aa
4
+ data.tar.gz: 2ac9a83e70854a1afe14777f339b1942715b75d1
5
5
  SHA512:
6
- metadata.gz: 3530a85d18b1150fde81ab80cb0395c142a43794ac494632a82997eb67e92b017a18a328af3c33880519ed91983feaec7be1b1b577e484014eabff1e28c0178e
7
- data.tar.gz: bd0ba8452584938c3f7f79ce747bf3d1ae881f1cd98b6ace2d1d837c5b22b3c0e52a77cc82e940a6d62ff0e7524e93bc50880f5fd09f4d36e6f9a3ebd03440ad
6
+ metadata.gz: 5545ec1bd08707b7beb3a9417befe88594aa3b982b35ba0992888a0b63540980da98c01e097ef3f1d09c296bc74fbeae0a849fcaf833ff952513543f810cc860
7
+ data.tar.gz: f0429bb8d0efc0c9be9977c910d853b2c0a0e48014559fb1104894a1813f057721e61e4104ed00706c56cd5bc5ce9381e006dc75b62d91f0ce7f4bfc297e92ed
data/Gemfile CHANGED
@@ -7,4 +7,5 @@ gem 'hashr', '~> 2.0.0'
7
7
  group :test do
8
8
  gem 'rspec', '~> 3.0'
9
9
  gem 'mocha', '~> 1.1'
10
+ gem 'fakefs'
10
11
  end
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ travis-config (1.0.13)
5
+ hashr (~> 2.0.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.3)
11
+ fakefs (0.10.2)
12
+ hashr (2.0.0)
13
+ metaclass (0.0.4)
14
+ mocha (1.1.0)
15
+ metaclass (~> 0.0.1)
16
+ rspec (3.3.0)
17
+ rspec-core (~> 3.3.0)
18
+ rspec-expectations (~> 3.3.0)
19
+ rspec-mocks (~> 3.3.0)
20
+ rspec-core (3.3.2)
21
+ rspec-support (~> 3.3.0)
22
+ rspec-expectations (3.3.1)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.3.0)
25
+ rspec-mocks (3.3.2)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.3.0)
28
+ rspec-support (3.3.0)
29
+
30
+ PLATFORMS
31
+ java
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ fakefs
36
+ hashr (~> 2.0.0)
37
+ mocha (~> 1.1)
38
+ rspec (~> 3.0)
39
+ travis-config!
40
+
41
+ BUNDLED WITH
42
+ 1.14.5
@@ -4,8 +4,10 @@ module Travis
4
4
  class Config < Hashr
5
5
  require 'travis/config/docker'
6
6
  require 'travis/config/env'
7
+ require 'travis/config/keychain'
7
8
  require 'travis/config/files'
8
9
  require 'travis/config/heroku'
10
+ require 'travis/config/serialize/env'
9
11
 
10
12
  include Hashr::Delegate::Conditional
11
13
 
@@ -30,8 +32,8 @@ module Travis
30
32
  end
31
33
 
32
34
  def loaders(*names)
33
- names = [:files, :env, :heroku, :docker] if names.empty?
34
- names.map { |name| const_get(camelize(name)).new }
35
+ names = [:files, :keychain, :heroku, :docker, :env] if names.empty?
36
+ names.map { |name| const_get(camelize(name)).new(defaults) }
35
37
  end
36
38
  end
37
39
 
@@ -2,7 +2,7 @@ require 'travis/config/helpers'
2
2
 
3
3
  module Travis
4
4
  class Config
5
- class Docker
5
+ class Docker < Struct.new(:defaults)
6
6
  include Helpers
7
7
 
8
8
  PATTERN = %r(tcp://(?<host>[^:]+):?(?<port>.*))
@@ -1,8 +1,95 @@
1
1
  module Travis
2
2
  class Config
3
- class Env # TODO rename to keychain
3
+ class Env < Struct.new(:defaults)
4
+ class UnexpectedString < ArgumentError
5
+ MSG = 'Expected %s to be an array of hashes, but it is a string: %s'
6
+
7
+ def initialize(*args)
8
+ super(MSG % args)
9
+ end
10
+ end
11
+
12
+ class Vars < Struct.new(:defaults, :prefix)
13
+ TRUE = /^(true|yes|on)$/
14
+ FALSE = /^(false|no|off)$/
15
+
16
+ def to_h
17
+ defaults.deep_merge(hash(ENV, prefix.dup, defaults))
18
+ end
19
+
20
+ private
21
+
22
+ def hash(env, prefix, defaults)
23
+ defaults.inject({}) do |config, (key, default)|
24
+ config.merge key => obj(env, prefix + [key], default)
25
+ end
26
+ end
27
+
28
+ def obj(env, keys, default)
29
+ case default
30
+ when Hash
31
+ hash(env, keys, default)
32
+ when Array
33
+ vars = array(env, keys, default)
34
+ vars.any? ? vars : var(env, keys, default)
35
+ else
36
+ var(env, keys, default)
37
+ end
38
+ end
39
+
40
+ def array(env, keys, defaults)
41
+ vars(env, keys, defaults).map.with_index do |var, ix|
42
+ obj(var, [], defaults[ix] || defaults[0] || {})
43
+ end
44
+ end
45
+
46
+ def var(env, key, default)
47
+ key = key.map(&:upcase).join('_')
48
+ value = env.fetch(key, default)
49
+ raise UnexpectedString.new(key, value) if value.is_a?(String) && hashes?(default)
50
+ default.is_a?(Array) ? split(value) : cast(value)
51
+ end
52
+
53
+ def vars(env, keys, default)
54
+ pattern = /^#{keys.map(&:upcase).join('_')}_([\d]+)_/
55
+ vars = env.select { |key, _| key =~ pattern }
56
+ vars = vars.map { |key, value| [key.sub(pattern, ''), value, $1] }
57
+ vars.group_by(&:pop).values.map(&:to_h)
58
+ end
59
+
60
+ def cast(value)
61
+ case value
62
+ when /^[\d]+\.[\d]+$/
63
+ value.to_f
64
+ when /^[\d]+$/
65
+ value.to_i
66
+ when TRUE
67
+ true
68
+ when FALSE
69
+ false
70
+ when ''
71
+ nil
72
+ else
73
+ value
74
+ end
75
+ end
76
+
77
+ def split(value)
78
+ values = value.respond_to?(:split) ? value.split(',') : Array(value)
79
+ values.map { |value| cast(value) }
80
+ end
81
+
82
+ def hashes?(obj)
83
+ obj.is_a?(Array) && obj.first.is_a?(Hash)
84
+ end
85
+ end
86
+
87
+ def self.prefix(prefix = nil)
88
+ prefix ? @prefix = prefix : @prefix
89
+ end
90
+
4
91
  def load
5
- ENV['travis_config'] ? YAML.load(ENV['travis_config']) : {}
92
+ Vars.new(defaults, [self.class.prefix.to_s.upcase]).to_h
6
93
  end
7
94
  end
8
95
  end
@@ -3,18 +3,22 @@ require 'travis/config/helpers'
3
3
 
4
4
  module Travis
5
5
  class Config
6
- class Files
6
+ class Files < Struct.new(:defaults)
7
7
  include Helpers
8
8
 
9
+ MSGS = {
10
+ empty: <<-msg.split("\n").map(&:strip).join("\n")
11
+ Warning: config in %{filename} has no data for current env %{env}.
12
+ If you are expecting config to be loaded from this file, please make sure
13
+ your config is indented under a key of the environment (%{env}).
14
+ msg
15
+ }
16
+
9
17
  def load
10
- filenames.inject({}) do |config, filename|
11
- file_config = load_file(filename)
12
- if Config.env != "production" and file_config[Config.env].nil?
13
- puts "Warning: config in #{filename} has no data for current env #{Config.env}"
14
- puts "If you are expecting config to be loaded from this file, please make sure"
15
- puts "your config is indented under a key of the environment (#{Config.env})"
16
- end
17
- deep_merge(config, file_config[Config.env] || {})
18
+ filenames.inject({}) do |result, filename|
19
+ config = load_file(filename)
20
+ warn_empty(filename) if warn_empty? && config[env].nil?
21
+ deep_merge(result, config[env] || {})
18
22
  end
19
23
  end
20
24
 
@@ -27,8 +31,20 @@ module Travis
27
31
  {}
28
32
  end
29
33
 
34
+ def warn_empty(filename)
35
+ puts MSGS[:empty] % { filename: filename, env: env }
36
+ end
37
+
38
+ def warn_empty?
39
+ !%w(production test).include?(Config.env)
40
+ end
41
+
30
42
  def filenames
31
- @filenames ||= Dir['config/{travis.yml,travis/*.yml}'].sort
43
+ @filenames ||= Dir['config/travis.yml'] + Dir['config/travis/*.yml'].sort
44
+ end
45
+
46
+ def env
47
+ Config.env
32
48
  end
33
49
  end
34
50
  end
@@ -1,16 +1,17 @@
1
1
  require 'travis/config/helpers'
2
- require 'travis/config/heroku/database'
3
- require 'travis/config/heroku/memcached'
4
-
5
2
  module Travis
6
3
  class Config
7
- class Heroku # TODO rename to EnvVar
4
+ class Heroku < Struct.new(:defaults)
5
+ require 'travis/config/heroku/database'
6
+ require 'travis/config/heroku/memcached'
7
+
8
8
  include Helpers
9
9
 
10
10
  def load
11
11
  compact(
12
12
  database: database,
13
13
  logs_database: logs_database,
14
+ logs_readonly_database: logs_readonly_database,
14
15
  amqp: amqp,
15
16
  redis: redis,
16
17
  memcached: memcached,
@@ -28,6 +29,10 @@ module Travis
28
29
  Database.new(prefix: 'logs').config
29
30
  end
30
31
 
32
+ def logs_readonly_database
33
+ Database.new(prefix: 'logs_readonly').config
34
+ end
35
+
31
36
  def amqp
32
37
  compact(Url.parse(amqp_url).to_h)
33
38
  end
@@ -13,6 +13,7 @@ module Travis
13
13
  config = compact(Url.parse(url).to_h)
14
14
  config = deep_merge(DEFAULTS, config) unless config.empty?
15
15
  config[:pool] = pool.to_i if pool
16
+ config[:prepared_statements] = prepared_statements != 'false' if prepared_statements
16
17
  config
17
18
  end
18
19
 
@@ -25,6 +26,10 @@ module Travis
25
26
  def pool
26
27
  env('DATABASE_POOL_SIZE', 'DB_POOL').compact.first
27
28
  end
29
+
30
+ def prepared_statements
31
+ ENV['PGBOUNCER_PREPARED_STATEMENTS']
32
+ end
28
33
 
29
34
  def env(*keys)
30
35
  ENV.values_at(*keys.map { |key| prefix(key) }.flatten)
@@ -0,0 +1,9 @@
1
+ module Travis
2
+ class Config
3
+ class Keychain < Struct.new(:defaults)
4
+ def load
5
+ ENV['travis_config'] ? YAML.load(ENV['travis_config']) : {}
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module Travis
2
+ class Config
3
+ module Serialize
4
+ class Env < Struct.new(:config, :opts)
5
+ attr_reader :config, :opts
6
+
7
+ def initialize(config, opts = {})
8
+ @config = config
9
+ @opts = opts
10
+ end
11
+
12
+ def apply
13
+ vars.to_a.map { |pair| pair.join('=') }
14
+ end
15
+
16
+ private
17
+
18
+ def vars
19
+ collect(Array(prefix), config).map do |keys, value|
20
+ [keys.map(&:to_s).map(&:upcase).join('_'), value.to_s]
21
+ end.to_h
22
+ end
23
+
24
+ def collect(keys, config)
25
+ compact(config).inject({}) do |result, (key, value)|
26
+ case value
27
+ when Hash
28
+ result.merge collect(keys + [key], value)
29
+ else
30
+ result.merge [[keys + [key], value]].to_h
31
+ end
32
+ end
33
+ end
34
+
35
+ def compact(hash)
36
+ hash.reject { |_, value| value.nil? }.to_h
37
+ end
38
+
39
+ def prefix
40
+ opts[:prefix]
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module TravisConfig
2
- VERSION = '1.0.13'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -3,15 +3,22 @@ ENV['DYNO'] = 'travis-config/specs'
3
3
 
4
4
  require 'mocha'
5
5
  require 'travis/config'
6
+ require 'support/env'
7
+ require 'support/fakefs'
6
8
 
7
9
  module Travis::Test
8
10
  class Config < Travis::Config
9
- define amqp: { username: 'guest', password: 'guest', host: 'localhost', prefetch: 1 }
10
- define database: { adapter: 'postgresql', database: 'test', encoding: 'unicode' }
11
+ define amqp: { username: 'guest', password: 'guest', host: 'localhost', prefetch: 1 },
12
+ database: { adapter: 'postgresql', database: 'test', encoding: 'unicode' },
13
+ redis: { url: 'redis://localhost:6379' }
14
+
15
+ Env.prefix :travis
11
16
  end
12
17
  end
13
18
 
14
- RSpec.configure do |config|
15
- config.mock_with :mocha
19
+ RSpec.configure do |c|
20
+ c.mock_with :mocha
21
+ c.include Support::Env
22
+ c.include Support::FakeFs
16
23
  end
17
24
 
@@ -0,0 +1,24 @@
1
+ module Support
2
+ module Env
3
+ def self.included(base)
4
+ base.send(:extend, ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def env(vars)
9
+ before { define_env(vars) }
10
+ end
11
+ end
12
+
13
+ def define_env(vars)
14
+ vars.each do |key, value|
15
+ ENV[key.to_s] = value.is_a?(Proc) ? instance_exec(&value).to_s : value.to_s
16
+ end
17
+ self.class.after { undefine_env(vars) }
18
+ end
19
+
20
+ def undefine_env(vars)
21
+ vars.each { |key, _| ENV.delete(key.to_s) }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ require 'pp' # https://github.com/fakefs/fakefs#fakefs-vs-pp-----typeerror-superclass-mismatch-for-class-file
2
+ require 'fakefs/safe'
3
+ require 'fileutils'
4
+
5
+ module Support
6
+ module FakeFs
7
+ def self.included(base)
8
+ base.send(:extend, ClassMethods)
9
+ base.before { FakeFS.activate! }
10
+ base.after { FakeFS.deactivate! }
11
+ base.after { FakeFS::FileSystem.clear }
12
+ end
13
+
14
+ module ClassMethods
15
+ def dir(dir)
16
+ before { FileUtils.mkdir_p(dir) }
17
+ after { FileUtils.rm_rf(dir) }
18
+ end
19
+
20
+ def file(path, content)
21
+ before { FileUtils.mkdir_p(File.dirname(path)) }
22
+ before { File.write(path, content) }
23
+ after { FileUtils.rm_rf(File.dirname(path)) }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,10 +1,8 @@
1
1
  describe Travis::Config::Docker do
2
2
  let(:config) { Travis::Test::Config.load(:docker) }
3
- let(:vars) { %w(POSTGRESQL_PORT RABBITMQ_PORT REDIS_PORT) }
4
- after { vars.each { |key| ENV.delete(key) } }
5
3
 
6
4
  describe 'loads POSTGRESQL_PORT to config.database' do
7
- before { ENV['POSTGRESQL_PORT'] = 'tcp://172.17.0.11:5432' }
5
+ env POSTGRESQL_PORT: 'tcp://172.17.0.11:5432'
8
6
 
9
7
  it 'loads host and port from the env var' do
10
8
  expect(config.database.values_at(:host, :port)).to eq(['172.17.0.11', '5432'])
@@ -16,7 +14,7 @@ describe Travis::Config::Docker do
16
14
  end
17
15
 
18
16
  describe 'loads RABBITMQ_PORT to config.amqp' do
19
- before { ENV['RABBITMQ_PORT'] = 'tcp://172.17.0.11:5672' }
17
+ env RABBITMQ_PORT: 'tcp://172.17.0.11:5672'
20
18
 
21
19
  it 'loads host and port from the env var' do
22
20
  expect(config.amqp.values_at(:host, :port)).to eq(['172.17.0.11', '5672'])
@@ -28,7 +26,7 @@ describe Travis::Config::Docker do
28
26
  end
29
27
 
30
28
  describe 'loads REDIS_PORT' do
31
- before { ENV['REDIS_PORT'] = 'tcp://172.17.0.7:6379' }
29
+ env REDIS_PORT: 'tcp://172.17.0.7:6379'
32
30
 
33
31
  it 'loads the port to redis.url' do
34
32
  expect(config.redis.to_h).to eq({ url: 'tcp://172.17.0.7:6379' })
@@ -0,0 +1,90 @@
1
+ module Travis::Test::Env
2
+ class Config < Travis::Config
3
+ define database: { adapter: nil, variables: { statement_timeout: nil } },
4
+ hash: { under_scored: nil, nested: { foo: nil } },
5
+ integer: nil,
6
+ float: nil,
7
+ true: nil,
8
+ yes: nil,
9
+ on: nil,
10
+ false: nil,
11
+ no: nil,
12
+ off: nil,
13
+ nil: nil
14
+
15
+
16
+ Env.prefix :travis
17
+ end
18
+ end
19
+
20
+ describe Travis::Config::Env do
21
+ let(:config) { Travis::Test::Env::Config.load(:env) }
22
+
23
+ describe 'cast' do
24
+ env TRAVIS_HASH_UNDER_SCORED: 'under_scored',
25
+ TRAVIS_HASH_NESTED_FOO: 'foo',
26
+ TRAVIS_INTEGER: '10',
27
+ TRAVIS_FLOAT: '10.0',
28
+ TRAVIS_TRUE: 'true',
29
+ TRAVIS_YES: 'yes',
30
+ TRAVIS_ON: 'on',
31
+ TRAVIS_FALSE: 'false',
32
+ TRAVIS_NO: 'no',
33
+ TRAVIS_OFF: 'off',
34
+ TRAVIS_NIL: nil
35
+
36
+ it { expect(config.hash.under_scored).to eq 'under_scored' }
37
+ it { expect(config.hash.nested.foo).to eq 'foo' }
38
+ it { expect(config.integer).to eq 10 }
39
+ it { expect(config.float).to eq 10.0 }
40
+ it { expect(config.true).to be true }
41
+ it { expect(config.yes).to be true }
42
+ it { expect(config.on).to be true }
43
+ it { expect(config.false).to be false }
44
+ it { expect(config.no).to be false }
45
+ it { expect(config.off).to be false }
46
+ it { expect(config.nil).to be_nil }
47
+ end
48
+
49
+ describe 'database' do
50
+ env TRAVIS_DATABASE_ADAPTER: 'postgres',
51
+ TRAVIS_DATABASE_VARIABLES_STATEMENT_TIMEOUT: 10_000
52
+
53
+ it { expect(config.database.adapter).to eq 'postgres' }
54
+ it { expect(config.database.variables.statement_timeout).to eq 10_000 }
55
+ end
56
+ end
57
+
58
+ module Travis::Test::Env::Arrays
59
+ class Config < Travis::Config
60
+ define hashes_one: [foo: 'foo'],
61
+ hashes_two: [foo: 1, bar: true],
62
+ strings: []
63
+
64
+ Env.prefix :travis
65
+ end
66
+ end
67
+
68
+ describe Travis::Config::Env, 'arrays' do
69
+ let(:config) { Travis::Test::Env::Arrays::Config.load(:env) }
70
+
71
+ describe 'cast' do
72
+ env TRAVIS_HASHES_ONE_0_FOO: 'bar',
73
+ TRAVIS_HASHES_ONE_1_FOO: 'baz',
74
+ TRAVIS_HASHES_TWO_0_FOO: 1,
75
+ TRAVIS_HASHES_TWO_0_BAR: 'true',
76
+ TRAVIS_HASHES_TWO_1_FOO: 1.1,
77
+ TRAVIS_HASHES_TWO_1_BAR: 'false',
78
+ TRAVIS_STRINGS: 'foo,bar'
79
+
80
+ it { expect(config.hashes_one).to eq [{ foo: 'bar' }, { foo: 'baz' }] }
81
+ it { expect(config.hashes_two).to eq [{ foo: 1, bar: true }, { foo: 1.1, bar: false }] }
82
+ it { expect(config.strings).to eq ['foo', 'bar'] }
83
+ end
84
+
85
+ describe 'unexpected string' do
86
+ env TRAVIS_HASHES_ONE: 'foo'
87
+
88
+ it { expect { config }.to raise_error(described_class::UnexpectedString) }
89
+ end
90
+ end
@@ -1,8 +1,7 @@
1
1
  describe Travis::Config::Heroku, :Amqp do
2
2
  let(:config) { Travis::Test::Config.load(:heroku) }
3
3
 
4
- before { ENV['RABBITMQ_URL'] = url }
5
- after { ENV.delete('RABBITMQ_URL') }
4
+ env RABBITMQ_URL: -> { url }
6
5
 
7
6
  describe 'using amqp as a protocol' do
8
7
  let(:url) { 'amqp://username:password@hostname:1234/vhost' }
@@ -1,199 +1,222 @@
1
1
  describe Travis::Config::Heroku, :Database do
2
2
  let(:config) { Travis::Test::Config.load(:heroku) }
3
- before { ENV['DYNO'] = 'app_name' }
4
- after { ENV.clear }
5
-
6
- it 'loads a TRAVIS_DATABASE_URL with a port' do
7
- ENV['TRAVIS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/database'
8
-
9
- expect(config.database.to_h).to eq(
10
- adapter: 'postgresql',
11
- host: 'hostname',
12
- port: 1234,
13
- database: 'database',
14
- username: 'username',
15
- password: 'password',
16
- encoding: 'unicode',
17
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
18
- )
3
+ env DYNO: 'app_name'
4
+
5
+ describe 'loads a TRAVIS_DATABASE_URL with a port' do
6
+ env TRAVIS_DATABASE_URL: 'postgres://username:password@hostname:1234/database'
7
+
8
+ it do
9
+ expect(config.database.to_h).to eq(
10
+ adapter: 'postgresql',
11
+ host: 'hostname',
12
+ port: 1234,
13
+ database: 'database',
14
+ username: 'username',
15
+ password: 'password',
16
+ encoding: 'unicode',
17
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
18
+ )
19
+ end
19
20
  end
20
21
 
21
- it 'loads a DATABASE_URL with a port' do
22
- ENV['DATABASE_URL'] = 'postgres://username:password@hostname:1234/database'
23
-
24
- expect(config.database.to_h).to eq(
25
- adapter: 'postgresql',
26
- host: 'hostname',
27
- port: 1234,
28
- database: 'database',
29
- username: 'username',
30
- password: 'password',
31
- encoding: 'unicode',
32
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
33
- )
22
+ describe 'loads a DATABASE_URL with a port' do
23
+ env DATABASE_URL: 'postgres://username:password@hostname:1234/database'
24
+
25
+ it do
26
+ expect(config.database.to_h).to eq(
27
+ adapter: 'postgresql',
28
+ host: 'hostname',
29
+ port: 1234,
30
+ database: 'database',
31
+ username: 'username',
32
+ password: 'password',
33
+ encoding: 'unicode',
34
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
35
+ )
36
+ end
34
37
  end
35
38
 
36
- it 'loads a DATABASE_URL without a port' do
37
- ENV['DATABASE_URL'] = 'postgres://username:password@hostname/database'
38
-
39
- expect(config.database.to_h).to eq(
40
- adapter: 'postgresql',
41
- host: 'hostname',
42
- database: 'database',
43
- username: 'username',
44
- password: 'password',
45
- encoding: 'unicode',
46
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
47
- )
39
+ describe 'loads a DATABASE_URL without a port' do
40
+ env DATABASE_URL: 'postgres://username:password@hostname/database'
41
+
42
+ it do
43
+ expect(config.database.to_h).to eq(
44
+ adapter: 'postgresql',
45
+ host: 'hostname',
46
+ database: 'database',
47
+ username: 'username',
48
+ password: 'password',
49
+ encoding: 'unicode',
50
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
51
+ )
52
+ end
48
53
  end
49
54
 
50
- it 'loads TRAVIS_DATABASE_POOL_SIZE' do
51
- ENV['TRAVIS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/database'
52
- ENV['TRAVIS_DATABASE_POOL_SIZE'] = '25'
53
-
54
- expect(config.database.to_h).to eq(
55
- adapter: 'postgresql',
56
- host: 'hostname',
57
- port: 1234,
58
- database: 'database',
59
- username: 'username',
60
- password: 'password',
61
- encoding: 'unicode',
62
- pool: 25,
63
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
64
- )
55
+ describe 'loads TRAVIS_DATABASE_POOL_SIZE' do
56
+ env TRAVIS_DATABASE_URL: 'postgres://username:password@hostname:1234/database'
57
+ env TRAVIS_DATABASE_POOL_SIZE: '25'
58
+
59
+ it do
60
+ expect(config.database.to_h).to eq(
61
+ adapter: 'postgresql',
62
+ host: 'hostname',
63
+ port: 1234,
64
+ database: 'database',
65
+ username: 'username',
66
+ password: 'password',
67
+ encoding: 'unicode',
68
+ pool: 25,
69
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
70
+ )
71
+ end
65
72
  end
66
73
 
67
- it 'loads DATABASE_POOL_SIZE' do
68
- ENV['DATABASE_URL'] = 'postgres://username:password@hostname:1234/database'
69
- ENV['DATABASE_POOL_SIZE'] = '25'
70
-
71
- expect(config.database.to_h).to eq(
72
- adapter: 'postgresql',
73
- host: 'hostname',
74
- port: 1234,
75
- database: 'database',
76
- username: 'username',
77
- password: 'password',
78
- encoding: 'unicode',
79
- pool: 25,
80
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
81
- )
74
+ describe 'loads DATABASE_POOL_SIZE' do
75
+ env DATABASE_URL: 'postgres://username:password@hostname:1234/database'
76
+ env DATABASE_POOL_SIZE: '25'
77
+
78
+ it do
79
+ expect(config.database.to_h).to eq(
80
+ adapter: 'postgresql',
81
+ host: 'hostname',
82
+ port: 1234,
83
+ database: 'database',
84
+ username: 'username',
85
+ password: 'password',
86
+ encoding: 'unicode',
87
+ pool: 25,
88
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
89
+ )
90
+ end
82
91
  end
83
92
 
84
- it 'loads DB_POOL' do
85
- ENV['DATABASE_URL'] = 'postgres://username:password@hostname:1234/database'
86
- ENV['DB_POOL'] = '25'
87
-
88
- expect(config.database.to_h).to eq(
89
- adapter: 'postgresql',
90
- host: 'hostname',
91
- port: 1234,
92
- database: 'database',
93
- username: 'username',
94
- password: 'password',
95
- encoding: 'unicode',
96
- pool: 25,
97
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
98
- )
93
+ describe 'loads DB_POOL' do
94
+ env DATABASE_URL: 'postgres://username:password@hostname:1234/database'
95
+ env DB_POOL: '25'
96
+
97
+ it do
98
+ expect(config.database.to_h).to eq(
99
+ adapter: 'postgresql',
100
+ host: 'hostname',
101
+ port: 1234,
102
+ database: 'database',
103
+ username: 'username',
104
+ password: 'password',
105
+ encoding: 'unicode',
106
+ pool: 25,
107
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
108
+ )
109
+ end
99
110
  end
100
111
 
101
- it 'loads a TRAVIS_LOGS_DATABASE_URL with a port' do
102
- ENV['TRAVIS_LOGS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/logs_database'
103
-
104
- expect(config.logs_database.to_h).to eq(
105
- adapter: 'postgresql',
106
- host: 'hostname',
107
- port: 1234,
108
- database: 'logs_database',
109
- username: 'username',
110
- password: 'password',
111
- encoding: 'unicode',
112
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
113
- )
112
+ describe 'loads a TRAVIS_LOGS_DATABASE_URL with a port' do
113
+ env TRAVIS_LOGS_DATABASE_URL: 'postgres://username:password@hostname:1234/logs_database'
114
+
115
+ it do
116
+ expect(config.logs_database.to_h).to eq(
117
+ adapter: 'postgresql',
118
+ host: 'hostname',
119
+ port: 1234,
120
+ database: 'logs_database',
121
+ username: 'username',
122
+ password: 'password',
123
+ encoding: 'unicode',
124
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
125
+ )
126
+ end
114
127
  end
115
128
 
116
- it 'loads a LOGS_DATABASE_URL with a port' do
117
- ENV['LOGS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/logs_database'
118
-
119
- expect(config.logs_database.to_h).to eq(
120
- adapter: 'postgresql',
121
- host: 'hostname',
122
- port: 1234,
123
- database: 'logs_database',
124
- username: 'username',
125
- password: 'password',
126
- encoding: 'unicode',
127
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
128
- )
129
+ describe 'loads a LOGS_DATABASE_URL with a port' do
130
+ env LOGS_DATABASE_URL: 'postgres://username:password@hostname:1234/logs_database'
131
+
132
+ it do
133
+ expect(config.logs_database.to_h).to eq(
134
+ adapter: 'postgresql',
135
+ host: 'hostname',
136
+ port: 1234,
137
+ database: 'logs_database',
138
+ username: 'username',
139
+ password: 'password',
140
+ encoding: 'unicode',
141
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
142
+ )
143
+ end
129
144
  end
130
145
 
131
- it 'loads a LOGS_DATABASE_URL without a port' do
132
- ENV['LOGS_DATABASE_URL'] = 'postgres://username:password@hostname/logs_database'
133
-
134
- expect(config.logs_database.to_h).to eq(
135
- adapter: 'postgresql',
136
- host: 'hostname',
137
- database: 'logs_database',
138
- username: 'username',
139
- password: 'password',
140
- encoding: 'unicode',
141
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
142
- )
146
+ describe 'loads a LOGS_DATABASE_URL without a port' do
147
+ env LOGS_DATABASE_URL: 'postgres://username:password@hostname/logs_database'
148
+
149
+ it do
150
+ expect(config.logs_database.to_h).to eq(
151
+ adapter: 'postgresql',
152
+ host: 'hostname',
153
+ database: 'logs_database',
154
+ username: 'username',
155
+ password: 'password',
156
+ encoding: 'unicode',
157
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
158
+ )
159
+ end
143
160
  end
144
161
 
145
- it 'loads LOGS_DB_POOL' do
146
- ENV['LOGS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/logs_database'
147
- ENV['LOGS_DB_POOL'] = '1'
148
-
149
- expect(config.logs_database.to_h).to eq(
150
- adapter: 'postgresql',
151
- host: 'hostname',
152
- port: 1234,
153
- database: 'logs_database',
154
- username: 'username',
155
- password: 'password',
156
- encoding: 'unicode',
157
- pool: 1,
158
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
159
- )
162
+ describe 'loads LOGS_DB_POOL' do
163
+ env LOGS_DATABASE_URL: 'postgres://username:password@hostname:1234/logs_database'
164
+ env LOGS_DB_POOL: '1'
165
+
166
+ it do
167
+ expect(config.logs_database.to_h).to eq(
168
+ adapter: 'postgresql',
169
+ host: 'hostname',
170
+ port: 1234,
171
+ database: 'logs_database',
172
+ username: 'username',
173
+ password: 'password',
174
+ encoding: 'unicode',
175
+ pool: 1,
176
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
177
+ )
178
+ end
160
179
  end
161
180
 
162
- it 'loads TRAVIS_LOGS_DATABASE_POOL_SIZE' do
163
- ENV['TRAVIS_LOGS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/logs_database'
164
- ENV['TRAVIS_LOGS_DATABASE_POOL_SIZE'] = '25'
165
-
166
- expect(config.logs_database.to_h).to eq(
167
- adapter: 'postgresql',
168
- host: 'hostname',
169
- port: 1234,
170
- database: 'logs_database',
171
- username: 'username',
172
- password: 'password',
173
- encoding: 'unicode',
174
- pool: 25,
175
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
176
- )
181
+ describe 'loads TRAVIS_LOGS_DATABASE_POOL_SIZE' do
182
+ env TRAVIS_LOGS_DATABASE_URL: 'postgres://username:password@hostname:1234/logs_database'
183
+ env TRAVIS_LOGS_DATABASE_POOL_SIZE: '25'
184
+
185
+ it do
186
+ expect(config.logs_database.to_h).to eq(
187
+ adapter: 'postgresql',
188
+ host: 'hostname',
189
+ port: 1234,
190
+ database: 'logs_database',
191
+ username: 'username',
192
+ password: 'password',
193
+ encoding: 'unicode',
194
+ pool: 25,
195
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
196
+ )
197
+ end
177
198
  end
178
199
 
179
- it 'loads LOGS_DATABASE_POOL_SIZE' do
180
- ENV['LOGS_DATABASE_URL'] = 'postgres://username:password@hostname:1234/logs_database'
181
- ENV['LOGS_DATABASE_POOL_SIZE'] = '25'
182
-
183
- expect(config.logs_database.to_h).to eq(
184
- adapter: 'postgresql',
185
- host: 'hostname',
186
- port: 1234,
187
- database: 'logs_database',
188
- username: 'username',
189
- password: 'password',
190
- encoding: 'unicode',
191
- pool: 25,
192
- variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
193
- )
200
+ describe 'loads LOGS_DATABASE_POOL_SIZE' do
201
+ env LOGS_DATABASE_URL: 'postgres://username:password@hostname:1234/logs_database'
202
+ env LOGS_DATABASE_POOL_SIZE: '25'
203
+
204
+ it do
205
+ expect(config.logs_database.to_h).to eq(
206
+ adapter: 'postgresql',
207
+ host: 'hostname',
208
+ port: 1234,
209
+ database: 'logs_database',
210
+ username: 'username',
211
+ password: 'password',
212
+ encoding: 'unicode',
213
+ pool: 25,
214
+ variables: { application_name: 'travis-config/specs', statement_timeout: 10_000 }
215
+ )
216
+ end
194
217
  end
195
218
 
196
- it 'sets logs_database to nil if no LOGS_DATABASE_URL is given' do
197
- expect(config.logs_database).to be_nil
219
+ describe 'sets logs_database to nil if no LOGS_DATABASE_URL is given' do
220
+ it { expect(config.logs_database).to be_nil }
198
221
  end
199
222
  end
@@ -5,8 +5,7 @@ describe Travis::Config::Heroku, :Memcached do
5
5
  let(:password) { 'password' }
6
6
 
7
7
  [:servers, :username, :password].each do |key|
8
- before { ENV["MEMCACHED_#{key.to_s.upcase}"] = send(key) }
9
- after { ENV.delete("MEMCACHED_#{key.to_s.upcase}") }
8
+ env "MEMCACHED_#{key.to_s.upcase}" => -> { send(key) }
10
9
  end
11
10
 
12
11
  it 'loads a MEMCACHED_SERVERS' do
@@ -2,8 +2,7 @@ describe Travis::Config::Heroku, :Redis do
2
2
  let(:config) { Travis::Test::Config.load(:heroku) }
3
3
  let(:url) { 'redis://username:password@hostname:1234/database' }
4
4
 
5
- before { ENV['REDIS_URL'] = url }
6
- after { ENV.delete('REDIS_URL') }
5
+ env REDIS_URL: -> { url }
7
6
 
8
7
  it 'loads a REDIS_URL' do
9
8
  expect(config.redis.to_h).to eq(url: url)
@@ -2,16 +2,13 @@ describe Travis::Config::Heroku, :Sentry do
2
2
  let(:config) { Travis::Test::Config.load(:heroku) }
3
3
  let(:dsn) { 'http://foo:bar@app.getsentry.com/1' }
4
4
 
5
- before { ENV[key] = dsn }
6
- after { ENV.delete('SENTRY_DSN') }
7
-
8
5
  describe 'loads a SENTRY_DSN' do
9
- let(:key) { 'SENTRY_DSN' }
6
+ env SENTRY_DSN: -> { dsn }
10
7
  it { expect(config.sentry.to_h).to eq(dsn: dsn) }
11
8
  end
12
9
 
13
10
  describe 'loads a TRAVIS_SENTRY_DSN' do
14
- let(:key) { 'TRAVIS_SENTRY_DSN' }
11
+ env TRAVIS_SENTRY_DSN: -> { dsn }
15
12
  it { expect(config.sentry.to_h).to eq(dsn: dsn) }
16
13
  end
17
14
  end
@@ -0,0 +1,17 @@
1
+ describe Travis::Config::Serialize::Env do
2
+ let(:config) do
3
+ {
4
+ foo: { bar: :baz },
5
+ true: true,
6
+ false: false,
7
+ nil: nil
8
+ }
9
+ end
10
+
11
+ subject { described_class.new(config, prefix: 'travis').apply }
12
+
13
+ it { should include 'TRAVIS_FOO_BAR=baz' }
14
+ it { should include 'TRAVIS_TRUE=true' }
15
+ it { should include 'TRAVIS_FALSE=false' }
16
+ it { should_not include 'TRAVIS_NIL=' }
17
+ end
@@ -1,72 +1,54 @@
1
1
  describe Travis::Config do
2
- let(:config) { Travis::Test::Config.load(:files, :env, :heroku, :docker) }
2
+ let(:config) { Travis::Test::Config.load(:files, :keychain, :heroku, :docker) }
3
3
 
4
4
  describe 'Hashr behaviour' do
5
5
  after :each do
6
6
  ENV.delete('travis_config')
7
7
  end
8
8
 
9
- it 'is a Hashr instance' do
10
- expect(config).to be_kind_of(Hashr)
11
- end
9
+ it { expect(config).to be_kind_of(Hashr) }
12
10
 
13
- it 'returns Hashr instances on subkeys' do
14
- ENV['travis_config'] = YAML.dump('redis' => { 'url' => 'redis://localhost:6379' })
15
- expect(config.redis).to be_kind_of(Hashr)
11
+ describe 'returns Hashr instances on subkeys' do
12
+ before { ENV['travis_config'] = YAML.dump('redis' => { 'url' => 'redis://localhost:6379' }) }
13
+ it { expect(config.redis).to be_kind_of(Hashr) }
16
14
  end
17
15
 
18
- it 'returns Hashr instances on subkeys that were set to Ruby Hashes' do
19
- config.foo = { :bar => { :baz => 'baz' } }
20
- expect(config.foo.bar).to be_kind_of(Hashr)
16
+ describe 'returns Hashr instances on subkeys that were set to Ruby Hashes' do
17
+ before { config.foo = { :bar => { :baz => 'baz' } } }
18
+ it { expect(config.foo.bar).to be_kind_of(Hashr) }
21
19
  end
22
20
 
23
- it 'can access nested keys' do
24
- expect(config.amqp.username).to eq('guest')
21
+ describe 'can access nested keys' do
22
+ it { expect(config.amqp.username).to eq('guest') }
25
23
  end
26
24
  end
27
25
 
28
26
  describe 'reads custom config files' do
29
- before :each do
30
- Dir.stubs(:[]).returns ['config/travis.yml', 'config/travis/foo.yml', 'config/travis/bar.yml']
31
- YAML.stubs(:load_file).with('config/travis.yml').returns('test' => { 'travis' => 'travis', 'shared' => 'travis' })
32
- YAML.stubs(:load_file).with('config/travis/foo.yml').returns('test' => { 'foo' => 'foo' })
33
- YAML.stubs(:load_file).with('config/travis/bar.yml').returns('test' => { 'bar' => 'bar', 'shared' => 'bar' })
34
- end
35
-
36
- it 'still reads the default config file' do
37
- expect(config.travis).to eq('travis')
38
- end
39
-
40
- it 'merges custom files' do
41
- expect(config.foo).to eq('foo')
42
- expect(config.bar).to eq('bar')
43
- end
44
-
45
- it 'overwrites previously set values with values loaded later' do
46
- expect(config.shared).to eq('bar')
47
- end
27
+ file 'config/travis.yml', YAML.dump('test' => { 'travis' => 'travis', 'shared' => 'travis' })
28
+ file 'config/travis/foo.yml', YAML.dump('test' => { 'foo' => 'foo' })
29
+ file 'config/travis/bar.yml', YAML.dump('test' => { 'bar' => 'bar', 'shared' => 'bar' })
30
+
31
+ it { expect(config.travis).to eq('travis') }
32
+ it { expect(config.foo).to eq('foo') }
33
+ it { expect(config.bar).to eq('bar') }
34
+ it { expect(config.shared).to eq('bar') }
48
35
  end
49
36
 
50
- it 'deep symbolizes arrays, too' do
51
- config = Travis::Config.new('queues' => [{ 'slug' => 'rails/rails', 'queue' => 'rails' }])
52
- expect(config.queues.first.values_at(:slug, :queue)).to eq(['rails/rails', 'rails'])
37
+ describe 'deep symbolizes arrays, too' do
38
+ let(:config) { Travis::Config.new('queues' => [{ 'slug' => 'rails/rails', 'queue' => 'rails' }]) }
39
+ it { expect(config.queues.first.values_at(:slug, :queue)).to eq(['rails/rails', 'rails']) }
53
40
  end
54
41
 
55
42
  describe 'logs_database config' do
56
- before { ENV['DATABASE_URL'] = 'postgres://username:password@hostname:1234/database' }
57
- after { ENV['DATABASE_URL'] = nil }
43
+ env DATABASE_URL: 'postgres://username:password@hostname:1234/database'
58
44
 
59
45
  describe 'given logs_database is defined in a config file' do
60
- before do
61
- Dir.stubs(:[]).returns ['config/travis.yml']
62
- YAML.stubs(:load_file).with('config/travis.yml').returns('test' => { 'logs_database' => { 'database' => 'config_file' } })
63
- end
64
- it { expect(config.logs_database.database).to eq 'config_file' }
46
+ file 'config/travis.yml', YAML.dump('test' => { 'logs_database' => { 'database' => 'from_file' } })
47
+ it { expect(config.logs_database.database).to eq 'from_file' }
65
48
  end
66
49
 
67
50
  describe 'given logs_database is defined in the keychain' do
68
- before { ENV['travis_config'] = YAML.dump('logs_database' => { 'database' => 'keychain' }) }
69
- after { ENV['travis_config'] = nil }
51
+ env travis_config: YAML.dump('logs_database' => { 'database' => 'keychain' })
70
52
  it { expect(config.logs_database.database).to eq 'keychain' }
71
53
  end
72
54
 
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: travis-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.13
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis CI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2017-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashr
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.0.0
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
26
  version: 2.0.0
27
27
  description: Travis CI config.
@@ -30,28 +30,35 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
+ - Gemfile
34
+ - Gemfile.lock
35
+ - LICENSE
36
+ - README.md
37
+ - lib/travis/config.rb
33
38
  - lib/travis/config/docker.rb
34
39
  - lib/travis/config/env.rb
35
40
  - lib/travis/config/files.rb
36
41
  - lib/travis/config/helpers.rb
42
+ - lib/travis/config/heroku.rb
37
43
  - lib/travis/config/heroku/database.rb
38
44
  - lib/travis/config/heroku/memcached.rb
39
45
  - lib/travis/config/heroku/url.rb
40
- - lib/travis/config/heroku.rb
46
+ - lib/travis/config/keychain.rb
47
+ - lib/travis/config/serialize/env.rb
41
48
  - lib/travis/config/version.rb
42
- - lib/travis/config.rb
43
49
  - spec/spec_helper.rb
50
+ - spec/support/env.rb
51
+ - spec/support/fakefs.rb
44
52
  - spec/travis/config/docker_spec.rb
53
+ - spec/travis/config/env_spec.rb
45
54
  - spec/travis/config/files_spec.rb
46
55
  - spec/travis/config/heroku/amqp_spec.rb
47
56
  - spec/travis/config/heroku/database_spec.rb
48
57
  - spec/travis/config/heroku/memcached_spec.rb
49
58
  - spec/travis/config/heroku/redis_spec.rb
50
59
  - spec/travis/config/heroku/sentry_spec.rb
60
+ - spec/travis/config/serialize/env_spec.rb
51
61
  - spec/travis/config_spec.rb
52
- - Gemfile
53
- - LICENSE
54
- - README.md
55
62
  homepage: https://github.com/travis-ci/travis-config
56
63
  licenses:
57
64
  - MIT
@@ -62,17 +69,17 @@ require_paths:
62
69
  - lib
63
70
  required_ruby_version: !ruby/object:Gem::Requirement
64
71
  requirements:
65
- - - '>='
72
+ - - ">="
66
73
  - !ruby/object:Gem::Version
67
74
  version: '0'
68
75
  required_rubygems_version: !ruby/object:Gem::Requirement
69
76
  requirements:
70
- - - '>='
77
+ - - ">="
71
78
  - !ruby/object:Gem::Version
72
79
  version: '0'
73
80
  requirements: []
74
- rubyforge_project: '[none]'
75
- rubygems_version: 2.0.14.1
81
+ rubyforge_project: "[none]"
82
+ rubygems_version: 2.6.11
76
83
  signing_key:
77
84
  specification_version: 4
78
85
  summary: Travis CI config