pact_broker 2.76.2 → 2.79.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/release_gem.yml +1 -0
  4. data/.github/workflows/test-ruby-3.yml +19 -0
  5. data/.github/workflows/test.yml +16 -7
  6. data/.gitignore +3 -1
  7. data/CHANGELOG.md +53 -0
  8. data/DEVELOPER_DOCUMENTATION.md +13 -0
  9. data/DEVELOPER_SETUP.md +62 -3
  10. data/Dockerfile +1 -0
  11. data/ISSUES.md +7 -7
  12. data/config.ru +2 -1
  13. data/db/ddl_statements/head_pact_tags.rb +24 -1
  14. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  15. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  16. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  17. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  18. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  19. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  20. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  21. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  22. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  23. data/db/migrations/20210210_create_environments_table.rb +16 -0
  24. data/docker-compose-dev-postgres.yml +9 -1
  25. data/lib/pact_broker/api.rb +7 -2
  26. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  27. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  28. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  29. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  30. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  31. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  32. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  33. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  34. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  35. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  36. data/lib/pact_broker/api/resources/default_base_resource.rb +18 -0
  37. data/lib/pact_broker/api/resources/environment.rb +76 -0
  38. data/lib/pact_broker/api/resources/environments.rb +75 -0
  39. data/lib/pact_broker/api/resources/index.rb +20 -0
  40. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  41. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  42. data/lib/pact_broker/api/resources/version.rb +15 -9
  43. data/lib/pact_broker/app.rb +1 -1
  44. data/lib/pact_broker/certificates/certificate.rb +1 -1
  45. data/lib/pact_broker/config/setting.rb +1 -1
  46. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  47. data/lib/pact_broker/configuration.rb +22 -1
  48. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  49. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  50. data/lib/pact_broker/db/migrate_data.rb +1 -0
  51. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  52. data/lib/pact_broker/deployments/environment.rb +15 -0
  53. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  54. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  55. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  56. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  57. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  58. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  59. data/lib/pact_broker/domain/index_item.rb +18 -4
  60. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  61. data/lib/pact_broker/domain/tag.rb +131 -71
  62. data/lib/pact_broker/domain/verification.rb +3 -2
  63. data/lib/pact_broker/domain/version.rb +58 -23
  64. data/lib/pact_broker/domain/webhook.rb +6 -3
  65. data/lib/pact_broker/index/service.rb +55 -49
  66. data/lib/pact_broker/locale/en.yml +3 -1
  67. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  68. data/lib/pact_broker/metrics/service.rb +1 -1
  69. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  70. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  71. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  72. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  73. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  74. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  75. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  76. data/lib/pact_broker/pacts/repository.rb +5 -240
  77. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  78. data/lib/pact_broker/pacts/selector.rb +56 -1
  79. data/lib/pact_broker/pacts/selectors.rb +16 -0
  80. data/lib/pact_broker/pacts/service.rb +2 -6
  81. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  82. data/lib/pact_broker/pacts/verifiable_pact.rb +23 -2
  83. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  84. data/lib/pact_broker/repositories/helpers.rb +4 -0
  85. data/lib/pact_broker/services.rb +9 -0
  86. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  87. data/lib/pact_broker/tags/repository.rb +3 -1
  88. data/lib/pact_broker/tags/service.rb +0 -3
  89. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  90. data/lib/pact_broker/test/http_test_data_builder.rb +23 -7
  91. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  92. data/lib/pact_broker/ui/view_models/index_item.rb +19 -2
  93. data/lib/pact_broker/ui/view_models/matrix_line.rb +38 -2
  94. data/lib/pact_broker/ui/views/index/show-with-tags.haml +14 -6
  95. data/lib/pact_broker/ui/views/matrix/show.haml +12 -2
  96. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  97. data/lib/pact_broker/version.rb +1 -1
  98. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  99. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  100. data/lib/pact_broker/versions/repository.rb +22 -2
  101. data/lib/pact_broker/versions/service.rb +5 -1
  102. data/lib/pact_broker/webhooks/execution.rb +3 -2
  103. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  104. data/lib/pact_broker/webhooks/triggered_webhook.rb +11 -4
  105. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  106. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  107. data/lib/pact_broker/webhooks/webhook_execution_result.rb +6 -1
  108. data/lib/pact_broker/webhooks/webhook_request_logger.rb +7 -1
  109. data/lib/rack/pact_broker/set_base_url.rb +35 -5
  110. data/lib/sequel/plugins/upsert.rb +18 -4
  111. data/pact_broker.gemspec +1 -1
  112. data/public/javascripts/clipboard.js +8 -2
  113. data/public/stylesheets/index.css +26 -2
  114. data/public/stylesheets/matrix.css +0 -21
  115. data/regression/can_i_deploy_spec.rb +5 -4
  116. data/regression/index_spec.rb +26 -0
  117. data/regression/regression_helper.rb +29 -3
  118. data/regression/script/clear.sh +3 -0
  119. data/regression/script/run.sh +3 -0
  120. data/script/demonstrate-version-branches.rb +33 -0
  121. data/script/pry.rb +2 -2
  122. data/spec/features/create_environment_spec.rb +47 -0
  123. data/spec/features/create_tag_spec.rb +32 -0
  124. data/spec/features/create_version_spec.rb +70 -0
  125. data/spec/features/delete_environment_spec.rb +16 -0
  126. data/spec/features/end_deployment_spec.rb +29 -0
  127. data/spec/features/get_environment_spec.rb +19 -0
  128. data/spec/features/get_environments_spec.rb +20 -0
  129. data/spec/features/record_deployment_spec.rb +28 -0
  130. data/spec/features/update_environment_spec.rb +44 -0
  131. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  132. data/spec/fixtures/dashboard.json +4 -2
  133. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  134. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  135. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  136. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  137. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  138. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  139. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  140. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  141. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  142. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  143. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  144. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  145. data/spec/lib/pact_broker/domain/webhook_spec.rb +1 -1
  146. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  147. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  148. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  149. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  150. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  151. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  152. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +20 -7
  153. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  154. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  155. data/spec/lib/pact_broker/pacts/service_spec.rb +2 -2
  156. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  157. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  158. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  159. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  160. data/spec/lib/rack/pact_broker/set_base_url_spec.rb +86 -0
  161. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  162. data/spec/migrations/change_migration_strategy_spec.rb +3 -3
  163. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  164. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  165. data/spec/spec_helper.rb +17 -5
  166. data/spec/support/approvals.rb +24 -0
  167. data/spec/support/shared_examples_for_responses.rb +11 -0
  168. data/tasks/database.rb +1 -1
  169. data/tasks/db.rake +1 -0
  170. data/tasks/rspec.rake +1 -1
  171. data/vendor/hal-browser/styles.css +6 -0
  172. metadata +70 -11
@@ -67,7 +67,7 @@ module PactBroker
67
67
  it "only returns the pacts for the consumer" do
68
68
  expect(subject.size).to eq 1
69
69
  expect(subject.first.consumer.name).to eq "Foo"
70
- expect(subject.first.selectors.first).to eq selector.resolve(PactBroker::Domain::Version.for("Foo", "1"))
70
+ expect(subject.first.selectors.first).to eq selector.resolve_for_fallback(PactBroker::Domain::Version.for("Foo", "1"))
71
71
  end
72
72
  end
73
73
  end
@@ -74,7 +74,7 @@ module PactBroker
74
74
 
75
75
  it "returns the latest pact for each consumer" do
76
76
  expect(subject.size).to eq 1
77
- expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [pact_selector_1.resolve(PactBroker::Domain::Version.find(number: "2"))]
77
+ expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [pact_selector_1.resolve(PactBroker::Domain::Version.for("Foo1", "2"))]
78
78
  end
79
79
  end
80
80
 
@@ -0,0 +1,224 @@
1
+ require 'pact_broker/pacts/repository'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe Repository do
6
+ describe "find_wip_pact_versions_for_provider by branch" do
7
+ # let(:provider_tags) { %w[dev] }
8
+ let(:provider_tags) { [] }
9
+ let(:provider_version_branch) { "dev" }
10
+ let(:options) { { include_wip_pacts_since: include_wip_pacts_since } }
11
+ let(:include_wip_pacts_since) { (Date.today - 1).to_datetime }
12
+
13
+ subject { Repository.new.find_wip_pact_versions_for_provider("bar", provider_version_branch, provider_tags, options) }
14
+
15
+ context "when there are no tags or branch" do
16
+ let(:provider_tags) { [] }
17
+ let(:provider_version_branch) { nil }
18
+
19
+ it "returns an empty list" do
20
+ expect(subject).to eq []
21
+ end
22
+ end
23
+
24
+ context "when there are multiple wip pacts" do
25
+ before do
26
+ td.create_provider("bar")
27
+ .create_provider_version("333", branch: provider_version_branch)
28
+ .add_day
29
+ .create_pact_with_hierarchy("foo", "1", "bar")
30
+ .create_consumer_version_tag("feat-1")
31
+ .add_day
32
+ .create_consumer_version("2", branch: "branch-1")
33
+ .create_pact
34
+ .create_pact_with_hierarchy("meep", "2", "bar")
35
+ .create_consumer_version_tag("feat-2")
36
+ .add_day
37
+ .create_pact_with_hierarchy("foo", "3", "bar")
38
+ .create_consumer_version_tag("feat-2")
39
+ .add_day
40
+ .create_pact_with_hierarchy("meep", "1", "bar")
41
+ .create_consumer_version_tag("feat-1")
42
+ end
43
+
44
+ it "sorts them" do
45
+ expect(subject[0].consumer_name).to eq "foo"
46
+ expect(subject[0].consumer_version_number).to eq "1"
47
+
48
+ expect(subject[1].consumer_name).to eq "foo"
49
+ expect(subject[1].consumer_version_number).to eq "2"
50
+
51
+ expect(subject[2].consumer_name).to eq "foo"
52
+ expect(subject[2].consumer_version_number).to eq "3"
53
+
54
+ expect(subject[3].consumer_name).to eq "meep"
55
+ expect(subject[3].consumer_version_number).to eq "2"
56
+
57
+ expect(subject[4].consumer_name).to eq "meep"
58
+ expect(subject[4].consumer_version_number).to eq "1"
59
+ end
60
+
61
+ it "sets the selectors" do
62
+ expect(subject[0].selectors).to eq Selectors.create_for_latest_for_tag("feat-1")
63
+ expect(subject[1].selectors).to eq Selectors.create_for_latest_for_branch("branch-1")
64
+ expect(subject[2].selectors).to eq Selectors.create_for_latest_for_tag("feat-2")
65
+ expect(subject[3].selectors).to eq Selectors.create_for_latest_for_tag("feat-2")
66
+ expect(subject[4].selectors).to eq Selectors.create_for_latest_for_tag("feat-1")
67
+ end
68
+ end
69
+
70
+ context "when the latest pact for a tag has been successfully verified by the given provider branch" do
71
+ before do
72
+ td.create_pact_with_hierarchy("foo", "1", "bar")
73
+ .comment("above not included because it's not the latest prod")
74
+ .create_consumer_version("2")
75
+ .create_consumer_version_tag("prod")
76
+ .create_pact
77
+ .create_verification(provider_version: "3", branch: provider_version_branch, comment: "not included because already verified")
78
+ end
79
+
80
+ it "is not included" do
81
+ expect(subject.size).to be 0
82
+ end
83
+ end
84
+
85
+ context "when the latest pact for a tag has been successfully verified by the given provider tag but it was a WIP verification" do
86
+ before do
87
+ td.create_provider("bar")
88
+ .create_provider_version("333", branch: provider_version_branch)
89
+ .add_day
90
+ .create_pact_with_hierarchy("foo", "1", "bar")
91
+ .comment("above not included because it's not the latest")
92
+ .create_consumer_version("2")
93
+ .create_consumer_version_tag("feat-1")
94
+ .create_pact
95
+ .create_verification(wip: true, success: true, provider_version: "3", branch: provider_version_branch)
96
+ end
97
+
98
+ it "it is included" do
99
+ expect(subject[0].consumer_name).to eq "foo"
100
+ expect(subject[0].consumer_version_number).to eq "2"
101
+ end
102
+ end
103
+
104
+ context "when a pact is the latest for a tag and a branch and has no successful verifications" do
105
+ before do
106
+ td.create_provider("bar")
107
+ .create_provider_version("333", branch: provider_version_branch)
108
+ .add_day
109
+ .create_consumer("foo")
110
+ .create_consumer_version("1", branch: "branch-1", tag_names: ["feat-1"])
111
+ .comment("above not included because it's not the latest")
112
+ .create_consumer_version("2", branch: "branch-1", tag_names: ["feat-1"])
113
+ .create_pact
114
+ end
115
+
116
+ it "it has two selectors" do
117
+ expect(subject.size).to eq 1
118
+ expect(subject.first.selectors).to eq Selectors.new([Selector.latest_for_branch("branch-1"), Selector.latest_for_tag("feat-1")])
119
+ end
120
+ end
121
+
122
+ context "when the latest pact for a tag has failed verification from the specified provider version branch" do
123
+ before do
124
+ td.create_provider("bar")
125
+ .create_provider_version("333")
126
+ .create_provider_version_tag("dev")
127
+ .add_day
128
+ .create_pact_with_hierarchy("foo", "1", "bar")
129
+ .create_consumer_version_tag("feat-1")
130
+ .create_verification(provider_version: "3", success: false, branch: provider_version_branch)
131
+ .add_day
132
+ .create_consumer_version("2", branch: "branch-1")
133
+ .create_pact
134
+ .create_verification(provider_version: "3", success: false, branch: provider_version_branch)
135
+
136
+ end
137
+
138
+ it "is included" do
139
+ expect(subject.size).to be 2
140
+ end
141
+
142
+ it "sets the pending tags" do
143
+ expect(subject.first.provider_branch).to eq provider_version_branch
144
+ expect(subject.last.provider_branch).to eq provider_version_branch
145
+ end
146
+ end
147
+
148
+ context "when there are no consumer tags" do
149
+ before do
150
+ td.create_pact_with_hierarchy("foo", "1", "bar")
151
+ .create_verification(provider_version: "3", success: false, branch: provider_version_branch)
152
+ end
153
+
154
+ it "returns an empty list" do
155
+ expect(subject).to eq []
156
+ end
157
+ end
158
+
159
+ context "when the latest pact for a tag has successful then failed verifications" do
160
+ before do
161
+ td.create_provider("bar")
162
+ .create_provider_version("333")
163
+ .create_provider_version_tag("dev")
164
+ .add_day
165
+ .create_pact_with_hierarchy("foo", "1", "bar")
166
+ .create_consumer_version_tag("dev")
167
+ .create_verification(provider_version: "3", success: true, branch: provider_version_branch)
168
+ .create_verification(provider_version: "5", success: false, number: 2, branch: provider_version_branch)
169
+ end
170
+
171
+ it "is not included, but maybe it should be? can't really work out a scenario where this is likely to happen" do
172
+ expect(subject).to eq []
173
+ end
174
+ end
175
+
176
+ context "when the latest pact for a tag has not been verified" do
177
+ before do
178
+ td.create_provider("bar")
179
+ .create_provider_version("333")
180
+ .create_provider_version_tag("dev")
181
+ .add_day
182
+ .create_pact_with_hierarchy("foo", "1", "bar")
183
+ .create_consumer_version_tag("feat-1")
184
+ end
185
+
186
+ it "is included" do
187
+ expect(subject.size).to be 1
188
+ end
189
+
190
+ it "sets the pending tags" do
191
+ expect(subject.first.provider_branch).to eq provider_version_branch
192
+ end
193
+ end
194
+
195
+ context "when the provider name does not match the given provider name" do
196
+ before do
197
+ td.create_pact_with_hierarchy("foo", "1", "baz")
198
+ .create_provider("bar")
199
+ end
200
+
201
+ it "is not included" do
202
+ expect(subject.size).to be 0
203
+ end
204
+ end
205
+
206
+ context "when the pact was published before the specified include_wip_pacts_since" do
207
+ before do
208
+ td.create_provider("bar")
209
+ .create_provider_version("333", branch: provider_version_branch)
210
+ .add_day
211
+ .create_pact_with_hierarchy("foo", "1", "bar")
212
+ .create_consumer_version_tag("prod")
213
+ end
214
+
215
+ let(:include_wip_pacts_since) { (Date.today + 3).to_datetime }
216
+
217
+ it "is not included" do
218
+ expect(subject.size).to be 0
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
@@ -5,10 +5,11 @@ module PactBroker
5
5
  describe Repository do
6
6
  describe "find_wip_pact_versions_for_provider" do
7
7
  let(:provider_tags) { %w[dev] }
8
+ let(:provider_version_branch) { nil }
8
9
  let(:options) { { include_wip_pacts_since: include_wip_pacts_since } }
9
10
  let(:include_wip_pacts_since) { (Date.today - 1).to_datetime }
10
11
 
11
- subject { Repository.new.find_wip_pact_versions_for_provider("bar", provider_tags, options) }
12
+ subject { Repository.new.find_wip_pact_versions_for_provider("bar", provider_version_branch, provider_tags, options) }
12
13
 
13
14
  context "when there are no tags" do
14
15
  let(:provider_tags) { [] }
@@ -21,16 +22,17 @@ module PactBroker
21
22
  context "when there are multiple wip pacts" do
22
23
  before do
23
24
  td.create_provider("bar")
24
- .create_provider_version("333")
25
- .create_provider_version_tag("dev")
25
+ .create_provider_version("333", tag_names: provider_tags)
26
26
  .add_day
27
27
  .create_pact_with_hierarchy("foo", "1", "bar")
28
28
  .create_consumer_version_tag("feat-1")
29
29
  .add_day
30
+ .create_consumer_version("2", branch: "branch-1")
31
+ .create_pact
30
32
  .create_pact_with_hierarchy("meep", "2", "bar")
31
33
  .create_consumer_version_tag("feat-2")
32
34
  .add_day
33
- .create_pact_with_hierarchy("foo", "2", "bar")
35
+ .create_pact_with_hierarchy("foo", "3", "bar")
34
36
  .create_consumer_version_tag("feat-2")
35
37
  .add_day
36
38
  .create_pact_with_hierarchy("meep", "1", "bar")
@@ -46,11 +48,22 @@ module PactBroker
46
48
  expect(subject[1].consumer_name).to eq "foo"
47
49
  expect(subject[1].consumer_version_number).to eq "2"
48
50
 
49
- expect(subject[2].consumer_name).to eq "meep"
50
- expect(subject[2].consumer_version_number).to eq "2"
51
+ expect(subject[2].consumer_name).to eq "foo"
52
+ expect(subject[2].consumer_version_number).to eq "3"
51
53
 
52
54
  expect(subject[3].consumer_name).to eq "meep"
53
- expect(subject[3].consumer_version_number).to eq "1"
55
+ expect(subject[3].consumer_version_number).to eq "2"
56
+
57
+ expect(subject[4].consumer_name).to eq "meep"
58
+ expect(subject[4].consumer_version_number).to eq "1"
59
+ end
60
+
61
+ it "sets the selectors" do
62
+ expect(subject[0].selectors).to eq Selectors.create_for_latest_for_tag("feat-1")
63
+ expect(subject[1].selectors).to eq Selectors.create_for_latest_for_branch("branch-1")
64
+ expect(subject[2].selectors).to eq Selectors.create_for_latest_for_tag("feat-2")
65
+ expect(subject[3].selectors).to eq Selectors.create_for_latest_for_tag("feat-2")
66
+ expect(subject[4].selectors).to eq Selectors.create_for_latest_for_tag("feat-1")
54
67
  end
55
68
  end
56
69
 
@@ -6,6 +6,7 @@ module PactBroker
6
6
  describe "<=>" do
7
7
  let(:overall_latest_1) { Selector.overall_latest }
8
8
  let(:overall_latest_2) { Selector.overall_latest }
9
+ let(:latest_for_branch_main) { Selector.latest_for_branch('main') }
9
10
  let(:latest_for_tag_prod) { Selector.latest_for_tag('prod') }
10
11
  let(:latest_for_tag_dev) { Selector.latest_for_tag('dev') }
11
12
  let(:all_prod_for_consumer_1) { Selector.all_for_tag_and_consumer('prod', 'Foo') }
@@ -15,11 +16,11 @@ module PactBroker
15
16
  let(:all_dev) { Selector.all_for_tag('dev') }
16
17
 
17
18
  let(:unsorted_selectors) do
18
- [all_prod, all_dev, all_dev_for_consumer_1, latest_for_tag_prod, overall_latest_1, overall_latest_1, latest_for_tag_dev, all_prod_for_consumer_2, all_prod_for_consumer_1]
19
+ [all_prod, all_dev, all_dev_for_consumer_1, latest_for_branch_main, latest_for_tag_prod, overall_latest_1, overall_latest_1, latest_for_tag_dev, all_prod_for_consumer_2, all_prod_for_consumer_1]
19
20
  end
20
21
 
21
22
  let(:expected_sorted_selectors) do
22
- [overall_latest_1, overall_latest_1, latest_for_tag_dev, latest_for_tag_prod, all_dev_for_consumer_1, all_prod_for_consumer_2, all_prod_for_consumer_1, all_dev, all_prod]
23
+ [overall_latest_1, overall_latest_1, latest_for_branch_main, latest_for_tag_dev, latest_for_tag_prod, all_dev_for_consumer_1, all_prod_for_consumer_2, all_prod_for_consumer_1, all_dev, all_prod]
23
24
  end
24
25
 
25
26
  it "sorts the selectors" do
@@ -2,9 +2,7 @@ require 'spec_helper'
2
2
  require 'pact_broker/pacts/service'
3
3
  require 'pact_broker/pacts/pact_params'
4
4
 
5
-
6
5
  module PactBroker
7
-
8
6
  module Pacts
9
7
  describe Service do
10
8
  let(:td) { TestDataBuilder.new }
@@ -38,13 +36,14 @@ module PactBroker
38
36
 
39
37
  let(:provider_name) { "Bar" }
40
38
  let(:provider_version_tags) { [] }
39
+ let(:provider_version_branch) { "main" }
41
40
  let(:consumer_version_selectors) { [] }
42
41
 
43
42
  before do
44
43
  allow(pact_repository).to receive(:find_for_verification).and_return(head_pacts)
45
44
  end
46
45
 
47
- subject { Service.find_for_verification(provider_name, provider_version_tags, consumer_version_selectors) }
46
+ subject { Service.find_for_verification(provider_name, provider_version_branch, provider_version_tags, consumer_version_selectors) }
48
47
  end
49
48
  end
50
49
  end
@@ -172,7 +172,7 @@ module PactBroker
172
172
 
173
173
  let(:options) { { } }
174
174
 
175
- subject { Service.find_for_verification("Bar", ["master"], Selectors.new, options) }
175
+ subject { Service.find_for_verification("Bar", nil, ["master"], Selectors.new, options) }
176
176
 
177
177
 
178
178
  context "when the consumer version tags are empty" do
@@ -209,7 +209,7 @@ module PactBroker
209
209
  .republish_same_pact(comment: "overall latest")
210
210
  end
211
211
 
212
- subject { Service.find_for_verification("Wiffle", ["master"], Selectors.new, options) }
212
+ subject { Service.find_for_verification("Wiffle", "main", ["master"], Selectors.new, options) }
213
213
 
214
214
  it "is not included" do
215
215
  expect(subject.size).to eq 1
@@ -7,6 +7,7 @@ module PactBroker
7
7
  describe VerifiablePactMessages do
8
8
  let(:pending_provider_tags) { [] }
9
9
  let(:non_pending_provider_tags) { [] }
10
+ let(:provider_branch) { nil }
10
11
  let(:pending) { false }
11
12
  let(:wip) { false }
12
13
  let(:selectors) { Selectors.new }
@@ -20,7 +21,8 @@ module PactBroker
20
21
  non_pending_provider_tags: non_pending_provider_tags,
21
22
  pending?: pending,
22
23
  wip?: wip,
23
- selectors: selectors
24
+ selectors: selectors,
25
+ provider_branch: provider_branch
24
26
  )
25
27
  end
26
28
 
@@ -35,7 +37,18 @@ module PactBroker
35
37
  context "when there is 1 head consumer tags" do
36
38
  let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[dev]) }
37
39
  its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact for a consumer version tagged 'dev'" }
38
- its(:pact_description) { is_expected.to eq "Pact between Foo and Bar, consumer version 123, latest dev"}
40
+ its(:pact_description) { is_expected.to eq "Pact between Foo and Bar, consumer version 123, latest with tag dev"}
41
+ end
42
+
43
+ context "when there are branches" do
44
+ let(:selectors) { Selectors.create_for_latest_of_each_branch(%w[main feat-x]) }
45
+ its(:inclusion_reason) { is_expected.to include "latest pact for a consumer version from branch 'feat-x', latest pact for a consumer version from branch 'main'" }
46
+ its(:pact_description) { is_expected.to eq "Pact between Foo and Bar, consumer version 123, latest from branch main, latest from branch feat-x"}
47
+ end
48
+
49
+ context "when there are branches and tags" do
50
+ let(:selectors) { Selectors.new([Selector.latest_for_branch("main"), Selector.latest_for_tag("prod")]) }
51
+ its(:inclusion_reason) { is_expected.to include "latest pact for a consumer version from branch 'main', latest pact for a consumer version tagged 'prod'" }
39
52
  end
40
53
 
41
54
  context "when there are 2 head consumer tags" do
@@ -53,13 +66,30 @@ module PactBroker
53
66
  its(:inclusion_reason) { is_expected.to include "latest pact for a consumer version tagged 'master' (fallback tag used as no pact was found with tag 'feat-x')" }
54
67
  end
55
68
 
56
- context "when the pact is a WIP pact" do
69
+ context "when the pact was selected by the fallback tag" do
70
+ let(:selectors) { Selectors.new(Selector.latest_for_branch_with_fallback("feat-x", "master")) }
71
+ its(:inclusion_reason) { is_expected.to include "latest pact for a consumer version from branch 'master' (fallback branch used as no pact was found from branch 'feat-x')" }
72
+ end
73
+
74
+ context "when the pact is a WIP pact for the specified provider tags" do
57
75
  let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[feat-x]) }
58
76
  let(:wip) { true }
59
77
  let(:pending) { true }
60
78
  let(:pending_provider_tags) { %w[dev] }
61
79
 
62
80
  its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is a 'work in progress' pact (ie. it is the pact for the latest version of Foo tagged with 'feat-x' and is still in pending state)."}
81
+
82
+ context "when the pact is a WIP pact for a consumer branch" do
83
+ let(:selectors) { Selectors.create_for_latest_of_each_branch(%w[feat-x feat-y]) }
84
+
85
+ its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is a 'work in progress' pact (ie. it is the pact for the latest versions of Foo from branches 'feat-x' and 'feat-y' (both have the same content) and is still in pending state)."}
86
+ end
87
+
88
+ context "when the pact is a WIP pact for a consumer branch and consumer rags" do
89
+ let(:selectors) { Selectors.create_for_latest_of_each_branch(%w[feat-x feat-y]) + Selectors.create_for_latest_of_each_tag(%w[feat-z feat-w]) }
90
+
91
+ its(:inclusion_reason) { is_expected.to include "it is the pact for the latest versions of Foo from branches 'feat-x' and 'feat-y' and tagged with 'feat-z' and 'feat-w' (all have the same content)"}
92
+ end
63
93
  end
64
94
 
65
95
  context "when the pact is one of all versions for a tag" do
@@ -74,13 +104,19 @@ module PactBroker
74
104
  its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: pacts for all Foo versions tagged 'prod'"}
75
105
  end
76
106
 
77
- context "when the pact is the latest versions for a tag and consumer" do
107
+ context "when the pact is the latest version for a tag and consumer" do
78
108
  let(:selectors) { Selectors.new(Selector.latest_for_tag_and_consumer('prod', 'Foo')) }
79
109
 
80
110
  its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact for a version of Foo tagged 'prod'"}
81
111
  end
82
112
 
83
- context "when the pact is the latest version for and consumer" do
113
+ context "when the pact is the latest version for a branch and consumer" do
114
+ let(:selectors) { Selectors.new(Selector.latest_for_branch_and_consumer('main', 'Foo')) }
115
+
116
+ its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact for a version of Foo from branch 'main'"}
117
+ end
118
+
119
+ context "when the pact is the latest version for a consumer" do
84
120
  let(:selectors) { Selectors.new(Selector.latest_for_consumer('Foo')) }
85
121
 
86
122
  its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact between Foo and Bar"}
@@ -89,7 +125,7 @@ module PactBroker
89
125
 
90
126
  describe "#pending_reason" do
91
127
  context "when the pact is not pending" do
92
- context "when there are no non_pending_provider_tags" do
128
+ context "when there are no non_pending_provider_tags or a provider branch" do
93
129
  its(:pending_reason) { is_expected.to include "This pact has previously been successfully verified by Bar. If this verification fails, it will fail the build." }
94
130
  end
95
131
 
@@ -98,15 +134,26 @@ module PactBroker
98
134
 
99
135
  its(:pending_reason) { is_expected.to include "This pact has previously been successfully verified by a version of Bar with tag 'dev'. If this verification fails, it will fail the build."}
100
136
  end
137
+
138
+ context "when there is a provider branch" do
139
+ let(:provider_branch) { "main" }
140
+ let(:non_pending_provider_tags) { %w[dev] }
141
+
142
+ # uses branch in preference as that's what the WIP pacts logic does
143
+ its(:pending_reason) { is_expected.to include "This pact has previously been successfully verified by a version of Bar from branch 'main'. If this verification fails, it will fail the build."}
144
+ end
101
145
  end
102
146
 
103
147
  context "when the pact is pending" do
104
148
  let(:pending) { true }
105
149
 
106
- context "when there are no pending_provider_tags" do
107
- context "when there are no non_pending_provider_tags" do
108
- its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for Bar has not yet been published. If this verification fails, it will not cause the overall build to fail." }
109
- end
150
+ context "when there are no non_pending_provider_tags or a provider_branch" do
151
+ its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for Bar has not yet been published. If this verification fails, it will not cause the overall build to fail." }
152
+ end
153
+
154
+ context "when there is a provider_branch" do
155
+ let(:provider_branch) { "main" }
156
+ its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for a version of Bar from branch 'main' has not yet been published. If this verification fails, it will not cause the overall build to fail." }
110
157
  end
111
158
 
112
159
  context "when there is 1 pending_provider_tag" do