aptible-cli 0.7.4 → 0.7.5

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: 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