mux_tf 0.3.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d3511e5badfa499bd43efb92048717c8d597633229c4e135a51c0d57ea56d84
4
- data.tar.gz: 3a2feb35ce3d7a9c4f2781b2ace26eb08ed41da0ba047b33a8b4882363878914
3
+ metadata.gz: d0ea81053f5625bf3418e334d5d7c0d6b8a8d37ddedf53f0f8c8e5ab90d845a4
4
+ data.tar.gz: 05133bedb2342a2d74a630bd2fff5bd18ff1db2b26dadcf9788c79763ba4dce5
5
5
  SHA512:
6
- metadata.gz: 7559eca291ace43436b5f38ea72823187573c85e7b51029861bf98a4e3b88b9144f0997a915a9ab1e9cb581ddc04807b9a9da569dd233a47207007fae5939b57
7
- data.tar.gz: 15d909df002d4ff344e2966eb2a54d3943407f6d9e910daebc84781de233f215bfa282067f7cf3eaf702811553785e785be9c5d8a437908e8b0f30d1efa911b8
6
+ metadata.gz: db6d757dd45d2e436f0ae475b9dc066d5a6f0b362eab0fe590b18257d620bc2c798fbe681c5533e89b6065a7c2765eccbebfc12bd6e7e1b347b581bcb94e4d60
7
+ data.tar.gz: 851a69520bcae89ca118e770920d85d04e446bddc2cd23877fe1ec73ef32a56c88a845752bdcad4c82ecc918f9037479acf17015323a53570aa6b25530e90c50
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:current, ARGV)
9
+ MuxTf::Cli.run(:current, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
data/exe/tf_mux CHANGED
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:mux, ARGV)
9
+ MuxTf::Cli.run(:mux, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:plan_summary, ARGV)
9
+ MuxTf::Cli.run(:plan_summary, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
@@ -0,0 +1,5 @@
1
+ require "bundler/inline"
2
+
3
+ gemfile do
4
+ gemspec(path: File.join(__dir__, ".."))
5
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "./deps"
4
+
3
5
  require "English"
4
6
 
5
7
  require "shellwords"
@@ -80,9 +80,16 @@ module MuxTf
80
80
  def process_remedies(remedies)
81
81
  if remedies.delete? :init
82
82
  log "Running terraform init ...", depth: 2
83
- tf_init
84
- remedies = PlanFormatter.process_validation(validate)
85
- process_remedies(remedies)
83
+ remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init)
84
+ if process_remedies(remedies)
85
+ remedies = PlanFormatter.process_validation(validate)
86
+ return false unless process_remedies(remedies)
87
+ end
88
+ end
89
+ if remedies.delete? :reconfigure
90
+ log "Running terraform init ...", depth: 2
91
+ remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init(reconfigure: true))
92
+ return false unless process_remedies(remedies)
86
93
  end
87
94
  unless remedies.empty?
88
95
  log "unprocessed remedies: #{remedies.to_a}", depth: 1
@@ -154,6 +161,7 @@ module MuxTf
154
161
  root_cmd.add_command(shell_cmd)
155
162
  root_cmd.add_command(force_unlock_cmd)
156
163
  root_cmd.add_command(upgrade_cmd)
164
+ root_cmd.add_command(reconfigure_cmd)
157
165
  root_cmd.add_command(interactive_cmd)
158
166
 
159
167
  root_cmd.add_command(exit_cmd)
@@ -238,6 +246,16 @@ module MuxTf
238
246
  end
239
247
  end
240
248
 
249
+ def reconfigure_cmd
250
+ define_cmd("reconfigure", summary: "Reconfigure modules/plguins") do |_opts, _args, _cmd|
251
+ status, meta = PlanFormatter.run_tf_init(reconfigure: true)
252
+ if status != 0
253
+ log meta.inspect unless meta.empty?
254
+ log "Reconfigure Failed!"
255
+ end
256
+ end
257
+ end
258
+
241
259
  def interactive_cmd
242
260
  define_cmd("interactive", summary: "Apply interactively") do |_opts, _args, _cmd|
243
261
  plan = PlanSummaryHandler.from_file(PLAN_FILENAME)
@@ -274,7 +292,7 @@ module MuxTf
274
292
  end
275
293
 
276
294
  def run_upgrade
277
- exit_code, meta = PlanFormatter.process_upgrade
295
+ exit_code, meta = PlanFormatter.run_tf_init(upgrade: true)
278
296
  case exit_code
279
297
  when 0
280
298
  [:ok, meta]
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bundler"
4
+
3
5
  module MuxTf
4
6
  module Cli
5
7
  module Mux
@@ -7,6 +9,21 @@ module MuxTf
7
9
  extend PiotrbCliUtils::ShellHelpers
8
10
 
9
11
  class << self
12
+ def with_clean_env
13
+ backup = {}
14
+ Bundler.with_original_env do
15
+ ENV.keys.grep(/^(RBENV_|RUBYLIB)/).each do |key|
16
+ backup[key] = ENV[key]
17
+ ENV.delete(key)
18
+ end
19
+ yield
20
+ end
21
+ ensure
22
+ backup.each do |k, v|
23
+ ENV[k] = v
24
+ end
25
+ end
26
+
10
27
  def run(_args)
11
28
  Dotenv.load(".env.mux")
12
29
 
@@ -38,9 +55,13 @@ module MuxTf
38
55
  end
39
56
 
40
57
  log "Starting new session ..."
41
- Tmux.new_session project
58
+ with_clean_env do
59
+ Tmux.new_session project
60
+ end
42
61
  Tmux.select_pane "initial"
43
62
 
63
+ # Tmux.set "remain-on-exit", "on"
64
+
44
65
  Tmux.set_hook "pane-exited", "select-layout tiled"
45
66
  Tmux.set_hook "window-pane-changed", "select-layout tiled"
46
67
 
@@ -68,6 +89,8 @@ module MuxTf
68
89
 
69
90
  puts "\e]0;tmux: #{project}\007"
70
91
 
92
+ sleep 1
93
+
71
94
  log "Attaching ..."
72
95
  Tmux.attach(project, cc: !!ENV["MUXP_CC_MODE"])
73
96
  log "Done!"
@@ -6,13 +6,9 @@ module MuxTf
6
6
  extend PiotrbCliUtils::Util
7
7
 
8
8
  class << self
9
- # include CommandHelpers
10
-
11
9
  def pretty_plan(filename)
12
10
  pastel = Pastel.new
13
11
 
14
- plan_output = String.new
15
-
16
12
  phase = :init
17
13
 
18
14
  meta = {}
@@ -31,7 +27,6 @@ module MuxTf
31
27
  parser.state(:plan_error, /^Error: /, %i[refreshing refresh_done])
32
28
 
33
29
  status = tf_plan(out: filename, detailed_exitcode: true, compact_warnings: true) { |raw_line|
34
- plan_output << raw_line
35
30
  parser.parse(raw_line.rstrip) do |state, line|
36
31
  case state
37
32
  when :none
@@ -87,10 +82,21 @@ module MuxTf
87
82
  [status.status, meta]
88
83
  end
89
84
 
90
- def process_upgrade
91
- pastel = Pastel.new
85
+ def init_status_to_remedies(status, meta)
86
+ remedies = Set.new
87
+ if status != 0
88
+ if meta[:need_reconfigure]
89
+ remedies << :reconfigure
90
+ else
91
+ p [status, meta]
92
+ remedies << :unknown
93
+ end
94
+ end
95
+ remedies
96
+ end
92
97
 
93
- plan_output = String.new
98
+ def run_tf_init(upgrade: nil, reconfigure: nil)
99
+ pastel = Pastel.new
94
100
 
95
101
  phase = :init
96
102
 
@@ -98,24 +104,39 @@ module MuxTf
98
104
 
99
105
  parser = StatefulParser.new(normalizer: pastel.method(:strip))
100
106
 
101
- parser.state(:modules, /^Upgrading modules\.\.\./)
102
- parser.state(:backend, /^Initializing the backend\.\.\./, [:modules])
107
+ parser.state(:modules_init, /^Initializing modules\.\.\./)
108
+ parser.state(:modules_upgrade, /^Upgrading modules\.\.\./)
109
+ parser.state(:backend, /^Initializing the backend\.\.\./, [:modules_init, :modules_upgrade])
103
110
  parser.state(:plugins, /^Initializing provider plugins\.\.\./, [:backend])
104
111
 
105
112
  parser.state(:plugin_warnings, /^$/, [:plugins])
113
+ parser.state(:backend_error, /Error:/, [:backend])
114
+
115
+ status = tf_init(upgrade: upgrade, reconfigure: reconfigure) { |raw_line|
116
+ stripped_line = pastel.strip(raw_line.rstrip)
106
117
 
107
- status = tf_init(upgrade: true, color: false) { |raw_line|
108
- plan_output << raw_line
109
118
  parser.parse(raw_line.rstrip) do |state, line|
110
119
  case state
111
- when :modules
120
+ when :modules_init
121
+ if phase != state
122
+ phase = state
123
+ log "Initializing modules ", depth: 1
124
+ next
125
+ end
126
+ case stripped_line
127
+ when ""
128
+ puts
129
+ else
130
+ p [state, stripped_line]
131
+ end
132
+ when :modules_upgrade
112
133
  if phase != state
113
134
  # first line
114
135
  phase = state
115
136
  log "Upgrding modules ", depth: 1, newline: false
116
137
  next
117
138
  end
118
- case line
139
+ case stripped_line
119
140
  when /^- (?<module>[^ ]+) in (?<path>.+)$/
120
141
  # info = $~.named_captures
121
142
  # log "- #{info["module"]}", depth: 2
@@ -127,7 +148,7 @@ module MuxTf
127
148
  when ""
128
149
  puts
129
150
  else
130
- p [state, line]
151
+ p [state, stripped_line]
131
152
  end
132
153
  when :backend
133
154
  if phase != state
@@ -136,11 +157,20 @@ module MuxTf
136
157
  log "Initializing the backend ", depth: 1, newline: false
137
158
  next
138
159
  end
139
- case line
160
+ case stripped_line
161
+ when /^Successfully configured/
162
+ log line, depth: 2
163
+ when /unless the backend/
164
+ log line, depth: 2
140
165
  when ""
141
166
  puts
142
167
  else
143
- p [state, line]
168
+ p [state, stripped_line]
169
+ end
170
+ when :backend_error
171
+ if raw_line.match "terraform init -reconfigure"
172
+ meta[:need_reconfigure] = true
173
+ log Paint["module needs to be reconfigured", :red], depth: 2
144
174
  end
145
175
  when :plugins
146
176
  if phase != state
@@ -149,7 +179,25 @@ module MuxTf
149
179
  log "Initializing provider plugins ...", depth: 1
150
180
  next
151
181
  end
152
- case line
182
+ case stripped_line
183
+ when /^- (?<module>.+) is built in to Terraform$/
184
+ info = $LAST_MATCH_INFO.named_captures
185
+ log "- [BUILTIN] #{info["module"]}", depth: 2
186
+ when /^- Finding (?<module>[^ ]+) versions matching "(?<version>.+)"\.\.\./
187
+ info = $LAST_MATCH_INFO.named_captures
188
+ log "- [FIND] #{info["module"]} matching #{info["version"].inspect}", depth: 2
189
+ when /^- Finding latest version of (?<module>.+)\.\.\.$/
190
+ info = $LAST_MATCH_INFO.named_captures
191
+ log "- [FIND] #{info["module"]}", depth: 2
192
+ when /^- Installing (?<module>[^ ]+) v(?<version>.+)\.\.\.$/
193
+ info = $LAST_MATCH_INFO.named_captures
194
+ log "- [INSTALLING] #{info["module"]} v#{info["version"]}", depth: 2
195
+ when /^- Installed (?<module>[^ ]+) v(?<version>.+) \(signed by( a)? (?<signed>.+)\)$/
196
+ info = $LAST_MATCH_INFO.named_captures
197
+ log "- [INSTALLED] #{info["module"]} v#{info["version"]} (#{info["signed"]})", depth: 2
198
+ when /^- Using previously-installed (?<module>[^ ]+) v(?<version>.+)$/
199
+ info = $LAST_MATCH_INFO.named_captures
200
+ log "- [USING] #{info["module"]} v#{info["version"]}", depth: 2
153
201
  when /^- Downloading plugin for provider "(?<provider>[^"]+)" \((?<provider_path>[^)]+)\) (?<version>.+)\.\.\.$/
154
202
  info = $LAST_MATCH_INFO.named_captures
155
203
  log "- #{info["provider"]} #{info["version"]}", depth: 2
@@ -3,6 +3,7 @@
3
3
  module MuxTf
4
4
  class PlanSummaryHandler
5
5
  extend TerraformHelpers
6
+ extend PiotrbCliUtils::Util
6
7
 
7
8
  def self.from_file(file)
8
9
  data = data_from_file(file)
@@ -177,7 +178,7 @@ module MuxTf
177
178
  resource, parent_address = find_config(data["configuration"], "root_module", address, [])
178
179
  if resource
179
180
  deps = []
180
- resource["expressions"].each do |_k, v|
181
+ resource["expressions"]&.each do |_k, v|
181
182
  deps << v["references"] if v.is_a?(Hash) && v["references"]
182
183
  end
183
184
  result += deps.map { |s| (parent_address + [s]).join(".") }
@@ -26,10 +26,11 @@ module MuxTf
26
26
  capture_terraform(cmd, json: true)
27
27
  end
28
28
 
29
- def tf_init(input: nil, upgrade: nil, color: true, &block)
29
+ def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, &block)
30
30
  args = []
31
31
  args << "-input=#{input.inspect}" unless input.nil?
32
32
  args << "-upgrade" unless upgrade.nil?
33
+ args << "-reconfigure" unless reconfigure.nil?
33
34
  args << "-no-color" unless color
34
35
 
35
36
  cmd = tf_prepare_command(["init", *args], need_auth: true)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MuxTf
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.2"
5
5
  end
@@ -1,40 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/mux_tf/version'
3
+ require_relative "lib/mux_tf/version"
4
+ require "rake"
4
5
 
5
6
  Gem::Specification.new do |spec|
6
- spec.name = 'mux_tf'
7
- spec.version = MuxTf::VERSION
8
- spec.authors = ['Piotr Banasik']
9
- spec.email = ['piotr@jane.app']
7
+ spec.name = "mux_tf"
8
+ spec.version = MuxTf::VERSION
9
+ spec.authors = ["Piotr Banasik"]
10
+ spec.email = ["piotr@jane.app"]
10
11
 
11
- spec.summary = 'Terraform Multiplexing Scripts'
12
+ spec.summary = "Terraform Multiplexing Scripts"
12
13
  # spec.description = 'TODO: Write a longer description or delete this line.'
13
- spec.homepage = 'https://github.com/piotrb/mux_tf'
14
- spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
14
+ spec.homepage = "https://github.com/piotrb/mux_tf"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
16
17
 
17
18
  # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
18
19
 
19
- spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = spec.homepage
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = spec.homepage
21
22
  # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
22
23
 
23
24
  # Specify which files should be added to the gem when it is released.
24
25
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
- end
28
- spec.bindir = 'exe'
29
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
- spec.require_paths = ['lib']
26
+ spec.files = Rake::FileList["exe/*", "lib/**/*.rb", "*.gemspec"]
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
31
30
 
32
- spec.add_dependency 'activesupport'
33
- spec.add_dependency 'dotenv'
34
- spec.add_dependency 'paint'
35
- spec.add_dependency 'pastel'
36
- spec.add_dependency 'piotrb_cli_utils', '~> 0.1.0'
37
- spec.add_dependency 'stateful_parser', '~> 0.1.1'
38
- spec.add_dependency 'tty-prompt'
39
- spec.add_dependency 'tty-table'
31
+ spec.add_dependency "activesupport"
32
+ spec.add_dependency "dotenv"
33
+ spec.add_dependency "paint"
34
+ spec.add_dependency "pastel"
35
+ spec.add_dependency "piotrb_cli_utils", "~> 0.1.0"
36
+ spec.add_dependency "stateful_parser", "~> 0.1.1"
37
+ spec.add_dependency "tty-prompt"
38
+ spec.add_dependency "tty-table"
40
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mux_tf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Banasik
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-05 00:00:00.000000000 Z
11
+ date: 2020-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -132,14 +132,10 @@ executables:
132
132
  extensions: []
133
133
  extra_rdoc_files: []
134
134
  files:
135
- - ".gitignore"
136
- - Gemfile
137
- - LICENSE.txt
138
- - README.md
139
- - Rakefile
140
135
  - exe/tf_current
141
136
  - exe/tf_mux
142
137
  - exe/tf_plan_summary
138
+ - lib/deps.rb
143
139
  - lib/mux_tf.rb
144
140
  - lib/mux_tf/cli.rb
145
141
  - lib/mux_tf/cli/current.rb
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- Gemfile.lock
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- # Specify your gem's dependencies in mux_tf.gemspec
6
- gemspec
7
-
8
- gem 'rake', '~> 12.0'
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2020 Piotr Banasik
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.
data/README.md DELETED
@@ -1,52 +0,0 @@
1
- # MuxTf
2
-
3
- Terraform Module Multiplexer
4
-
5
- ## Installation
6
-
7
- ```shell
8
- gem install mux_tf
9
- ```
10
-
11
- ## Usage
12
-
13
- At the root folder of your terraform modules eg:
14
-
15
- ```text
16
- ROOT/
17
- production/ << == HERE
18
- group1/
19
- cluster1/
20
- main.tf
21
- cluster2/
22
- main.tf
23
- group2/
24
- cluster3/
25
- main.tf
26
- cluster4/
27
- main.tf
28
- sandbox/ << == OR HERE
29
- {SIMILLAR STRUCTURE}
30
- ```
31
-
32
- ## Development
33
-
34
- To install this gem onto your local machine, run `bundle exec rake install`.
35
-
36
- ## Releasing
37
-
38
- To release a new version, first bump the version number by running:
39
-
40
- ```shell
41
- gem bump -v major|minor|patch
42
- ```
43
-
44
- And then run `rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
45
-
46
- ## Contributing
47
-
48
- Bug reports and pull requests are welcome on GitHub at https://github.com/piotrb/mux_tf.
49
-
50
- ## License
51
-
52
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- # task :default => :spec