Skip to content

Commit 02443f3

Browse files
committed
feat: add can-i-deploy endpoint to expose a simplified interface to the /matrix resource that accepts the same parameters as the can-i-deploy CLI.
1 parent fc73439 commit 02443f3

File tree

7 files changed

+136
-1
lines changed

7 files changed

+136
-1
lines changed

lib/pact_broker/api.rb

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ module PactBroker
8888
add ['matrix', 'provider', :provider_name, 'consumer', :consumer_name], Api::Resources::MatrixForConsumerAndProvider, {resource_name: "matrix_consumer_provider"}
8989
add ['matrix', 'provider', :provider_name, 'latest', :provider_tag, 'consumer', :consumer_name, 'latest', :tag, 'badge'], Api::Resources::MatrixBadge, {resource_name: "matrix_tag_badge"}
9090
add ['matrix'], Api::Resources::Matrix, {resource_name: "matrix"}
91+
add ['can-i-deploy'], Api::Resources::CanIDeploy, {resource_name: "can-i-deploy"}
9192

9293
add ['dashboard'], Api::Resources::Dashboard, {resource_name: "dashboard"}
9394
add ['dashboard', 'provider', :provider_name, 'consumer', :consumer_name ], Api::Resources::Dashboard, {resource_name: "integration_dashboard"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
require 'pact_broker/api/resources/matrix'
2+
require 'pact_broker/matrix/can_i_deploy_query_schema'
3+
require 'pact_broker/matrix/parse_can_i_deploy_query'
4+
5+
module PactBroker
6+
module Api
7+
module Resources
8+
class CanIDeploy < Matrix
9+
def initialize
10+
@query_params = JSON.parse(Rack::Utils.parse_nested_query(request.uri.query).to_json, symbolize_names: true)
11+
@selectors, @options = PactBroker::Matrix::ParseCanIDeployQuery.call(query_params)
12+
end
13+
14+
def malformed_request?
15+
if (errors = query_schema.call(query_params)).any?
16+
set_json_validation_error_messages(errors)
17+
true
18+
else
19+
false
20+
end
21+
end
22+
23+
private
24+
25+
attr_reader :query_params
26+
27+
def query_schema
28+
PactBroker::Api::Contracts::CanIDeployQuerySchema
29+
end
30+
31+
def selectors
32+
@selectors
33+
end
34+
35+
def options
36+
@options
37+
end
38+
end
39+
end
40+
end
41+
end

lib/pact_broker/api/resources/index.rb

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ def links
110110
href: base_url + '/metrics',
111111
title: "Get Pact Broker metrics",
112112
},
113+
'pb:can-i-deploy-pacticipant-version-to-tag' =>
114+
{
115+
href: base_url + '/can-i-deploy?pacticipant={pacticipant}&version={version}&to={tag}',
116+
title: "Determine if an application can be safely deployed to an environment identified by the given tag",
117+
templated: true
118+
},
113119
'curies' =>
114120
[{
115121
name: 'pb',

lib/pact_broker/doc/controllers/app.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ class App < Padrino::Application
1313

1414
MAPPINGS = {
1515
'webhooks-create' => 'webhooks',
16-
'webhooks-webhooks' => 'webhooks'
16+
'webhooks-webhooks' => 'webhooks',
17+
'can-i-deploy-pacticipant-version-to-tag' => 'can-i-deploy',
18+
'pacticipant' => 'pacticipants'
1719
}.freeze
1820

1921
helpers do
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'dry-validation'
2+
3+
module PactBroker
4+
module Api
5+
module Contracts
6+
class CanIDeployQuerySchema
7+
SCHEMA = Dry::Validation.Schema do
8+
required(:pacticipant).filled(:str?)
9+
required(:version).filled(:str?)
10+
optional(:to).filled(:str?)
11+
end
12+
13+
def self.call(params)
14+
select_first_message(SCHEMA.call(params).messages(full: true))
15+
end
16+
17+
def self.select_first_message(messages)
18+
messages.each_with_object({}) do | (key, value), new_messages |
19+
new_messages[key] = [value.first]
20+
end
21+
end
22+
end
23+
end
24+
end
25+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require 'rack/utils'
2+
3+
module PactBroker
4+
module Matrix
5+
class ParseCanIDeployQuery
6+
def self.call params
7+
selector = {}
8+
options = {
9+
latestby: 'cvp',
10+
latest: true
11+
}
12+
13+
if params[:pacticipant].is_a?(String)
14+
selector[:pacticipant_name] = params[:pacticipant]
15+
end
16+
17+
if params[:version].is_a?(String)
18+
selector[:pacticipant_version_number] = params[:version]
19+
end
20+
21+
if params[:to].is_a?(String)
22+
options[:tag] = params[:to]
23+
end
24+
25+
return [selector], options
26+
end
27+
end
28+
end
29+
end

spec/features/can_i_deploy_spec.rb

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
RSpec.describe "can i deploy" do
2+
before do
3+
td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
4+
end
5+
6+
let(:query) do
7+
{
8+
pacticipant: "Foo",
9+
version: "1.2.3",
10+
to: "prod"
11+
}
12+
end
13+
14+
let(:response_body) { JSON.parse(subject.body, symbolize_names: true) }
15+
16+
subject { get("/can-i-deploy", query, { 'HTTP_ACCEPT' => 'application/hal+json'}) }
17+
18+
it "returns the matrix response" do
19+
expect(subject).to be_a_hal_json_success_response
20+
expect(response_body[:matrix]).to be_instance_of(Array)
21+
end
22+
23+
context "with a validation error" do
24+
let(:query) { {} }
25+
26+
it "returns an error response" do
27+
expect(subject.status).to eq 400
28+
expect(response_body[:errors]).to be_instance_of(Hash)
29+
end
30+
end
31+
end

0 commit comments

Comments
 (0)