Skip to content

Commit

Permalink
Merge branch 'feat/dry-run'
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Jun 16, 2021
2 parents 1c1c7ac + 9d39d5e commit 9b08529
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 19 deletions.
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ Options:
# The pacticipant version. Must be entered after the --pacticipant that it relates to.
[--ignore=IGNORE]
# The pacticipant name to ignore. Use once for each pacticipant being ignored.
A specific version can be ignored by also specifying a --version after the pacticipant name option.
A specific version can be ignored by also specifying a --version after the
pacticipant name option.
-l, [--latest=[TAG]]
# Use the latest pacticipant version. Optionally specify a TAG to use the
latest version with the specified tag.
Expand All @@ -103,6 +104,9 @@ Options:
# The time between retries in seconds. Use in conjuction with --retry-while-unknown
# Default: 10
[--dry-run], [--no-dry-run]
# When enabled, always exits process with a success code. Can also be enabled by setting
the environment variable PACT_BROKER_CAN_I_DEPLOY_DRY_RUN=true.
-b, --broker-base-url=BROKER_BASE_URL
# The base URL of the Pact Broker
-u, [--broker-username=BROKER_USERNAME]
Expand All @@ -113,14 +117,6 @@ Options:
# Pact Broker bearer token
-v, [--verbose], [--no-verbose]
# Verbose output. Default: false
Description:
Returns exit code 0 or 1, indicating whether or not the specified application (pacticipant) versions are
compatible (ie. safe to deploy). Prints out the relevant pact/verification details, indicating any
missing or failed verification results.
The environment variables PACT_BROKER_BASE_URL, PACT_BROKER_USERNAME and PACT_BROKER_PASSWORD may be used
instead of their respective command line options.
```

Returns exit code 0 or 1, indicating whether or not the specified application (pacticipant) versions are compatible (ie. safe to deploy). Prints out the relevant pact/verification details, indicating any missing or failed verification results.
Expand Down
45 changes: 40 additions & 5 deletions lib/pact_broker/client/can_i_deploy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def initialize(pact_broker_base_url, version_selectors, matrix_options, options,
def call
create_result(fetch_matrix_with_retries)
rescue PactBroker::Client::Error => e
Result.new(false, Term::ANSIColor.red(e.message))
Result.new(dry_run_or_false, for_dry_run(Term::ANSIColor.red(e.message)))
rescue StandardError => e
Result.new(false, "Error retrieving matrix. #{e.class} - #{e.message}\n#{e.backtrace.join("\n")}")
Result.new(dry_run_or_false, for_dry_run(Term::ANSIColor.red("Error retrieving matrix. #{e.class} - #{e.message}") + "\n#{e.backtrace.join("\n")}"))
end

private
Expand All @@ -46,26 +46,44 @@ def create_result(matrix)
if matrix.deployable?
Result.new(true, success_message(matrix))
else
Result.new(false, failure_message(matrix))
Result.new(dry_run_or_false, failure_message(matrix))
end
end

def success_message(matrix)
message = format_matrix(matrix)
if format != 'json'
message = warning(matrix) + Term::ANSIColor.green('Computer says yes \o/ ') + message + "\n\n" + notice_or_reason(matrix, :green)
message = warning(matrix) + computer_says(true) + message + "\n\n" + notice_or_reason(matrix, :green)
message = for_dry_run(message)
end
message
end

def failure_message(matrix)
message = format_matrix(matrix)
if format != 'json'
message = warning(matrix) + Term::ANSIColor.red('Computer says no ¯\_(ツ)_/¯ ') + message + "\n\n" + notice_or_reason(matrix, :red)
message = warning(matrix) + computer_says(false) + message + "\n\n" + notice_or_reason(matrix, :red)
message = for_dry_run(message)
end
message
end

def computer_says(success)
if success
if dry_run?
"Computer says yes \\o/ (and maybe you don't need to enable dry run)"
else
Term::ANSIColor.green('Computer says yes \o/ ')
end
else
if dry_run?
"Computer says no ¯\\_(ツ)_/¯ (but you're ignoring this by enabling dry run)"
else
Term::ANSIColor.red("Computer says no ¯\_(ツ)_/¯")
end
end
end

def notice_or_reason(matrix, reason_color)
if matrix.notices
PactBroker::Client::ColorizeNotices.call(matrix.notices).join("\n")
Expand Down Expand Up @@ -114,6 +132,23 @@ def retry_while_unknown?
options[:retry_while_unknown] > 0
end

def dry_run?
options[:dry_run]
end

def dry_run_or_false
dry_run? || false
end

def for_dry_run(lines)
if dry_run?
prefix = Term::ANSIColor.yellow("[dry-run] ")
lines.split("\n").collect { |line| prefix + Term::ANSIColor.uncolor(line) }.join("\n") + "\n" + prefix + "\n" + prefix + Term::ANSIColor.green("Dry run enabled - ignoring any failures")
else
lines
end
end

def retry_options
{
condition: lambda { |matrix| !matrix.any_unknown? },
Expand Down
4 changes: 3 additions & 1 deletion lib/pact_broker/client/cli/broker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Broker < CustomThor
method_option :retry_interval, banner: 'SECONDS', type: :numeric, default: 10, required: false, desc: "The time between retries in seconds. Use in conjuction with --retry-while-unknown"
# Allow limit to be set manually until https://github.com/pact-foundation/pact_broker-client/issues/53 is fixed
method_option :limit, hide: true
method_option :dry_run, type: :boolean, default: false, desc: "When dry-run is enabled, always exit process with a success code. Can also be enabled by setting the environment variable PACT_BROKER_CAN_I_DEPLOY_DRY_RUN=true."
shared_authentication_options

def can_i_deploy(*ignored_but_necessary)
Expand All @@ -51,7 +52,8 @@ def can_i_deploy(*ignored_but_necessary)
[]
end
validate_can_i_deploy_selectors(selectors)
can_i_deploy_options = { output: options.output, retry_while_unknown: options.retry_while_unknown, retry_interval: options.retry_interval }
dry_run = options.dry_run || ENV["PACT_BROKER_CAN_I_DEPLOY_DRY_RUN"] == "true"
can_i_deploy_options = { output: options.output, retry_while_unknown: options.retry_while_unknown, retry_interval: options.retry_interval, dry_run: dry_run }
result = CanIDeploy.call(options.broker_base_url, selectors, { to_tag: options.to, to_environment: options.to_environment, limit: options.limit, ignore_selectors: ignore_selectors }, can_i_deploy_options, pact_broker_client_options)
$stdout.puts result.message
$stdout.flush
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[dry-run] Computer says no ¯\_(ツ)_/¯ (but you're ignoring this by enabling dry run)
[dry-run] 
[dry-run] text matrix
[dry-run] 
[dry-run] some reason
[dry-run] 
[dry-run] Dry run enabled - ignoring any failures
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[dry-run] Computer says yes \o/ (and maybe you don't need to enable dry run)
[dry-run] 
[dry-run] text matrix
[dry-run] 
[dry-run] some reason
[dry-run] 
[dry-run] Dry run enabled - ignoring any failures
64 changes: 62 additions & 2 deletions spec/lib/pact_broker/client/can_i_deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Client
let(:version_selectors) { [{ pacticipant: "Foo", version: "1" }] }
let(:matrix_options) { { } }
let(:pact_broker_client_options) { { foo: 'bar' } }
let(:dry_run) { false }
let(:matrix_client) { instance_double('PactBroker::Client::Matrix') }
let(:matrix) do
instance_double('Matrix::Resource',
Expand All @@ -23,7 +24,7 @@ module Client
let(:any_unknown) { unknown_count > 0 }
let(:supports_unknown_count) { true }
let(:retry_while_unknown) { 0 }
let(:options) { { output: 'text', retry_while_unknown: retry_while_unknown, retry_interval: 5 } }
let(:options) { { output: 'text', retry_while_unknown: retry_while_unknown, retry_interval: 5, dry_run: dry_run } }
let(:notices) { nil }
let(:supports_ignore) { true }
let(:deployable) { true }
Expand Down Expand Up @@ -69,6 +70,14 @@ module Client
expect(subject.message).to include "some notice"
end
end

context "when dry_run is enabled" do
let(:dry_run) { true }

it "prefixes each line with [dry-run]" do
Approvals.verify(subject.message, :name => "can_i_deploy_success_dry_run", format: :txt)
end
end
end

context "when the versions are not deployable" do
Expand All @@ -94,6 +103,18 @@ module Client
expect(subject.message).to include "some notice"
end
end

context "when dry_run is enabled" do
let(:dry_run) { true }

it "returns a success response" do
expect(subject.success).to be true
end

it "prefixes each line with [dry-run]" do
Approvals.verify(subject.message, :name => "can_i_deploy_failure_dry_run", format: :txt)
end
end
end

context "when retry_while_unknown is greater than 0" do
Expand Down Expand Up @@ -135,6 +156,19 @@ module Client
it "returns a failure message" do
expect(subject.message).to match /does not provide a count/
end

context "when dry_run is enabled" do
let(:dry_run) { true }

it "returns a success response" do
expect(subject.success).to be true
end

it "returns a failure message" do
expect(subject.message).to include "[dry-run]"
expect(subject.message).to match /does not provide a count/
end
end
end
end

Expand Down Expand Up @@ -169,6 +203,19 @@ module Client
it "returns a failure message" do
expect(subject.message).to include "error text"
end

context "when dry_run is enabled" do
let(:dry_run) { true }

it "returns a success response" do
expect(subject.success).to be true
end

it "returns a failure message" do
expect(subject.message).to include "[dry-run]"
expect(subject.message).to match /error text/
end
end
end

context "when a StandardError is raised" do
Expand All @@ -183,7 +230,20 @@ module Client
end

it "returns a failure message and backtrace" do
expect(subject.message).to include "Error retrieving matrix. StandardError - error text\n"
expect(subject.message).to include "Error retrieving matrix. StandardError - error text"
end

context "when dry_run is enabled" do
let(:dry_run) { true }

it "returns a success response" do
expect(subject.success).to be true
end

it "returns a failure message" do
expect(subject.message).to include "[dry-run]"
expect(subject.message).to match /error text/
end
end
end
end
Expand Down
17 changes: 15 additions & 2 deletions spec/lib/pact_broker/client/cli/broker_can_i_deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ module CLI
verbose: 'verbose',
retry_while_unknown: 1,
retry_interval: 2,
limit: 1000
limit: 1000,
dry_run: false
}
end

Expand All @@ -37,7 +38,7 @@ module CLI
end

it "invokes the CanIDeploy service" do
expect(CanIDeploy).to receive(:call).with('http://pact-broker', version_selectors, { to_tag: nil, to_environment: nil, limit: 1000, ignore_selectors: []}, {output: 'table', retry_while_unknown: 1, retry_interval: 2}, { pact_broker_base_url: 'http://pact-broker', verbose: 'verbose' })
expect(CanIDeploy).to receive(:call).with('http://pact-broker', version_selectors, { to_tag: nil, to_environment: nil, limit: 1000, ignore_selectors: []}, {output: 'table', retry_while_unknown: 1, retry_interval: 2, dry_run: false}, { pact_broker_base_url: 'http://pact-broker', verbose: 'verbose' })
invoke_can_i_deploy
end

Expand Down Expand Up @@ -94,6 +95,18 @@ module CLI
end
end

context "when PACT_BROKER_CAN_I_DEPLOY_DRY_RUN=true" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("PACT_BROKER_CAN_I_DEPLOY_DRY_RUN").and_return("true")
end

it "invokes the CanIDeploy service with dry_run set to true" do
expect(CanIDeploy).to receive(:call).with(anything, anything, anything, hash_including(dry_run: true), anything)
invoke_can_i_deploy
end
end

context "when successful" do
it "prints the message to stdout" do
expect($stdout).to receive(:puts).with(message)
Expand Down

0 comments on commit 9b08529

Please sign in to comment.