aptible-cli 0.7.4 → 0.7.5

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
  SHA1:
3
- metadata.gz: 02557871e371cd47bdc211ea7a52d11587c9c30c
4
- data.tar.gz: 3f110a5037e15116cd05b55e591e72decd52b677
3
+ metadata.gz: a46c716db34062c50939791b35288542ab1dacc4
4
+ data.tar.gz: 54293b621aba536d05c4ea25740fe61530e9209f
5
5
  SHA512:
6
- metadata.gz: 235225b2aa1c1935f077efd0f23dd5e1af98d46a1a045ef7d1d4a1da6fb9537de0b347cfb6ce58b90605394c94bcbb78dd8fb4777fb4b36b05050c1615b156a3
7
- data.tar.gz: cd51663f95904b23814bfa8d4c1db99357905ca7f4301cb60c5721e70cd8c4568b4a96407cd44e0e805e0e89478412d785949193b97892408f224cc7d4e98403
6
+ metadata.gz: 35fadaf8062518242be514c26c66f406cb9f3ebf79128986852a4a51ef84365610f5058b90fbdcf426a18e5bfc68d4ec3afd03935b6e08d9955961bc1f24d0bb
7
+ data.tar.gz: 96a7acb0ac08381a76753035670d6e26f3d72347ce1b5c2f64f7259a960b73ad12de3e35aedd0b30890a7d2701785059f45218a107fc35a6626106875aafe367
@@ -0,0 +1,31 @@
1
+ version: 1.0.{build}-{branch}
2
+
3
+ environment:
4
+ matrix:
5
+ - RUBY_VERSION: 200
6
+ - RUBY_VERSION: 21
7
+ - RUBY_VERSION: 22
8
+ - RUBY_VERSION: 23
9
+
10
+ install:
11
+ # The SSL_CERT_* environment variables are here since otherwise calls to
12
+ # codecov.io wtill not work. These variables do have to be set in order for
13
+ # the gem to make calls to the Aptible API, since otherwise Ruby will fail
14
+ # with a certificate verification error.
15
+ - set SSL_CERT_DIR=%PROGRAMFILES%\Git\mingw64\ssl\certs
16
+ - set SSL_CERT_FILE=%PROGRAMFILES%\Git\mingw64\ssl\cert.pem
17
+ # Override PATHEXT so our ssh bat file has a higher precedence.
18
+ - set PATHEXT=.BAT;.COM;.EXE;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
19
+ - set PATH=C:\Ruby%RUBY_VERSION%-x64\bin;%PATH%
20
+ - bundle config --local path vendor/bundle
21
+ - bundle install
22
+
23
+ build: off
24
+
25
+ before_test:
26
+ - ruby -v
27
+ - gem -v
28
+ - bundle -v
29
+
30
+ test_script:
31
+ - bundle exec rake ci
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'git'
28
28
  spec.add_dependency 'term-ansicolor'
29
29
  spec.add_dependency 'chronic_duration', '~> 0.10.6'
30
-
30
+ spec.add_dependency 'win32-process' if Gem.win_platform?
31
31
  spec.add_development_dependency 'bundler', '~> 1.3'
32
32
  spec.add_development_dependency 'aptible-tasks', '>= 0.2.0'
33
33
  spec.add_development_dependency 'rake'
@@ -44,9 +44,19 @@ module Aptible
44
44
  true
45
45
  end
46
46
 
47
+ def initialize(*)
48
+ nag_toolbelt unless toolbelt?
49
+ super
50
+ end
51
+
47
52
  desc 'version', 'Print Aptible CLI version'
48
53
  def version
49
- puts "aptible-cli v#{Aptible::CLI::VERSION}"
54
+ bits = [
55
+ 'aptible-cli',
56
+ "v#{Aptible::CLI::VERSION}"
57
+ ]
58
+ bits << 'toolbelt' if toolbelt?
59
+ puts bits.join ' '
50
60
  end
51
61
 
52
62
  desc 'login', 'Log in to Aptible'
@@ -104,6 +114,40 @@ module Aptible
104
114
  say "DEPRECATION NOTICE: #{msg}"
105
115
  say 'Please contact support@aptible.com with any questions.'
106
116
  end
117
+
118
+ def nag_toolbelt
119
+ # If you're reading this, it's possible you decided to not use the
120
+ # toolbelt and are a looking for a way to disable this warning. Look no
121
+ # further: to do so, edit the file `.aptible/nag_toolbelt` and put a
122
+ # timestamp far into the future. For example, writing 1577836800 will
123
+ # disable the warning until 2020.
124
+ nag_file = File.join ENV['HOME'], '.aptible', 'nag_toolbelt'
125
+ nag_frequency = 12.hours
126
+
127
+ last_nag = begin
128
+ Integer(File.read(nag_file))
129
+ rescue Errno::ENOENT, ArgumentError
130
+ 0
131
+ end
132
+
133
+ now = Time.now.utc.to_i
134
+
135
+ if last_nag < now - nag_frequency
136
+ $stderr.puts yellow([
137
+ 'You have installed the Aptible CLI from source.',
138
+ 'This is not recommended: some functionality may not work!',
139
+ 'Review this support topic for more information:',
140
+ 'https://www.aptible.com/support/topics/cli/how-to-install-cli/'
141
+ ].join("\n"))
142
+
143
+ FileUtils.mkdir_p(File.dirname(nag_file))
144
+ File.open(nag_file, 'w', 0o600) { |f| f.write(now.to_s) }
145
+ end
146
+ end
147
+
148
+ def toolbelt?
149
+ ENV['APTIBLE_TOOLBELT']
150
+ end
107
151
  end
108
152
  end
109
153
  end
@@ -1,9 +1,27 @@
1
1
  require 'socket'
2
2
  require 'open3'
3
+ require 'win32-process' if Gem.win_platform?
3
4
 
4
5
  module Aptible
5
6
  module CLI
6
7
  module Helpers
8
+ # The :new_pgroup key specifies the CREATE_NEW_PROCESS_GROUP flag for
9
+ # CreateProcessW() in the Windows API. This is a Windows only option.
10
+ # true means the new process is the root process of the new process
11
+ # group.
12
+ # This flag is necessary for Process.kill(:SIGINT, pid) on the
13
+ # subprocess.
14
+ STOP_SIGNAL = if Gem.win_platform?
15
+ :SIGINT
16
+ else
17
+ :SIGHUP
18
+ end
19
+ SPAWN_OPTS = if Gem.win_platform?
20
+ { new_pgroup: true }
21
+ else
22
+ {}
23
+ end
24
+
7
25
  class Tunnel
8
26
  def initialize(env, ssh_cmd)
9
27
  @env = env
@@ -37,9 +55,9 @@ module Aptible
37
55
 
38
56
  out_read, out_write = IO.pipe
39
57
  err_read, err_write = IO.pipe
40
- @pid = Process.spawn(tunnel_env, *tunnel_cmd, in: :close,
41
- out: out_write,
42
- err: err_write)
58
+
59
+ @pid = Process.spawn(tunnel_env, *tunnel_cmd, SPAWN_OPTS
60
+ .merge(in: :close, out: out_write, err: err_write))
43
61
 
44
62
  # Wait for the tunnel to come up before returning. The other end
45
63
  # will send a message on stdout to indicate that the tunnel is ready.
@@ -59,7 +77,7 @@ module Aptible
59
77
  def stop
60
78
  fail 'You must call #start before calling #stop' if @pid.nil?
61
79
  begin
62
- Process.kill('HUP', @pid)
80
+ Process.kill(STOP_SIGNAL, @pid)
63
81
  rescue Errno::ESRCH
64
82
  nil # Dear Rubocop: I know what I'm doing.
65
83
  end
@@ -22,7 +22,7 @@ module Aptible
22
22
 
23
23
  desc 'db:create HANDLE', 'Create a new database'
24
24
  option :type, default: 'postgresql'
25
- option :size, default: 10
25
+ option :size, default: 10, type: :numeric
26
26
  option :environment
27
27
  define_method 'db:create' do |handle|
28
28
  environment = ensure_environment(options)
@@ -1,5 +1,5 @@
1
1
  module Aptible
2
2
  module CLI
3
- VERSION = '0.7.4'.freeze
3
+ VERSION = '0.7.5'.freeze
4
4
  end
5
5
  end
@@ -7,9 +7,19 @@ describe Aptible::CLI::Agent do
7
7
 
8
8
  describe '#version' do
9
9
  it 'should print the version' do
10
- version = Aptible::CLI::VERSION
11
- expect(STDOUT).to receive(:puts).with "aptible-cli v#{version}"
12
- subject.version
10
+ ClimateControl.modify(APTIBLE_TOOLBELT: nil) do
11
+ version = Aptible::CLI::VERSION
12
+ expect(STDOUT).to receive(:puts).with "aptible-cli v#{version}"
13
+ subject.version
14
+ end
15
+ end
16
+
17
+ it 'should print the version (with toolbelt)' do
18
+ ClimateControl.modify(APTIBLE_TOOLBELT: '1') do
19
+ version = Aptible::CLI::VERSION
20
+ expect(STDOUT).to receive(:puts).with "aptible-cli v#{version} toolbelt"
21
+ subject.version
22
+ end
13
23
  end
14
24
  end
15
25
 
@@ -158,11 +168,72 @@ describe Aptible::CLI::Agent do
158
168
  end
159
169
  end
160
170
 
171
+ describe '#nag_toolbelt' do
172
+ let!(:work_dir) { Dir.mktmpdir }
173
+ after { FileUtils.remove_entry work_dir }
174
+ around { |example| ClimateControl.modify(HOME: work_dir) { example.run } }
175
+
176
+ let(:nag_dir) { File.join(work_dir, '.aptible') }
177
+ let(:nag_file) { File.join(nag_dir, 'nag_toolbelt') }
178
+
179
+ it 'warns if the nag file is not present' do
180
+ expect($stderr).to receive(:puts).at_least(:once)
181
+ subject.send(:nag_toolbelt)
182
+ expect(Integer(File.read(nag_file))).to be_within(5).of(Time.now.utc.to_i)
183
+ end
184
+
185
+ it 'warns if the nag file contains an old timestamp' do
186
+ Dir.mkdir(nag_dir)
187
+ File.open(nag_file, 'w') do |f|
188
+ f.write((Time.now.utc.to_i - 1.day).to_i.to_s)
189
+ end
190
+
191
+ expect($stderr).to receive(:puts).at_least(:once)
192
+ subject.send(:nag_toolbelt)
193
+ end
194
+
195
+ it 'does not warn if the nag file contains a recent timestamp' do
196
+ Dir.mkdir(nag_dir)
197
+ File.open(nag_file, 'w') do |f|
198
+ f.write((Time.now.utc.to_i - 3.hours).to_i.to_s)
199
+ end
200
+
201
+ expect($stderr).not_to receive(:puts)
202
+ subject.send(:nag_toolbelt)
203
+ end
204
+
205
+ it 'does not warn if the nag file contains a recent timestamp (newline)' do
206
+ # In case a customer writes to the nag file to disable the nag, they're
207
+ # likely to add a trailing newline. Let's just make sure we support that.
208
+ Dir.mkdir(nag_dir)
209
+ File.open(nag_file, 'w') do |f|
210
+ f.write("#{(Time.now.utc.to_i - 3.hours).to_i}\n")
211
+ end
212
+
213
+ expect($stderr).not_to receive(:puts)
214
+ subject.send(:nag_toolbelt)
215
+ end
216
+
217
+ it 'warns if the nag file contains an invalid timestamp' do
218
+ Dir.mkdir(nag_dir)
219
+ File.open(nag_file, 'w') { |f| f.write('foobar') }
220
+
221
+ expect($stderr).to receive(:puts).at_least(:once)
222
+ subject.send(:nag_toolbelt)
223
+ end
224
+
225
+ it 'is compatible with itself' do
226
+ expect($stderr).to receive(:puts).once
227
+ 2.times { subject.send(:nag_toolbelt) }
228
+ end
229
+ end
230
+
161
231
  context 'load' do
162
232
  it 'loads without git' do
163
233
  mocks = File.expand_path('../../../mock', __FILE__)
164
234
  bins = File.expand_path('../../../../bin', __FILE__)
165
- ClimateControl.modify PATH: [mocks, bins, ENV['PATH']].join(':') do
235
+ sep = File::PATH_SEPARATOR
236
+ ClimateControl.modify PATH: [mocks, bins, ENV['PATH']].join(sep) do
166
237
  _, _, status = Open3.capture3('aptible version')
167
238
  expect(status).to eq(0)
168
239
  end
@@ -1,9 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Aptible::CLI::Helpers::App::GitRemoteHandleStrategy do
4
- let!(:work_dir) { Dir.mktmpdir }
5
- after { FileUtils.remove_entry work_dir }
6
- around { |example| Dir.chdir(work_dir) { example.run } }
4
+ around do |example|
5
+ Dir.mktmpdir do |work_dir|
6
+ Dir.chdir(work_dir) { example.run }
7
+ end
8
+ end
7
9
 
8
10
  context 'with git repo' do
9
11
  before { `git init` }
@@ -4,7 +4,7 @@ describe Aptible::CLI::Helpers::Tunnel do
4
4
  include_context 'mock ssh'
5
5
 
6
6
  it 'forwards traffic to the remote port given by the server (1234)' do
7
- helper = described_class.new({}, ['ssh_mock.rb'])
7
+ helper = described_class.new({}, ['ssh'])
8
8
 
9
9
  helper.start(0)
10
10
  helper.stop
@@ -23,7 +23,7 @@ describe Aptible::CLI::Helpers::Tunnel do
23
23
  end
24
24
 
25
25
  it 'accepts a desired local port' do
26
- helper = described_class.new({}, ['ssh_mock.rb'])
26
+ helper = described_class.new({}, ['ssh'])
27
27
  helper.start(5678)
28
28
  helper.stop
29
29
 
@@ -35,13 +35,13 @@ describe Aptible::CLI::Helpers::Tunnel do
35
35
  end
36
36
 
37
37
  it 'captures and displays port discovery errors' do
38
- helper = described_class.new({ 'FAIL_PORT' => '1' }, ['ssh_mock.rb'])
38
+ helper = described_class.new({ 'FAIL_PORT' => '1' }, ['ssh'])
39
39
  expect { helper.start }
40
40
  .to raise_error(/Failed to request.*Something went wrong/m)
41
41
  end
42
42
 
43
43
  it 'captures and displays tunnel errors' do
44
- helper = described_class.new({ 'FAIL_TUNNEL' => '1' }, ['ssh_mock.rb'])
44
+ helper = described_class.new({ 'FAIL_TUNNEL' => '1' }, ['ssh'])
45
45
  expect { helper.start(0) }
46
46
  .to raise_error(/Tunnel did not come up.*Something went wrong/m)
47
47
  end
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ ruby.exe %cd%\spec\mock\ssh_mock.rb %*
@@ -9,7 +9,7 @@ shared_context 'mock ssh' do
9
9
  around do |example|
10
10
  mocks_path = File.expand_path('../../mock', __FILE__)
11
11
  env = {
12
- PATH: "#{mocks_path}:#{ENV['PATH']}",
12
+ PATH: "#{mocks_path}#{File::PATH_SEPARATOR}#{ENV['PATH']}",
13
13
  SSH_MOCK_OUTFILE: ssh_mock_outfile.path
14
14
  }
15
15
 
@@ -21,4 +21,10 @@ require 'aptible/cli'
21
21
 
22
22
  RSpec.configure do |config|
23
23
  config.before {}
24
+
25
+ # We make the CLI believe it's running in a toolbelt context to avoid running
26
+ # the toolbelt nag every time it initializes.
27
+ config.around(:each) do |example|
28
+ ClimateControl.modify(APTIBLE_TOOLBELT: '1') { example.run }
29
+ end
24
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aptible-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-03 00:00:00.000000000 Z
11
+ date: 2016-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aptible-api
@@ -222,6 +222,7 @@ files:
222
222
  - LICENSE.md
223
223
  - README.md
224
224
  - Rakefile
225
+ - appveyor.yml
225
226
  - aptible-cli.gemspec
226
227
  - bin/aptible
227
228
  - codecov.yml
@@ -266,6 +267,7 @@ files:
266
267
  - spec/fabricators/vhost_fabricator.rb
267
268
  - spec/mock/git
268
269
  - spec/mock/ssh
270
+ - spec/mock/ssh.bat
269
271
  - spec/mock/ssh_mock.rb
270
272
  - spec/shared/mock_ssh_context.rb
271
273
  - spec/spec_helper.rb
@@ -315,6 +317,7 @@ test_files:
315
317
  - spec/fabricators/vhost_fabricator.rb
316
318
  - spec/mock/git
317
319
  - spec/mock/ssh
320
+ - spec/mock/ssh.bat
318
321
  - spec/mock/ssh_mock.rb
319
322
  - spec/shared/mock_ssh_context.rb
320
323
  - spec/spec_helper.rb