Skip to content

Commit

Permalink
Return non-zero exit codes when something goes wrong
Browse files Browse the repository at this point in the history
  • Loading branch information
Flavio Auciello committed Apr 28, 2017
1 parent c0b2ce3 commit 018a129
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 40 deletions.
1 change: 1 addition & 0 deletions lib/pulsar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Pulsar
require 'fileutils'

require 'pulsar/context_error'
require 'pulsar/executor'
require 'pulsar/validator'
require 'pulsar/interactors/cleanup'
require 'pulsar/interactors/create_run_dirs'
Expand Down
13 changes: 13 additions & 0 deletions lib/pulsar/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

module Pulsar
class CLI < Thor
def self.exit_on_failure?; true; end

map %w[--version -v] => :__print_version

desc 'install [DIRECTORY]', 'Install initial repository in DIRECTORY'
Expand All @@ -20,9 +22,11 @@ def install(directory = './pulsar-conf')

if result.success?
puts 'Successfully created intial repo!'
exit_with_status 0
else
puts 'Failed to create intial repo.'
puts result.error
exit_with_status result.error.is_a?(Pulsar::ContextError) ? result.error.exit_code : 1
end
end

Expand All @@ -40,9 +44,11 @@ def list
result.applications.each do |app, stages|
puts "#{app}: #{stages.join(', ')}"
end
exit_with_status 0
else
puts 'Failed to list application and environments.'
puts result.error
exit_with_status result.error.is_a?(Pulsar::ContextError) ? result.error.exit_code : 1
end
end

Expand All @@ -62,19 +68,26 @@ def deploy(application, environment)

if result.success?
puts "Deployed #{application} on #{environment}!"
exit_with_status 0
else
puts "Failed to deploy #{application} on #{environment}."
puts result.error
exit_with_status result.error.is_a?(Pulsar::ContextError) ? result.error.exit_code : 1
end
end

desc "--version, -v", "print the version"
def __print_version
puts Pulsar::VERSION
exit_with_status 0
end

private

def exit_with_status(status)
exit status
end

def load_config
Dotenv.load(PULSAR_CONF) # Load configurations for Pulsar
end
Expand Down
6 changes: 6 additions & 0 deletions lib/pulsar/context_error.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module Pulsar
class ContextError < StandardError
attr_reader :exit_code
def initialize(obj, exit_code)
super obj
@exit_code = exit_code
end

def to_s
backtrace ? backtrace.unshift(super).join("\n") : super
end
Expand Down
18 changes: 18 additions & 0 deletions lib/pulsar/executor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'open3'

module Pulsar
module Executor
def self.sh(cmd)
stdin_stream, stdout_stream, stderr_stream, wait_thr = Open3.popen3(cmd)
stdout = stdout_stream.gets(nil) || ""
stderr = stderr_stream.gets(nil) || ""
stdout_stream.close
stderr_stream.gets(nil)
stderr_stream.close
stdin_stream.close
exit_code = wait_thr.value
yield exit_code, stdout, stderr if block_given?
{ status: exit_code.exitstatus, output: stdout + stderr }
end
end
end
2 changes: 1 addition & 1 deletion lib/pulsar/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def validate_context!
end

def context_fail!(msg)
context.fail! error: Pulsar::ContextError.new(msg)
context.fail! error: Pulsar::ContextError.new(msg, 1)
end

def validable_properties
Expand Down
51 changes: 33 additions & 18 deletions spec/features/deploy_spec.rb
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
require 'spec_helper'

RSpec.describe 'Deploy' do
subject { -> { command } }
subject { command_output }

let(:command) do
`DRY_RUN=true #{RSpec.configuration.pulsar_command} deploy #{options} #{arguments}`
Pulsar::Executor.sh("DRY_RUN=true #{RSpec.configuration.pulsar_command} deploy #{options} #{arguments}")
end

let(:repo) { RSpec.configuration.pulsar_conf_path }
let(:options) { "--conf-repo #{repo}" }
let(:app) { 'blog' }
let(:environment) { 'production' }
let(:arguments) { "#{app} #{environment}" }
let(:command_output) { command[:output] }
let(:exit_status) { command[:status] }
let(:repo) { RSpec.configuration.pulsar_conf_path }
let(:options) { "--conf-repo #{repo}" }
let(:app) { 'blog' }
let(:environment) { 'production' }
let(:arguments) { "#{app} #{environment}" }

context 'via a subcommand named deploy' do
let(:error) { /Could not find command/ }

it { is_expected.not_to output(error).to_stderr_from_any_process }
it { is_expected.not_to match(error) }
it { expect(exit_status).to eq(0) }
end

context 'requires a --conf-repo option' do
let(:options) { nil }
let(:error) { /No value provided for required options '--conf-repo'/ }

it { is_expected.to output(error).to_stderr_from_any_process }
it { is_expected.to match(error) }

context 'can be specified via the alias -c' do
let(:options) { "-c #{repo}" }

it { is_expected.not_to output(error).to_stderr_from_any_process }
it { is_expected.not_to match(error) }
it { expect(exit_status).to eq(0) }
end

context 'can be specified via the environment variable PULSAR_CONF_REPO' do
before { ENV['PULSAR_CONF_REPO'] = repo }

it { is_expected.not_to output(error).to_stderr_from_any_process }
it { is_expected.not_to match(error) }
it { expect(exit_status).to eq(0) }
end
end

Expand All @@ -43,11 +47,12 @@
let(:environment) { nil }
let(:error) { /Usage: "pulsar deploy APPLICATION ENVIRONMENT"/ }

it { is_expected.to output(error).to_stderr_from_any_process }
it { is_expected.to match(error) }
it { expect(exit_status).to eq(1) }
end

context 'when succeeds' do
subject { command }
subject { command_output }

context 'deploys an application on a environment in the pulsar configuration' do
let(:output) { "Deployed blog on production!\n" }
Expand All @@ -60,11 +65,12 @@
end

it { is_expected.to match(output) }
it { expect(exit_status).to eq(0) }

context 'leaves the tmp folder empty' do
subject { Dir.glob("#{Pulsar::PULSAR_TMP}/*") }

before { command }
before { command_output }

it { is_expected.to be_empty }
end
Expand All @@ -77,11 +83,12 @@
let(:output) { "Deployed your_app on staging!\n" }

it { is_expected.to match(output) }
it { expect(exit_status).to eq(0) }

context 'leaves the tmp folder empty' do
subject { Dir.glob("#{Pulsar::PULSAR_TMP}/*") }

before { command }
before { command_output }

it { is_expected.to be_empty }
end
Expand All @@ -94,11 +101,12 @@
let(:output) { "Deployed your_app on staging!\n" }

it { is_expected.to match(output) }
it { expect(exit_status).to eq(0) }

context 'leaves the tmp folder empty' do
subject { Dir.glob("#{Pulsar::PULSAR_TMP}/*") }

before { command }
before { command_output }

it { is_expected.to be_empty }
end
Expand All @@ -107,31 +115,35 @@
end

context 'when fails' do
subject { command }
subject { command_output }

context 'because of wrong directory' do
let(:repo) { './some-wrong-directory' }

it { is_expected.to match("Failed to deploy blog on production.\n") }
it { expect(exit_status).to eq(1) }
end

context 'because of empty directory' do
let(:repo) { RSpec.configuration.pulsar_empty_conf_path }

it { is_expected.to match("Failed to deploy blog on production.\n") }
it { is_expected.to match "No application found on repository #{RSpec.configuration.pulsar_empty_conf_path}\n" }
it { expect(exit_status).to eq(1) }
end

context 'because Bundler failed' do
let(:repo) { RSpec.configuration.pulsar_wrong_bundle_conf_path }

it { is_expected.to match("Failed to deploy blog on production.\n") }
it { expect(exit_status).to eq(1) }
end

context 'because Capistrano failed' do
let(:repo) { RSpec.configuration.pulsar_wrong_cap_conf_path }

it { is_expected.to match("Failed to deploy blog on production.\n") }
it { expect(exit_status).to eq(1) }
end

context 'because the application does not exists in the repository' do
Expand All @@ -140,6 +152,7 @@
let(:environment) { 'staging' }

it { is_expected.to match("The application foobuzz does not exist in your repository") }
it { expect(exit_status).to eq(1) }
end

context 'because the environment does not exists for the application' do
Expand All @@ -148,11 +161,13 @@
let(:environment) { 'foobuzz' }

it { is_expected.to match("The application blog does not have an environment called foobuzz") }
it { expect(exit_status).to eq(1) }

context 'but \'no application error\' message takes precedence' do
let(:app) { 'foobuzz' }

it { is_expected.to match("The application foobuzz does not exist in your repository") }
it { expect(exit_status).to eq(1) }
end
end
end
Expand Down
18 changes: 12 additions & 6 deletions spec/features/install_spec.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
require 'spec_helper'

RSpec.describe 'Install' do
subject { command }
subject { command_output }

let(:command) do
`#{RSpec.configuration.pulsar_command} install #{arguments}`
Pulsar::Executor.sh("#{RSpec.configuration.pulsar_command} install #{arguments}")
end
let(:command_output) { command[:output] }
let(:exit_status) { command[:status] }

let(:arguments) { nil }

context 'via a subcommand named install' do
subject { -> { command } }
subject { -> { command_output } }

let(:error) { /Could not find command/ }

it { is_expected.not_to output(error).to_stderr_from_any_process }
it { expect(exit_status).to eq(0) }
end

context 'when succeeds' do
it { is_expected.to eql "Successfully created intial repo!\n" }

context 'creates a directory' do
subject { -> { command } }
subject { -> { command_output } }

it { expect(exit_status).to eq(0) }

context 'with the basic configuration' do
subject(:initial_pulsar_repo) do
Dir.entries('./../../../lib/pulsar/generators/initial_repo/')
end

before { command }
before { command_output }

it 'contains the initial directory structure' do
is_expected.to eql Dir.entries('./pulsar-conf')
Expand Down Expand Up @@ -58,9 +63,10 @@
it { is_expected.to match "Failed to create intial repo.\n" }

context 'does not create a directory' do
subject { -> { command } }
subject { -> { command_output } }

it { is_expected.not_to change { File.exist?('./my-dir') }.from(false) }
it { expect(exit_status).to eq(1) }
end
end
end
Loading

0 comments on commit 018a129

Please sign in to comment.