pact_broker 2.6.0 → 2.7.0.beta.1

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/db/migrations/42_delete_orphan_webhook_data.rb +0 -2
  4. data/db/migrations/43_add_provider_version_to_verification.rb +12 -0
  5. data/db/migrations/44_populate_verifications_provider_version_id.rb +25 -0
  6. data/db/migrations/45_set_verification_provider_number_nullable.rb +7 -0
  7. data/db/migrations/46_recreate_latest_verifications.rb +18 -0
  8. data/db/migrations/47_create_all_verifications.rb +19 -0
  9. data/lib/pact_broker/api.rb +4 -0
  10. data/lib/pact_broker/api/decorators/matrix_decorator.rb +114 -0
  11. data/lib/pact_broker/api/decorators/verification_decorator.rb +1 -1
  12. data/lib/pact_broker/api/pact_broker_urls.rb +2 -2
  13. data/lib/pact_broker/api/resources/index.rb +3 -5
  14. data/lib/pact_broker/api/resources/matrix.rb +48 -0
  15. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +42 -0
  16. data/lib/pact_broker/domain/relationship.rb +26 -6
  17. data/lib/pact_broker/domain/verification.rb +5 -1
  18. data/lib/pact_broker/matrix/repository.rb +51 -0
  19. data/lib/pact_broker/matrix/service.rb +50 -0
  20. data/lib/pact_broker/pacticipants/service.rb +21 -5
  21. data/lib/pact_broker/pacts/all_pact_publications.rb +11 -0
  22. data/lib/pact_broker/pacts/pact_publication.rb +4 -0
  23. data/lib/pact_broker/pacts/repository.rb +1 -1
  24. data/lib/pact_broker/repositories.rb +5 -0
  25. data/lib/pact_broker/services.rb +5 -0
  26. data/lib/pact_broker/tags/service.rb +0 -1
  27. data/lib/pact_broker/ui/app.rb +5 -0
  28. data/lib/pact_broker/ui/controllers/matrix.rb +27 -0
  29. data/lib/pact_broker/ui/controllers/relationships.rb +2 -2
  30. data/lib/pact_broker/ui/view_models/matrix_line.rb +79 -0
  31. data/lib/pact_broker/ui/view_models/relationship.rb +22 -4
  32. data/lib/pact_broker/ui/views/matrix/show.haml +42 -0
  33. data/lib/pact_broker/ui/views/relationships/show-prod-tags.haml +83 -0
  34. data/lib/pact_broker/ui/views/relationships/show.haml +1 -1
  35. data/lib/pact_broker/verifications/repository.rb +8 -1
  36. data/lib/pact_broker/verifications/service.rb +2 -1
  37. data/lib/pact_broker/version.rb +1 -1
  38. data/lib/pact_broker/versions/service.rb +7 -0
  39. data/lib/pact_broker/webhooks/status.rb +1 -1
  40. data/lib/rack/pact_broker/convert_file_extension_to_accept_header.rb +1 -1
  41. data/script/seed.rb +5 -0
  42. data/spec/features/get_matrix_for_consumer_and_provider_spec.rb +25 -0
  43. data/spec/features/get_matrix_spec.rb +31 -0
  44. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +133 -0
  45. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +2 -8
  46. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +3 -2
  47. data/spec/lib/pact_broker/api/resources/matrix_spec.rb +38 -0
  48. data/spec/lib/pact_broker/domain/relationship_spec.rb +1 -1
  49. data/spec/lib/pact_broker/matrix/repository_spec.rb +153 -0
  50. data/spec/lib/pact_broker/matrix/service_spec.rb +46 -0
  51. data/spec/lib/pact_broker/pacticipants/service_spec.rb +78 -4
  52. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +35 -0
  53. data/spec/lib/pact_broker/pacts/repository_spec.rb +16 -14
  54. data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +5 -6
  55. data/spec/lib/pact_broker/verifications/repository_spec.rb +7 -7
  56. data/spec/lib/pact_broker/verifications/service_spec.rb +6 -0
  57. data/spec/lib/pact_broker/versions/service_spec.rb +37 -0
  58. data/spec/lib/pact_broker/webhooks/status_spec.rb +6 -0
  59. data/spec/migrations/44_add_provider_version_to_verification_spec.rb +60 -0
  60. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +12 -0
  61. data/spec/support/shared_examples_for_responses.rb +4 -0
  62. data/spec/support/test_data_builder.rb +26 -3
  63. metadata +34 -4
@@ -0,0 +1,83 @@
1
+ %body
2
+ %link{rel: 'stylesheet', href: '/css/bootstrap.min.css'}
3
+ %link{rel: 'stylesheet', href: '/stylesheets/relationships.css'}
4
+ %script{type: 'text/javascript', src:'/javascripts/jquery-2.1.1.min.js'}
5
+ %script{type: 'text/javascript', src:'/javascripts/jquery.tablesorter.min.js'}
6
+ %script{type: 'text/javascript', src:'/js/bootstrap.min.js'}
7
+ %nav.navbase-default.navbar-right{role: "navigation"}
8
+ .container
9
+ %ul
10
+ %li.navbar-right
11
+ %a{href: '/hal-browser/browser.html'}
12
+ HAL Browser
13
+ .container
14
+ %h1.page-header
15
+ Pacts
16
+ %table.table.table-bordered.table-striped{id: 'relationships'}
17
+ %thead
18
+ %th.consumer
19
+ Consumer
20
+ %span.glyphicon.glyphicon-sort.relationships-sort
21
+ %th.tag
22
+ Version
23
+ %span.glyphicon.glyphicon-sort.relationships-sort
24
+ %th.pact
25
+ %th.provider
26
+ Provider
27
+ %span.glyphicon.glyphicon-sort.relationships-sort
28
+ %th.tag
29
+ Version
30
+ %span.glyphicon.glyphicon-sort.relationships-sort
31
+ %th
32
+ Published
33
+ %th
34
+ Webhook<br>status
35
+ %th
36
+ Last<br>verified
37
+ %tbody
38
+
39
+ - relationships.each do | relationship |
40
+ %tr
41
+ %td.consumer
42
+ %a{:href => relationship.consumer_group_url}
43
+ = relationship.consumer_name
44
+ %td
45
+ = relationship.consumer_version_number
46
+ %span{style: 'color:gray'}
47
+ = relationship.tag_names
48
+ %td.pact
49
+ %a{:href => relationship.pact_url, :title => "View pact"}
50
+ %span.pact
51
+ %td.provider
52
+ %a{:href => relationship.provider_group_url}
53
+ = relationship.provider_name
54
+ %td
55
+ = relationship.provider_version_number
56
+ %td
57
+ = relationship.publication_date_of_latest_pact.gsub("about ", "")
58
+ %td{class: relationship.webhook_status}
59
+ - if relationship.show_webhook_status?
60
+ %a{:href => relationship.webhook_url}
61
+ = relationship.webhook_label
62
+
63
+ %td{class: relationship.verification_status, title: relationship.verification_tooltip, "data-toggle": "tooltip", "data-placement": "left"}
64
+ %div
65
+ = relationship.last_verified_date.gsub("about ", "")
66
+ - if relationship.warning?
67
+ %span.glyphicon.glyphicon-warning-sign{'aria-hidden':true}
68
+ %div.relationships-size
69
+ = relationships.size_label
70
+
71
+ :javascript
72
+ $(function(){
73
+ $("#relationships").tablesorter();
74
+ });
75
+
76
+ $(document).ready(function(){
77
+ $("span.pact").load("/images/doc-text.svg");
78
+ $('td[data-toggle="tooltip"]').each(function(index, td){
79
+ //appended tooltip div screws up table if it's appended after a
80
+ //td, so need to append it to a div
81
+ $(td).tooltip({container: $(td).first()});
82
+ });
83
+ });
@@ -40,7 +40,7 @@
40
40
  %a{:href => relationship.consumer_group_url}
41
41
  = relationship.consumer_name
42
42
  %td.pact
43
- %a{:href => relationship.latest_pact_url, :title => "View pact"}
43
+ %a{:href => relationship.pact_url, :title => "View pact"}
44
44
  %span.pact
45
45
  %td.provider
46
46
  %a{:href => relationship.provider_group_url}
@@ -7,9 +7,13 @@ module PactBroker
7
7
  class Repository
8
8
 
9
9
  include PactBroker::Repositories::Helpers
10
+ include PactBroker::Repositories
10
11
 
11
- def create verification, pact
12
+ def create verification, provider_version_number, pact
13
+ provider = pacticipant_repository.find_by_name(pact.provider_name)
14
+ version = version_repository.find_by_pacticipant_id_and_number_or_create(provider.id, provider_version_number)
12
15
  verification.pact_version_id = pact_version_id_for(pact)
16
+ verification.provider_version = version
13
17
  verification.save
14
18
  end
15
19
 
@@ -39,6 +43,9 @@ module PactBroker
39
43
  .all
40
44
  end
41
45
 
46
+ # The most recent verification for the latest revision of the pact
47
+ # belonging to the version with the largest consumer_version_order.
48
+
42
49
  def find_latest_verification_for consumer_name, provider_name, tag = nil
43
50
  query = LatestVerificationsByConsumerVersion
44
51
  .select_all_qualified
@@ -19,9 +19,10 @@ module PactBroker
19
19
  def create next_verification_number, params, pact
20
20
  PactBroker.logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id} from params #{params}"
21
21
  verification = PactBroker::Domain::Verification.new
22
+ provider_version_number = params.fetch('providerApplicationVersion')
22
23
  PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
23
24
  verification.number = next_verification_number
24
- verification_repository.create(verification, pact)
25
+ verification_repository.create(verification, provider_version_number, pact)
25
26
  end
26
27
 
27
28
  def errors params
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.6.0'
2
+ VERSION = '2.7.0.beta.1'
3
3
  end
@@ -16,6 +16,13 @@ module PactBroker
16
16
  pact_repository.delete_by_version_id version.id
17
17
  version_repository.delete_by_id version.id
18
18
  end
19
+
20
+ def self.find_versions_by_selector selectors
21
+ selectors.collect do | selector |
22
+ pacticipant_name, type, number = selector.split("/")
23
+ version_repository.find_by_pacticipant_name_and_number pacticipant_name, number
24
+ end
25
+ end
19
26
  end
20
27
  end
21
28
  end
@@ -13,7 +13,7 @@ module PactBroker
13
13
 
14
14
  def to_sym
15
15
  return :none if webhooks.empty?
16
- return :not_run if latest_triggered_webhooks.empty?
16
+ return :not_run if latest_triggered_webhooks.empty? || latest_triggered_webhooks.all?{|w| w.status == "not_run"}
17
17
  if latest_triggered_webhooks.any?{|w| w.status == "retrying" }
18
18
  return :retrying
19
19
  end
@@ -7,7 +7,7 @@ module Rack
7
7
 
8
8
  class ConvertFileExtensionToAcceptHeader
9
9
 
10
- EXTENSIONS = {".csv" => "text/csv", ".svg" => "image/svg+xml"}
10
+ EXTENSIONS = {".csv" => "text/csv", ".svg" => "image/svg+xml", ".json" => "application/hal+json"}
11
11
  EXTENSION_REGEXP = /\.\w+$/
12
12
 
13
13
  def initialize app
data/script/seed.rb CHANGED
@@ -59,9 +59,12 @@ TestDataBuilder.new
59
59
  .create_verification(provider_version: "1.4.234", success: true, execution_date: DateTime.now - 15)
60
60
  .revise_pact
61
61
  .create_consumer_version("1.2.101")
62
+ .create_consumer_version_tag('prod')
62
63
  .publish_pact
64
+ .create_verification(provider_version: "9.9.10", success: false, execution_date: DateTime.now - 15)
63
65
  .create_consumer_version("1.2.102")
64
66
  .publish_pact(created_at: (Date.today - 7).to_datetime)
67
+ .create_verification(provider_version: "9.9.9", success: true, execution_date: DateTime.now - 14)
65
68
  .create_provider("Animals")
66
69
  .create_webhook(method: 'GET', url: 'http://localhost:9393/')
67
70
  .publish_pact(created_at: (Time.now - 140).to_datetime)
@@ -76,6 +79,8 @@ TestDataBuilder.new
76
79
  .create_provider("The back end")
77
80
  .create_webhook(method: 'GET', url: 'http://localhost:9393/')
78
81
  .create_consumer_version("1.2.106")
82
+ .create_consumer_version_tag("production")
83
+ .create_consumer_version_tag("feat-x")
79
84
  .publish_pact
80
85
  .create_consumer("Some other app")
81
86
  .create_provider("A service")
@@ -0,0 +1,25 @@
1
+ require 'spec/support/test_data_builder'
2
+
3
+ describe "Get matrix for consumer and provider" do
4
+ before do
5
+ TestDataBuilder.new
6
+ .create_pact_with_hierarchy('Consumer', '1.0.0', 'Provider')
7
+ .create_verification(provider_version: '4.5.6')
8
+ end
9
+
10
+ let(:path) { "/matrix/provider/Provider/consumer/Consumer" }
11
+ let(:last_response_body) { JSON.parse(subject.body, symbolize_names: true) }
12
+
13
+ subject { get path; last_response }
14
+
15
+ it "returns a 200 HAL JSON response" do
16
+ expect(subject).to be_a_hal_json_success_response
17
+ end
18
+
19
+ it "returns the JSON representation of the matrix" do
20
+ expect(last_response_body[:matrix][0][:consumer]).to be_instance_of(Hash)
21
+ expect(last_response_body[:matrix][0][:provider]).to be_instance_of(Hash)
22
+ expect(last_response_body[:matrix][0][:pact]).to be_instance_of(Hash)
23
+ expect(last_response_body[:matrix][0][:verificationResult]).to be_instance_of(Hash)
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec/support/test_data_builder'
2
+
3
+ describe "Get matrix for consumer and provider" do
4
+ before do
5
+ TestDataBuilder.new
6
+ .create_pact_with_hierarchy('Consumer', '1.0.0', 'Provider')
7
+ .create_verification(provider_version: '4.5.6')
8
+ end
9
+
10
+ let(:path) { "/matrix" }
11
+ let(:params) do
12
+ {
13
+ selectors: ['Consumer/version/1.0.0','Provider/version/4.5.6']
14
+ }
15
+ end
16
+ let(:last_response_body) { JSON.parse(subject.body, symbolize_names: true) }
17
+
18
+ subject { get path, params; last_response }
19
+
20
+ it "returns a 200 HAL JSON response" do
21
+ expect(subject).to be_a_hal_json_success_response
22
+ end
23
+
24
+ it "returns the JSON representation of the matrix" do
25
+ expect(last_response_body[:matrix][0][:consumer]).to be_instance_of(Hash)
26
+ expect(last_response_body[:matrix][0][:provider]).to be_instance_of(Hash)
27
+ expect(last_response_body[:matrix][0][:pact]).to be_instance_of(Hash)
28
+ expect(last_response_body[:matrix][0][:verificationResult]).to be_instance_of(Hash)
29
+ end
30
+ end
31
+
@@ -0,0 +1,133 @@
1
+ require 'pact_broker/api/decorators/matrix_decorator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+ describe MatrixPactDecorator do
7
+ describe "to_json" do
8
+ let(:verification_date) { DateTime.new(2017, 12, 31) }
9
+ let(:pact_created_at) { DateTime.new(2017, 1, 1) }
10
+ let(:line_1) do
11
+ {
12
+ consumer_name: "Consumer",
13
+ consumer_version_number: "1.0.0",
14
+ pact_version_sha: "1234",
15
+ pact_created_at: pact_created_at,
16
+ provider_version_number: "4.5.6",
17
+ provider_name: "Provider",
18
+ success: true,
19
+ number: 1,
20
+ build_url: nil,
21
+ verification_executed_at: verification_date
22
+ }
23
+ end
24
+
25
+ let(:line_2) do
26
+ {
27
+ consumer_name: "Consumer",
28
+ consumer_version_number: "1.0.0",
29
+ pact_version_sha: "1234",
30
+ pact_created_at: pact_created_at,
31
+ provider_version_number: nil,
32
+ provider_name: "Provider",
33
+ success: nil,
34
+ number: nil,
35
+ build_url: nil,
36
+ verification_executed_at: nil
37
+ }
38
+ end
39
+
40
+ let(:consumer_hash) do
41
+ {
42
+ name: 'Consumer',
43
+ _links: {
44
+ self: {
45
+ href: 'http://example.org/pacticipants/Consumer'
46
+ }
47
+ },
48
+ version: {
49
+ number: '1.0.0',
50
+ _links: {
51
+ self: {
52
+ href: 'http://example.org/pacticipants/Consumer/versions/1.0.0'
53
+ }
54
+ }
55
+ }
56
+ }
57
+ end
58
+
59
+ let(:provider_hash) do
60
+ {
61
+ name: 'Provider',
62
+ _links: {
63
+ self: {
64
+ href: 'http://example.org/pacticipants/Provider'
65
+ }
66
+ },
67
+ version: {
68
+ number: '4.5.6'
69
+ }
70
+ }
71
+ end
72
+
73
+ let(:verification_hash) do
74
+ {
75
+ success: true,
76
+ verifiedAt: "2017-12-31T00:00:00+00:00",
77
+ _links: {
78
+ self: {
79
+ href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/1"
80
+ }
81
+ }
82
+ }
83
+ end
84
+
85
+ let(:pact_hash) do
86
+ {
87
+ createdAt: "2017-01-01T00:00:00+00:00",
88
+ _links: {
89
+ self: {
90
+ href: "http://example.org/pacts/provider/Provider/consumer/Consumer/version/1.0.0"
91
+ }
92
+ }
93
+ }
94
+ end
95
+
96
+ let(:lines){ [line_1, line_2]}
97
+ let(:json) { MatrixPactDecorator.new(lines).to_json(user_options: { base_url: 'http://example.org' }) }
98
+ let(:parsed_json) { JSON.parse(json, symbolize_names: true) }
99
+
100
+ it "includes the consumer details" do
101
+ expect(parsed_json[:matrix][0][:consumer]).to eq consumer_hash
102
+ end
103
+
104
+ it "includes the provider details" do
105
+ expect(parsed_json[:matrix][0][:provider]).to eq provider_hash
106
+ end
107
+
108
+ it "includes the verification details" do
109
+ expect(parsed_json[:matrix][0][:verificationResult]).to eq verification_hash
110
+ end
111
+
112
+ it "includes the pact details" do
113
+ expect(parsed_json[:matrix][0][:pact]).to eq pact_hash
114
+ end
115
+
116
+ context "when the pact has not been verified" do
117
+ let(:verification_hash) do
118
+ nil
119
+ end
120
+
121
+ it "has empty provider details" do
122
+ expect(parsed_json[:matrix][1][:provider]).to eq provider_hash.merge(version: nil)
123
+ end
124
+
125
+ it "has a nil verificationResult" do
126
+ expect(parsed_json[:matrix][1][:verificationResult]).to eq verification_hash
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -9,21 +9,15 @@ module PactBroker
9
9
  instance_double('PactBroker::Domain::Verification',
10
10
  number: 1,
11
11
  success: true,
12
- provider_version: "4.5.6",
12
+ provider_version_number: "4.5.6",
13
13
  provider_name: 'Provider',
14
14
  consumer_name: 'Consumer',
15
15
  build_url: 'http://build-url',
16
- pact_version: pact_version,
16
+ pact_version_sha: '1234',
17
17
  latest_pact_publication: pact_publication,
18
18
  execution_date: DateTime.now)
19
19
  end
20
20
 
21
- let(:pact_version) do
22
- instance_double('PactBroker::Pacts::PactVersion',
23
- sha: '1234'
24
- )
25
- end
26
-
27
21
  let(:pact_publication) do
28
22
  instance_double('PactBroker::Pacts::PactPublication',
29
23
  name: 'A name',
@@ -12,16 +12,17 @@ module PactBroker
12
12
  let(:verification) do
13
13
  instance_double("PactBroker::Domain::Verification",
14
14
  success: true, number: 1,
15
- provider_version: '4.5.6',
15
+ provider_version_number: '4.5.6',
16
16
  build_url: 'http://some-build',
17
17
  provider_name: 'Provider',
18
18
  consumer_name: 'Consumer',
19
19
  pact_version: pact_version,
20
+ pact_version_sha: '1234',
20
21
  latest_pact_publication: pact,
21
22
  execution_date: DateTime.now)
22
23
  end
23
24
  let(:pact_version) do
24
- instance_double("PactBroker::Pacts::PactVersion", sha: '1234', name: 'Name')
25
+ instance_double("PactBroker::Pacts::PactVersion", name: 'Name')
25
26
  end
26
27
 
27
28
  let(:pact) { instance_double("PactBroker::Domain::Pact", name: "Some pact", consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1.2.3") }
@@ -0,0 +1,38 @@
1
+ require 'pact_broker/api/resources/matrix'
2
+ require 'pact_broker/matrix/service'
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Resources
7
+ describe Matrix do
8
+ before do
9
+ allow(PactBroker::Matrix::Service).to receive(:validate_selectors).and_return(error_messages)
10
+ end
11
+
12
+ let(:td) { TestDataBuilder.new }
13
+ let(:path) { "/matrix" }
14
+ let(:json_response_body) { JSON.parse(subject.body, symbolize_names: true) }
15
+ let(:params) { { selectors: ['Foo/version/1', 'Bar/version/2'] } }
16
+ let(:error_messages) { [] }
17
+
18
+ subject { get path, params, {'Content-Type' => 'application/hal+json'}; last_response }
19
+
20
+ it "validates the selectors" do
21
+ expect(PactBroker::Matrix::Service).to receive(:validate_selectors).with(['Foo/version/1', 'Bar/version/2'])
22
+ subject
23
+ end
24
+
25
+ context "when a validation error occurs" do
26
+ let(:error_messages) { ['foo'] }
27
+ it "returns a 400 status" do
28
+ expect(subject.status).to eq 400
29
+ end
30
+
31
+ it "returns error messages" do
32
+ expect(json_response_body[:errors]).to eq ['foo']
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end