brightpearl-cli 2.5.0 → 2.6.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.
@@ -25,9 +25,18 @@ module AppCommand
25
25
  # Updates the current branch.
26
26
  # @return void
27
27
  def update_branch_single
28
+ release_error_code = false
28
29
  @git.check_for_uncommitted_files(true)
29
30
  @git.repo_loop.each do |repo_dir|
30
31
  current_branch = @git.current_branch_for_repo(repo_dir)
32
+
33
+ # Skip if this is a release branch.
34
+ if current_branch =~ App::Git::RELEASE_BRANCH_REGEX
35
+ App::Terminal::warning("#{App::Terminal::format_directory(@git.get_repo_shorthand(repo_dir))} is on a #{App::Terminal::format_highlight('release branch', true)}", ['Cannot perform update.'], release_error_code ? false : true)
36
+ release_error_code = true
37
+ next
38
+ end
39
+
31
40
  commands = Array.new
32
41
  if current_branch != App::Git::MASTER
33
42
  commands << "git checkout #{App::Git::MASTER}"
@@ -27,6 +27,8 @@ module AppCommand
27
27
 
28
28
  App::Terminal::info('Running branch cleaner', "Gathering list of #{App::Terminal::format_highlight('local')} branches where last commit was #{App::Terminal::format_highlight('more than 1 month ago')}")
29
29
 
30
+ sleep(1)
31
+
30
32
  branches_code, branches_db = get_historic_branches
31
33
  umc_branches = get_unmerged_commit_branches(branches_code, branches_db)
32
34
  fnl_branches_cd, fnl_branches_db = get_final_branches(branches_code, branches_db, umc_branches)
@@ -36,25 +38,25 @@ module AppCommand
36
38
  atleast_one_error = false
37
39
 
38
40
  if umc_branches.any?
39
- App::Terminal::warning("The following branches have commits which #{App::Terminal::format_invalid('have not been merged to', true)} #{App::Terminal::format_branch(App::Git::MASTER)}", umc_branches, false)
41
+ App::Terminal::warning("The following branches have commits which have not been merged to #{App::Terminal::format_branch(App::Git::MASTER)}", umc_branches, false)
40
42
  atleast_one_error = true
41
43
  end
42
44
 
43
45
  unless fnl_branches_cd.any? || fnl_branches_db.any?
44
- App::Terminal::info('No branches to delete', ["The script found no branches which are #{App::Terminal::format_action('eligible for deletion')}.","All branches on your system have either a #{App::Terminal::format_highlight('commit within the last month')} or a #{App::Terminal::format_highlight('commit not in')} #{App::Terminal::format_branch(App::Git::MASTER)}."])
46
+ App::Terminal::info('No branches to delete', ['The script found no branches which are eligible for deletion.', "All branches on your system have either a #{App::Terminal::format_highlight('commit within the last month')} or a #{App::Terminal::format_highlight('commit not in')} #{App::Terminal::format_branch(App::Git::MASTER)}."])
45
47
  exit
46
48
  end
47
49
 
48
50
  if atleast_one_error
49
51
  unless App::Terminal::prompt_yes_no('Continue by skipping these branches?', ["The above branch(es) have unmerged commits and will be #{App::Terminal::format_action('skipped')} in the removal process.", "You #{App::Terminal::format_invalid('cannot delete', true)} these branches using this script, this must be done manually #{App::Terminal::format_highlight('afterwards')}."])
50
- App::Terminal::abort(nil, nil, true, false)
52
+ App::Terminal::abort
51
53
  end
52
54
  end
53
55
 
54
56
  @git.show_branches_draw_table(fnl_branches_cd, fnl_branches_db)
55
57
 
56
58
  unless App::Terminal::prompt_yes_no('Remove these branches?', ["By continuing, the above branches will be #{App::Terminal::format_action('removed permanently')} both #{App::Terminal::format_highlight('locally & remotely')} (except release branches)."], 'Are you absolutely sure you want to continue?', false)
57
- App::Terminal::abort(nil, nil, true, false)
59
+ App::Terminal::abort
58
60
  end
59
61
 
60
62
  repo_cd = App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_CODE)
@@ -132,18 +134,14 @@ module AppCommand
132
134
  branches_code.each do |code_branch|
133
135
  missing_commits = App::Terminal::command_capture("git log origin/master..origin/#{code_branch[:"#{App::Git::REFNAME}"]}", App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_CODE), true, false)
134
136
  if missing_commits[0] != ''
135
- missing_commits[0].split("\n").each do |line|
136
- App::Terminal::output(line, App::Terminal::MSG_WARNING)
137
- end
137
+ parse_missing_commits(missing_commits[0])
138
138
  branches_unmerged_commits << code_branch[:"#{App::Git::REFNAME}"]
139
139
  end
140
140
  end
141
141
  branches_db.each do |db_branch|
142
142
  missing_commits = App::Terminal::command_capture("git log origin/master..origin/#{db_branch[:"#{App::Git::REFNAME}"]}", App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_DB), true, false)
143
143
  if missing_commits[0] != ''
144
- missing_commits[0].split("\n").each do |line|
145
- App::Terminal::output(line, App::Terminal::MSG_WARNING)
146
- end
144
+ parse_missing_commits(missing_commits[0])
147
145
  branches_unmerged_commits << db_branch[:"#{App::Git::REFNAME}"]
148
146
  end
149
147
  end
@@ -152,6 +150,42 @@ module AppCommand
152
150
  branches_unmerged_commits
153
151
  end
154
152
 
153
+ # Returns array where [0] is the branch_name and [1] is an array of missing commit messages
154
+ # @return Array
155
+ def parse_missing_commits(missing_commits)
156
+ counter = false
157
+ hash = ''
158
+ missing_commits.split("\n").each do |line|
159
+
160
+ if counter != false
161
+ unless line.strip =~ /\AMerge:\s\w{7}\s\w{7}/i
162
+ counter = counter + 1
163
+ end
164
+ end
165
+
166
+ if counter == 4
167
+ commit_msg = nil
168
+ if line.strip != ''
169
+
170
+ match = line.strip.match(/bp-\d{4,5}/i)
171
+ line.gsub!(match.to_s, "\x1B[38;5;196m#{match.to_s}\x1B[38;5;246m") if match
172
+
173
+ commit_msg = "\xe2\x80\x94 \x1B[38;5;246m#{line.strip}\x1B[0m"
174
+ end
175
+ App::Terminal::output("\x1B[38;5;240m[\x1B[38;5;221m#{hash}\x1B[38;5;240m]\x1B[0m #{commit_msg}", App::Terminal::MSG_CUSTOM, ' Un-merged ', 238)
176
+ counter = false
177
+ hash = ''
178
+ end
179
+
180
+ if line.strip =~ /\Acommit\s\w{40}\z/i
181
+ line_split = line.strip.split(' ')
182
+ counter = 0
183
+ hash = line_split[1]
184
+ end
185
+
186
+ end
187
+ end
188
+
155
189
  # Gets final array of branches which are safe to delete.
156
190
  # @return Array
157
191
  def get_final_branches(branches_code, branches_db, umc_branches)
@@ -9,6 +9,8 @@ module AppCommand
9
9
 
10
10
  @git = App::Git.new
11
11
 
12
+ App::Terminal::info('Running PHP Sonar (CodeSniffer)')
13
+
12
14
  opts_validate
13
15
  opts_routing
14
16
 
@@ -16,6 +18,8 @@ module AppCommand
16
18
 
17
19
  def opts_validate
18
20
 
21
+ check_phpcs_is_installed
22
+
19
23
  end
20
24
 
21
25
  def opts_routing
@@ -26,7 +30,6 @@ module AppCommand
26
30
 
27
31
  def run_sonar
28
32
 
29
- App::Terminal::info('Running PHP Sonar (CodeSniffer)')
30
33
  space_inserted = false
31
34
  file_found_to_scan = false
32
35
 
@@ -48,7 +51,7 @@ module AppCommand
48
51
 
49
52
  unless file_found_to_scan
50
53
  if changed_files[0] == '' && changed_files[1].nil?
51
- App::Terminal::info("No files to scan. #{App::Terminal::format_highlight('No files changed')} between #{App::Terminal::format_branch(@git.current_branch_for_repo(App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_CODE)))} and #{App::Terminal::format_branch("origin/#{App::Git::MASTER}")}")
54
+ App::Terminal::info("No files to scan. #{App::Terminal::format_highlight('No files changed')} in #{App::Terminal::format_directory("#{@git.get_repo_shorthand(App::Config.param(ConfigUnique::WORKSTATION_PATH_TO_BP_CODE))}/brightpearl/private/library/Lib")} between #{App::Terminal::format_branch(@git.current_branch_for_repo(App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_CODE)))} and #{App::Terminal::format_branch("origin/#{App::Git::MASTER}")}")
52
55
  else
53
56
  App::Terminal::info("No files to scan. #{App::Terminal::format_highlight('The only files changed')} between #{App::Terminal::format_branch(@git.current_branch_for_repo(App::Config.param(App::Config::WORKSTATION_PATH_TO_BP_CODE)))} and #{App::Terminal::format_branch("origin/#{App::Git::MASTER}")} are:", changed_files[0].split("\n"))
54
57
  end
@@ -87,6 +90,17 @@ module AppCommand
87
90
 
88
91
  end
89
92
 
93
+ private
94
+
95
+ def check_phpcs_is_installed
96
+ App::Terminal::output("Checking if #{App::Terminal::format_highlight('phpcs')} is installed...")
97
+ result = App::Terminal::command_capture('phpcs --version', nil, false, false)
98
+ result = result[0].split(' ')
99
+ unless result[0].downcase == 'php_codesniffer'
100
+ App::Terminal::error("#{App::Terminal::format_highlight('phpcs')} is not installed")
101
+ end
102
+ end
103
+
90
104
  end
91
105
 
92
106
  end
data/lib/routes/ssh.rb CHANGED
@@ -16,47 +16,6 @@ module AppCommand
16
16
 
17
17
  def opts_validate
18
18
 
19
- if @args[0].nil?
20
- App::Terminal::error('You must specify what server you want to SSH into', "This must be specified in: #{App::Terminal::format_directory(ConfigUnique::CONFIG_FILE)}", true)
21
- end
22
-
23
- if @args[0] =~ /\Assh_\S+\z/i
24
- config_param = @args[0]
25
- else
26
- config_param = "#{CONFIGURATION_PREFIX}#{@args[0]}"
27
- end
28
-
29
- unless App::Config::param_exists(config_param)
30
- App::Terminal::error('Invalid Config Parameter', "The #{App::Terminal::format_highlight('config parameter')} #{App::Terminal::format_invalid(config_param)} doesn't exist in: #{App::Terminal::format_directory(ConfigUnique::CONFIG_FILE)}", true)
31
- end
32
-
33
- ssh_parts = App::Config.param(config_param).split('|')
34
-
35
- @ssh_user = ssh_parts[0]
36
- @ssh_host = ssh_parts[1]
37
- @ssh_cert = ssh_parts[2].to_s.strip.length == 0 ? nil : ssh_parts[2]
38
-
39
- help_message = [
40
- "The file: #{App::Terminal::format_directory(ConfigUnique::CONFIG_FILE)} must contain a line similar to the following:",
41
- nil,
42
- 'ssh_ec2=ec2-user|ec2-XX-XX-XX-XX.eu-west-1.compute.amazonaws.com|~/.ssh/pem-key.pem',
43
- 'ssh_ec2=ec2-user|ec2-XX-XX-XX-XX.eu-west-1.compute.amazonaws.com',
44
- ]
45
-
46
- if @ssh_user.nil? || @ssh_user == ''
47
- App::Terminal::error("SSH #{App::Terminal::format_highlight('user')} required", help_message, true)
48
- end
49
-
50
- if @ssh_host.nil? || @ssh_host == ''
51
- App::Terminal::error("SSH #{App::Terminal::format_highlight('host')} required", help_message, true)
52
- end
53
-
54
- unless @ssh_cert.nil?
55
- unless App::UtilsFiles::file_exists(File.expand_path(@ssh_cert))
56
- App::Terminal::error("PEM key not found: #{App::Terminal::format_directory(@ssh_cert)}")
57
- end
58
- end
59
-
60
19
  end
61
20
 
62
21
  def opts_routing
@@ -67,11 +26,7 @@ module AppCommand
67
26
 
68
27
  def ssh_into_server
69
28
 
70
- if @ssh_cert.nil?
71
- App::Terminal::command("ssh #{@ssh_user}@#{@ssh_host}", nil, false, false)
72
- else
73
- App::Terminal::command("ssh -i #{@ssh_cert} #{@ssh_user}@#{@ssh_host}", nil, false, false)
74
- end
29
+ App::SSH::ssh_into_remote(@args[0])
75
30
 
76
31
  end
77
32
 
data/lib/routes/tail.rb CHANGED
@@ -2,10 +2,17 @@ module AppCommand
2
2
 
3
3
  class Tail < ::Convoy::ActionCommand::Base
4
4
 
5
+ DIR_CATALINA = ' /var/log/tomcat/*/catalina.out'
6
+ DIR_ACCESS = ' /var/log/tomcat/*/access*'
7
+
5
8
  def execute
6
9
 
7
10
  @opts = command_options
8
11
  @args = arguments
12
+
13
+ @ssh_user = App::Config.param(ConfigUnique::VM_USER)
14
+ @ssh_host = App::Config.param(ConfigUnique::VM_IP)
15
+
9
16
  opts_validate
10
17
  opts_routing
11
18
 
@@ -13,32 +20,39 @@ module AppCommand
13
20
 
14
21
  def opts_validate
15
22
 
16
- end
17
-
18
- def opts_routing
23
+ if App::UtilsRoutes::flags_set(@opts) == 0
24
+ App::Terminal::error('You must specify a flag', nil, true)
25
+ end
19
26
 
20
- tail_all_catalina_out
27
+ if App::UtilsRoutes::flags_set(@opts) > 1
28
+ App::Terminal::error('Too many flags', "You cannot pass the #{App::Terminal::format_flag('c', false)} and #{App::Terminal::format_flag('a', false)} flags at the same time.", true)
29
+ end
21
30
 
22
31
  end
23
32
 
24
- def tail_all_catalina_out
33
+ def opts_routing
25
34
 
26
- if App::Tools::this_is_a_mac
35
+ tail_catalina_out if @opts[:catalina]
36
+ tail_access if @opts[:access]
37
+ tail_php if @opts[:php]
38
+ tail_phpunit if @opts[:phpunit]
27
39
 
28
- begin
29
- system('clear')
30
- App::Terminal::info("Tailing #{App::Terminal::format_action('all')} Java logs", ['tail -f /var/log/tomcat/*/catalina.out | grep -v "scheduling\|/var/log\|rabbitmq\|Clearing app version/service version cache\|^$"', nil, "Press '#{App::Terminal::format_command('CTRL + C')}\x1B[38;5;240m' to quit."])
31
- system("sshpass -p#{App::Config.param(App::Config::VM_USER_PASSWORD)} ssh #{App::Config.param(App::Config::VM_USER)}@#{App::Config.param(App::Config::VM_IP)} 'tail -f /var/log/tomcat/*/catalina.out | grep -v \"scheduling\\|/var/log\\|rabbitmq\\|Clearing app version/service version cache\\|^$\"'")
32
- ensure
33
- exit
34
- end
40
+ end
35
41
 
36
- else
42
+ def tail_catalina_out
43
+ App::SSH::run_script_on_remote_credentials(@ssh_user, @ssh_host, nil, 'tail-catalina.sh')
44
+ end
37
45
 
38
- App::Terminal::info('This functionality has not yet been implemented on your OS', ["Currently only works on #{App::Terminal::format_action(App::Config.param(App::Config::WORKSTATION_OS))}", nil, "You are on #{App::Terminal::format_action(App::Config.param(App::Config::WORKSTATION_OS))}"])
46
+ def tail_access
47
+ App::SSH::run_script_on_remote_credentials(@ssh_user, @ssh_host, nil, 'tail-access.sh')
48
+ end
39
49
 
40
- end
50
+ def tail_php
51
+ App::SSH::run_script_on_remote_credentials(@ssh_user, @ssh_host, nil, 'tail-php.sh')
52
+ end
41
53
 
54
+ def tail_phpunit
55
+ App::SSH::run_script_on_remote_credentials(@ssh_user, @ssh_host, nil, 'tail-phpunit.sh')
42
56
  end
43
57
 
44
58
  end
data/lib/routes/test.rb CHANGED
@@ -13,17 +13,11 @@ module AppCommand
13
13
 
14
14
  def opts_validate
15
15
 
16
- opts_set = 0
17
- opts_set = opts_set + 1 if @opts[:cucumber]
18
- opts_set = opts_set + 1 if @opts[:fitnesse]
19
- opts_set = opts_set + 1 if @opts[:php]
20
- opts_set = opts_set + 1 if @opts[:php_local]
21
- opts_set = opts_set + 1 if @opts[:ruby]
22
-
23
- if opts_set >= 2
24
- puts "You can only run one set of tests at a time. Please set only 1 one of the following flags: \x1B[90m-c, -f, -p, -P, -r\x1B[0m"
25
- exit
26
- elsif opts_set == 0
16
+ flags_set = App::UtilsRoutes::flags_set(@opts)
17
+
18
+ if flags_set >= 2
19
+ App::Terminal::error('You can only run one set of tests at a time', "Please set only 1 one of the following flags: #{App::Terminal::format_flag('c', false)}, #{App::Terminal::format_flag('f', false)},#{App::Terminal::format_flag('p', false)},#{App::Terminal::format_flag('b', false)},#{App::Terminal::format_flag('r', false)}", true)
20
+ elsif flags_set == 0
27
21
  @opts[:php] = true
28
22
  end
29
23
 
@@ -35,8 +29,10 @@ module AppCommand
35
29
  run_cucumber
36
30
  elsif @opts[:fitnesse]
37
31
  run_fitnesse
38
- elsif @opts[:php] || @opts[:php_local]
32
+ elsif @opts[:php]
39
33
  run_php
34
+ elsif @opts[:behat]
35
+ run_behat
40
36
  elsif @opts[:ruby]
41
37
  run_ruby
42
38
  end
@@ -45,38 +41,34 @@ module AppCommand
45
41
 
46
42
  def run_cucumber
47
43
 
44
+ App::Terminal::info('Not yet implemented')
45
+
48
46
  end
49
47
 
50
48
  def run_fitnesse
51
49
 
50
+ App::Terminal::info('Not yet implemented')
51
+
52
52
  end
53
53
 
54
54
  def run_php
55
55
 
56
- if @opts[:php]
57
-
58
- App::Terminal::info('Running PHPUnit tests on VM')
59
-
60
- commands = [
61
- "sshpass -p#{App::Config.param(App::Config::VM_USER_PASSWORD)} ssh #{App::Config.param(App::Config::VM_USER)}@#{App::Config.param(App::Config::VM_IP)} 'cd /brightpearl-source/brightpearl-code/brightpearl/private/tests/ && ./phpunit.sh #{@args.join(' ')}'"
62
- ]
63
- App::Terminal::command(commands, nil, false)
56
+ App::Terminal::info("Running #{App::Terminal::format_action('PHPUnit Tests')} on VM \xe2\x80\x94 #{App::Terminal::format_highlight("#{App::Config.param(ConfigUnique::VM_IP)}")}")
57
+ App::SSH::run_script_on_remote('vm', 'run-phpunit-tests.sh', @args)
64
58
 
65
- elsif @opts[:php_local]
66
-
67
- App::Terminal::warning('Running PHPUnit tests on Workstation', "This isn't fully functioning yet.")
59
+ end
68
60
 
69
- commands = [
70
- "phpunit --bootstrap #{App::Enum::get_base_path}/assets/phpunit/bootstrap.php"
71
- ]
72
- App::Terminal::command(commands, "#{App::Config.param(ConfigUnique::WORKSTATION_PATH_TO_BP_CODE)}/brightpearl/private/tests", false)
61
+ def run_behat
73
62
 
74
- end
63
+ App::Terminal::info("Running #{App::Terminal::format_action('Behat Tests')} on VM \xe2\x80\x94 #{App::Terminal::format_highlight("#{App::Config.param(ConfigUnique::VM_IP)}")}")
64
+ App::SSH::run_script_on_remote('vm', 'run-behat-tests.sh', $args)
75
65
 
76
66
  end
77
67
 
78
68
  def run_ruby
79
69
 
70
+ App::Terminal::info('Not yet implemented')
71
+
80
72
  end
81
73
 
82
74
  end
data/lib/version.rb CHANGED
@@ -1 +1 @@
1
- VERSION = '2.5.0'
1
+ VERSION = '2.6.0'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ mysql -e "SELECT @@GLOBAL.sql_mode; SET @@GLOBAL.sql_mode=(SELECT REPLACE(@@GLOBAL.sql_mode,'STRICT_TRANS_TABLES','')); SELECT @@GLOBAL.sql_mode;"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ cd /brightpearl-source/brightpearl-code/brightpearl/private/tests
4
+
5
+ composer dump-autoload
6
+
7
+ ./behat.sh
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+
3
+ cd /brightpearl-source/brightpearl-code/brightpearl/private/tests
4
+
5
+ ./phpunit.sh $1
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ tail -f /var/log/tomcat/*/access* | grep -v "^$\|get-status-check\|post-internal-service\|has not started because it is suspended\|::1 XFF" | grep -v "==> /var/log/"
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ tail -f /var/log/tomcat/*/catalina.out | grep -v "scheduling\|/var/log\|rabbitmq\|Clearing app version/service version cache\|^$"
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ tail -f /var/log/php/php.log | grep -v "NOTICE"
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ tail -f /tmp/phpunit.error.log
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brightpearl-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert Rannetsperger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-14 00:00:00.000000000 Z
11
+ date: 2015-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: columnist
@@ -128,15 +128,15 @@ files:
128
128
  - lib/core/mysql.rb
129
129
  - lib/core/pom.rb
130
130
  - lib/core/sql_update.rb
131
+ - lib/core/ssh.rb
131
132
  - lib/core/terminal.rb
132
133
  - lib/core/tools.rb
133
134
  - lib/core/utils_files.rb
134
135
  - lib/core/utils_routes.rb
135
136
  - lib/core/utils_strings.rb
137
+ - lib/core/utils_tools.rb
136
138
  - lib/core/validate.rb
137
- - lib/core/vm.rb
138
139
  - lib/routes/build.rb
139
- - lib/routes/dummy_order.rb
140
140
  - lib/routes/fix.rb
141
141
  - lib/routes/git_branch.rb
142
142
  - lib/routes/git_checkout.rb
@@ -162,7 +162,13 @@ files:
162
162
  - lib/routes/test.rb
163
163
  - lib/routes/update.rb
164
164
  - lib/version.rb
165
- - vm-scripts/sql-updates.sh
165
+ - vm-scripts/fix-sql-mode.sh
166
+ - vm-scripts/run-behat-tests.sh
167
+ - vm-scripts/run-phpunit-tests.sh
168
+ - vm-scripts/tail-access.sh
169
+ - vm-scripts/tail-catalina.sh
170
+ - vm-scripts/tail-php.sh
171
+ - vm-scripts/tail-phpunit.sh
166
172
  - bin/bp
167
173
  - bin/brightpearl
168
174
  homepage: http://rubygems.org/gems/brightpearl-cli