pact_broker 2.75.0 → 2.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/test-ruby-3.yml +19 -0
  4. data/.github/workflows/test.yml +19 -4
  5. data/.gitignore +3 -1
  6. data/CHANGELOG.md +48 -0
  7. data/DEVELOPER_SETUP.md +62 -3
  8. data/Dockerfile +1 -0
  9. data/ISSUES.md +13 -5
  10. data/README.md +1 -1
  11. data/config.ru +1 -0
  12. data/db/ddl_statements/head_pact_tags.rb +24 -1
  13. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  14. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  15. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  16. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  17. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  18. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  19. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  20. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  21. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  22. data/db/migrations/20210210_create_environments_table.rb +16 -0
  23. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +44 -0
  24. data/lib/pact_broker/api.rb +7 -2
  25. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  26. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  27. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  28. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  29. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  30. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  31. data/lib/pact_broker/api/decorators/matrix_decorator.rb +8 -2
  32. data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -2
  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/paths.rb +5 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +15 -2
  38. data/lib/pact_broker/api/resources/environment.rb +76 -0
  39. data/lib/pact_broker/api/resources/environments.rb +75 -0
  40. data/lib/pact_broker/api/resources/index.rb +20 -0
  41. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  42. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  43. data/lib/pact_broker/api/resources/verifications.rb +5 -2
  44. data/lib/pact_broker/api/resources/version.rb +15 -9
  45. data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
  46. data/lib/pact_broker/app.rb +3 -0
  47. data/lib/pact_broker/certificates/certificate.rb +1 -1
  48. data/lib/pact_broker/config/setting.rb +1 -1
  49. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  50. data/lib/pact_broker/configuration.rb +18 -1
  51. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  52. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  53. data/lib/pact_broker/db/migrate_data.rb +1 -0
  54. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  55. data/lib/pact_broker/deployments/environment.rb +15 -0
  56. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  57. data/lib/pact_broker/doc/controllers/app.rb +1 -1
  58. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  59. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  60. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  61. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  62. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  63. data/lib/pact_broker/domain/index_item.rb +18 -4
  64. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  65. data/lib/pact_broker/domain/tag.rb +131 -71
  66. data/lib/pact_broker/domain/verification.rb +3 -2
  67. data/lib/pact_broker/domain/version.rb +58 -23
  68. data/lib/pact_broker/domain/webhook.rb +12 -9
  69. data/lib/pact_broker/hash_refinements.rb +4 -0
  70. data/lib/pact_broker/index/service.rb +55 -49
  71. data/lib/pact_broker/locale/en.yml +3 -1
  72. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  73. data/lib/pact_broker/metrics/service.rb +1 -1
  74. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  75. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  76. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  77. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  78. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  79. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  80. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  81. data/lib/pact_broker/pacts/repository.rb +5 -231
  82. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  83. data/lib/pact_broker/pacts/selector.rb +56 -1
  84. data/lib/pact_broker/pacts/selectors.rb +16 -0
  85. data/lib/pact_broker/pacts/service.rb +6 -8
  86. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  87. data/lib/pact_broker/pacts/verifiable_pact.rb +45 -2
  88. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  89. data/lib/pact_broker/repositories/helpers.rb +4 -0
  90. data/lib/pact_broker/services.rb +9 -0
  91. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  92. data/lib/pact_broker/tags/repository.rb +3 -1
  93. data/lib/pact_broker/tags/service.rb +0 -3
  94. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  95. data/lib/pact_broker/test/http_test_data_builder.rb +101 -35
  96. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  97. data/lib/pact_broker/ui/app.rb +6 -0
  98. data/lib/pact_broker/ui/controllers/base_controller.rb +5 -1
  99. data/lib/pact_broker/ui/controllers/pacts.rb +18 -0
  100. data/lib/pact_broker/ui/view_models/index_item.rb +9 -0
  101. data/lib/pact_broker/ui/view_models/matrix_line.rb +36 -0
  102. data/lib/pact_broker/ui/views/index/show-with-tags.haml +8 -0
  103. data/lib/pact_broker/ui/views/matrix/show.haml +10 -0
  104. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  105. data/lib/pact_broker/verifications/service.rb +2 -1
  106. data/lib/pact_broker/version.rb +1 -1
  107. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  108. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  109. data/lib/pact_broker/versions/repository.rb +22 -2
  110. data/lib/pact_broker/versions/service.rb +5 -1
  111. data/lib/pact_broker/webhooks/execution.rb +3 -2
  112. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  113. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  114. data/lib/pact_broker/webhooks/service.rb +8 -7
  115. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  116. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  117. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  118. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  119. data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
  120. data/lib/pact_broker/webhooks/webhook_request_logger.rb +5 -1
  121. data/lib/rack/pact_broker/set_base_url.rb +22 -0
  122. data/lib/sequel/plugins/upsert.rb +18 -4
  123. data/public/stylesheets/index.css +22 -1
  124. data/public/stylesheets/matrix.css +0 -21
  125. data/regression/can_i_deploy_spec.rb +5 -4
  126. data/regression/index_spec.rb +26 -0
  127. data/regression/regression_helper.rb +29 -3
  128. data/regression/script/clear.sh +3 -0
  129. data/regression/script/run.sh +3 -0
  130. data/script/demonstrate-version-branches.rb +33 -0
  131. data/script/pry.rb +2 -2
  132. data/script/reproduce-issue-starting-up.rb +13 -23
  133. data/script/reproduce-issue.rb +18 -14
  134. data/script/trigger-release.sh +1 -1
  135. data/script/webhook-server.ru +5 -5
  136. data/spec/features/create_environment_spec.rb +47 -0
  137. data/spec/features/create_tag_spec.rb +32 -0
  138. data/spec/features/create_version_spec.rb +70 -0
  139. data/spec/features/delete_environment_spec.rb +16 -0
  140. data/spec/features/end_deployment_spec.rb +29 -0
  141. data/spec/features/get_environment_spec.rb +19 -0
  142. data/spec/features/get_environments_spec.rb +20 -0
  143. data/spec/features/record_deployment_spec.rb +28 -0
  144. data/spec/features/update_environment_spec.rb +44 -0
  145. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  146. data/spec/fixtures/dashboard.json +4 -2
  147. data/spec/integration/ui/index_spec.rb +4 -4
  148. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  149. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  150. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  151. data/spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb +6 -6
  152. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  153. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  154. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  155. data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +1 -12
  156. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  157. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  158. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  159. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  160. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  161. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  162. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
  163. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  164. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  165. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  166. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  167. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  168. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  169. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  170. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  171. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  172. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +46 -7
  173. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  174. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  175. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  176. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  177. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  178. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  179. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  180. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  181. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  182. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  183. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  184. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  185. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  186. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  187. data/spec/spec_helper.rb +17 -5
  188. data/spec/support/approvals.rb +24 -0
  189. data/spec/support/shared_examples_for_responses.rb +11 -0
  190. data/tasks/db.rake +1 -0
  191. data/tasks/rspec.rake +1 -1
  192. metadata +69 -4
  193. data/docker-compose-issue-repro.yml +0 -22
@@ -0,0 +1,27 @@
1
+ require_relative 'migration_helper'
2
+
3
+ include PactBroker::MigrationHelper
4
+
5
+ Sequel.migration do
6
+ up do
7
+ if postgres?
8
+ run("CREATE INDEX tags_pacticipant_id_name_version_order_desc_index ON tags (pacticipant_id, name, version_order DESC);")
9
+ run("CREATE INDEX versions_pacticipant_id_order_desc_index ON versions (pacticipant_id, \"order\" DESC);")
10
+ else
11
+ alter_table(:tags) do
12
+ add_index([:pacticipant_id, :name, :version_order], name: "tags_pacticipant_id_name_version_order_index")
13
+ end
14
+ end
15
+ end
16
+
17
+ down do
18
+ if postgres?
19
+ run("DROP INDEX tags_pacticipant_id_name_version_order_desc_index")
20
+ run("DROP INDEX versions_pacticipant_id_order_desc_index")
21
+ else
22
+ alter_table(:tags) do
23
+ drop_index([:pacticipant_id, :name, :version_order], name: "tags_pacticipant_id_name_version_order_index")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_or_replace_view(:latest_verification_ids_for_consumer_version_tags,
6
+ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V4)
7
+ end
8
+
9
+ down do
10
+ create_or_replace_view(:latest_verification_ids_for_consumer_version_tags,
11
+ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V3)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_or_replace_view(:latest_tagged_pact_consumer_version_orders,
6
+ latest_tagged_pact_consumer_version_orders_v4(self))
7
+ end
8
+
9
+ down do
10
+ create_or_replace_view(:latest_tagged_pact_consumer_version_orders,
11
+ latest_tagged_pact_consumer_version_orders_v3(self))
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ Sequel.migration do
2
+ change do
3
+ create_table(:environments, charset: 'utf8') do
4
+ primary_key :id
5
+ String :uuid, nullable: false
6
+ String :name, nullable: false
7
+ String :display_name
8
+ Boolean :production, nullable: false
9
+ String :contacts
10
+ DateTime :created_at, nullable: false
11
+ DateTime :updated_at, nullable: false
12
+ index [:uuid], unique: true, name: "environments_uuid_index"
13
+ index [:name], unique: true, name: "environments_name_index"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ version: "3"
2
+
3
+ services:
4
+ postgres:
5
+ image: postgres
6
+ healthcheck:
7
+ test: psql postgres --command "select 1" -U postgres
8
+ environment:
9
+ POSTGRES_USER: postgres
10
+ POSTGRES_PASSWORD: password
11
+ POSTGRES_DB: postgres
12
+
13
+ pact-broker:
14
+ image: pactfoundation/pact-broker:2.76.0.0
15
+ ports:
16
+ - "9292:9292"
17
+ # depends_on:
18
+ # - postgres
19
+ environment:
20
+ PACT_BROKER_PORT: '9292'
21
+ #PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
22
+ PACT_BROKER_DATABASE_URL: "sqlite:////tmp/pact_broker.sqlite3"
23
+ PACT_BROKER_LOG_LEVEL: INFO
24
+ PACT_BROKER_SQL_LOG_LEVEL: DEBUG
25
+ PACT_BROKER_WEBHOOK_SCHEME_WHITELIST: "http https"
26
+ PACT_BROKER_WEBHOOK_HOST_WHITELIST: "/.*/"
27
+
28
+ repro-issue:
29
+ build: .
30
+ depends_on:
31
+ - pact-broker
32
+ command: -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
33
+ entrypoint: dockerize
34
+ environment:
35
+ - PACT_BROKER_BASE_URL=http://pact-broker:9292
36
+ volumes:
37
+ - $PWD:/home
38
+ working_dir: /home
39
+
40
+ webhook-server:
41
+ build: .
42
+ entrypoint: ["/bin/sh", "-c", "bundle exec rackup -p 9393 -o 0.0.0.0 /home/script/webhook-server.ru"]
43
+ volumes:
44
+ - ./script/webhook-server.ru:/home/script/webhook-server.ru
@@ -71,10 +71,10 @@ module PactBroker
71
71
  add ['pacticipants', :pacticipant_name], Api::Resources::Pacticipant, {resource_name: "pacticipant"}
72
72
  add ['pacticipants', :pacticipant_name, 'versions'], Api::Resources::Versions, {resource_name: "pacticipant_versions"}
73
73
  add ['pacticipants', :pacticipant_name, 'versions', :pacticipant_version_number], Api::Resources::Version, {resource_name: "pacticipant_version"}
74
- add ['pacticipants', :pacticipant_name, 'latest-version', :tag], Api::Resources::Version, {resource_name: "latest_tagged_pacticipant_version"}
74
+ add ['pacticipants', :pacticipant_name, 'latest-version', :tag], Api::Resources::LatestVersion, {resource_name: "latest_tagged_pacticipant_version"}
75
75
  add ['pacticipants', :pacticipant_name, 'latest-version', :tag, 'can-i-deploy', 'to', :to], Api::Resources::CanIDeployPacticipantVersion, { resource_name: "can_i_deploy_latest_tagged_version" }
76
76
  add ['pacticipants', :pacticipant_name, 'latest-version', :tag, 'can-i-deploy', 'to', :to, 'badge'], Api::Resources::CanIDeployBadge, { resource_name: "can_i_deploy_badge" }
77
- add ['pacticipants', :pacticipant_name, 'latest-version'], Api::Resources::Version, {resource_name: "latest_pacticipant_version"}
77
+ add ['pacticipants', :pacticipant_name, 'latest-version'], Api::Resources::LatestVersion, {resource_name: "latest_pacticipant_version"}
78
78
  add ['pacticipants', :pacticipant_name, 'versions', :pacticipant_version_number, 'tags', :tag_name], Api::Resources::Tag, {resource_name: "pacticipant_version_tag"}
79
79
  add ['pacticipants', :pacticipant_name, 'labels', :label_name], Api::Resources::Label, {resource_name: "pacticipant_label"}
80
80
 
@@ -105,6 +105,11 @@ module PactBroker
105
105
  add ['dashboard', 'provider', :provider_name, 'consumer', :consumer_name ], Api::Resources::Dashboard, {resource_name: "integration_dashboard"}
106
106
  add ['test','error'], Api::Resources::ErrorTest, {resource_name: "error_test"}
107
107
 
108
+ if PactBroker.feature_enabled?(:environments)
109
+ add ['environments'], Api::Resources::Environments, { resource_name: "environments" }
110
+ add ['environments', :environment_uuid], Api::Resources::Environment, { resource_name: "environment" }
111
+ end
112
+
108
113
  add ['integrations'], Api::Resources::Integrations, {resource_name: "integrations"}
109
114
  add ['integrations', 'provider', :provider_name, 'consumer', :consumer_name], Api::Resources::Integration, {resource_name: "integration"}
110
115
  add ['metrics'], Api::Resources::Metrics, {resource_name: 'metrics'}
@@ -13,6 +13,14 @@ module PactBroker
13
13
  predicate(:not_blank?) do | value |
14
14
  value && value.is_a?(String) && value.strip.size > 0
15
15
  end
16
+
17
+ predicate(:single_line?) do | value |
18
+ value && value.is_a?(String) && !value.include?("\n")
19
+ end
20
+
21
+ predicate(:no_spaces?) do | value |
22
+ value && value.is_a?(String) && !value.include?(" ")
23
+ end
16
24
  end
17
25
  end
18
26
  end
@@ -0,0 +1,49 @@
1
+ require 'dry-validation'
2
+ require 'pact_broker/api/contracts/dry_validation_workarounds'
3
+ require 'pact_broker/api/contracts/dry_validation_predicates'
4
+ require 'pact_broker/messages'
5
+
6
+ module PactBroker
7
+ module Api
8
+ module Contracts
9
+ class EnvironmentSchema
10
+ extend DryValidationWorkarounds
11
+ extend PactBroker::Messages
12
+ using PactBroker::HashRefinements
13
+
14
+ SCHEMA = Dry::Validation.Schema do
15
+ configure do
16
+ predicates(DryValidationPredicates)
17
+ config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
18
+ end
19
+ required(:name).filled(:str?, :single_line?, :no_spaces?)
20
+ required(:displayName).filled(:str?, :single_line?)
21
+ required(:production).filled(included_in?: [true, false])
22
+ optional(:contacts).each do
23
+ schema do
24
+ required(:name).filled(:str?, :single_line?)
25
+ optional(:details).schema do
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.call(params_with_string_keys)
32
+ params = params_with_string_keys&.symbolize_keys
33
+ results = select_first_message(flatten_indexed_messages(SCHEMA.call(params).messages(full: true)))
34
+ validate_name(params, results)
35
+ results
36
+ end
37
+
38
+ def self.validate_name(params, results)
39
+ if (environment_with_same_name = PactBroker::Deployments::EnvironmentService.find_by_name(params[:name]))
40
+ if environment_with_same_name.uuid != params[:uuid]
41
+ results[:name] ||= []
42
+ results[:name] << message('errors.validation.environment_name_must_be_unique', name: params[:name])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -3,6 +3,7 @@ require 'roar/json/hal'
3
3
  require 'pact_broker/api/pact_broker_urls'
4
4
  require 'pact_broker/api/decorators/decorator_context'
5
5
  require 'pact_broker/api/decorators/format_date_time'
6
+ require 'pact_broker/string_refinements'
6
7
 
7
8
  module PactBroker
8
9
  module Api
@@ -12,6 +13,16 @@ module PactBroker
12
13
  include Roar::JSON::HAL::Links
13
14
  include PactBroker::Api::PactBrokerUrls
14
15
  include FormatDateTime
16
+ using PactBroker::StringRefinements
17
+
18
+ def self.property(name, options={}, &block)
19
+ if options.delete(:camelize)
20
+ camelized_name = name.to_s.camelcase(false).to_sym
21
+ super(name, { as: camelized_name }.merge(options), &block)
22
+ else
23
+ super
24
+ end
25
+ end
15
26
  end
16
27
  end
17
28
  end
@@ -58,6 +58,7 @@ module PactBroker
58
58
  name: index_item.consumer_name,
59
59
  version: {
60
60
  number: index_item.consumer_version_number,
61
+ branch: index_item.consumer_version_branch,
61
62
  _links: {
62
63
  self: {
63
64
  href: version_url(base_url, index_item.consumer_version)
@@ -84,7 +85,10 @@ module PactBroker
84
85
  }
85
86
 
86
87
  if index_item.latest_verification
87
- hash[:version] = { number: index_item.provider_version_number }
88
+ hash[:version] = {
89
+ number: index_item.provider_version_number,
90
+ branch: index_item.provider_version_branch
91
+ }
88
92
  end
89
93
 
90
94
  hash
@@ -0,0 +1,30 @@
1
+ require_relative 'base_decorator'
2
+ require_relative 'timestamps'
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Decorators
7
+ class EnvironmentDecorator < BaseDecorator
8
+ property :uuid, writeable: false
9
+ property :name
10
+ property :display_name, camelize: true
11
+ property :production
12
+
13
+ collection :contacts, class: OpenStruct do
14
+ property :name
15
+ property :details
16
+ end
17
+
18
+ include Timestamps
19
+
20
+ link :self do | options |
21
+ {
22
+ title: 'Environment',
23
+ name: represented.name,
24
+ href: environment_url(represented, options[:base_url])
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ require 'pact_broker/api/decorators/base_decorator'
2
+ require 'pact_broker/api/decorators/environment_decorator'
3
+ require 'pact_broker/deployments/environment'
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Decorators
8
+ class EnvironmentsDecorator < BaseDecorator
9
+
10
+ collection :entries, :as => :environments, :class => PactBroker::Deployments::Environment, :extend => PactBroker::Api::Decorators::EnvironmentDecorator, embedded: true
11
+
12
+ link :self do | options |
13
+ {
14
+ title: 'Environments',
15
+ href: options[:resource_url]
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -39,7 +39,7 @@ module PactBroker
39
39
  query_results_with_deployment_status_summary
40
40
  .deployment_status_summary
41
41
  .reasons
42
- .collect{ | reason | ReasonDecorator.new(reason).to_s }
42
+ .collect{ | reason | reason_decorator_class.new(reason).to_s }
43
43
  .join("\n")
44
44
  end
45
45
 
@@ -47,6 +47,10 @@ module PactBroker
47
47
 
48
48
  attr_reader :query_results_with_deployment_status_summary
49
49
 
50
+ def reason_decorator_class
51
+ ReasonDecorator
52
+ end
53
+
50
54
  def matrix(base_url)
51
55
  query_results_with_deployment_status_summary.rows.collect do | line |
52
56
  provider = OpenStruct.new(name: line.provider_name)
@@ -71,6 +75,7 @@ module PactBroker
71
75
  name: line.consumer_name,
72
76
  version: {
73
77
  number: line.consumer_version_number,
78
+ branch: line.consumer_version_branch,
74
79
  _links: {
75
80
  self: {
76
81
  href: version_url(base_url, consumer_version)
@@ -87,7 +92,7 @@ module PactBroker
87
92
  end
88
93
 
89
94
  def tags(tags, base_url)
90
- tags.collect do | tag |
95
+ tags.sort_by(&:created_at).collect do | tag |
91
96
  {
92
97
  name: tag.name,
93
98
  latest: tag.latest?,
@@ -114,6 +119,7 @@ module PactBroker
114
119
  if !line.provider_version_number.nil?
115
120
  hash[:version] = {
116
121
  number: line.provider_version_number,
122
+ branch: line.provider_version_branch,
117
123
  _links: {
118
124
  self: {
119
125
  href: version_url(base_url, provider_version)
@@ -14,8 +14,8 @@ module PactBroker
14
14
  "There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
15
15
  when PactBroker::Matrix::PactNotVerifiedByRequiredProviderVersion
16
16
  "There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
17
- when PactBroker::Matrix::VerificationFailed
18
- "The verification between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
17
+ # when PactBroker::Matrix::VerificationFailed
18
+ # "The pact verification between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
19
19
  when PactBroker::Matrix::SpecifiedVersionDoesNotExist
20
20
  version_does_not_exist_description(reason.selector)
21
21
  when PactBroker::Matrix::VerificationFailed
@@ -12,9 +12,11 @@ module PactBroker
12
12
  using PactBroker::HashRefinements
13
13
 
14
14
  collection :provider_version_tags, default: []
15
+ property :provider_version_branch
15
16
 
16
17
  collection :consumer_version_selectors, default: PactBroker::Pacts::Selectors.new, class: PactBroker::Pacts::Selector do
17
18
  property :tag
19
+ property :branch
18
20
  property :latest,
19
21
  setter: ->(fragment:, represented:, **) {
20
22
  represented.latest = (fragment == 'true' || fragment == true)
@@ -6,9 +6,11 @@ module PactBroker
6
6
  module Decorators
7
7
  class VersionDecorator < BaseDecorator
8
8
 
9
- property :number
9
+ property :number, writeable: false
10
+ property :branch
11
+ property :build_url, as: :buildUrl
10
12
 
11
- collection :tags, embedded: true, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator
13
+ collection :tags, embedded: true, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator, class: OpenStruct
12
14
 
13
15
  include Timestamps
14
16
 
@@ -61,6 +63,17 @@ module PactBroker
61
63
  }]
62
64
  end
63
65
 
66
+ def from_hash(hash, options = {})
67
+ if hash["tags"]
68
+ updated_hash = hash.dup
69
+ updated_hash["_embedded"] ||= {}
70
+ updated_hash["_embedded"]["tags"] = updated_hash.delete("tags")
71
+ super(updated_hash, options)
72
+ else
73
+ super
74
+ end
75
+ end
76
+
64
77
  private
65
78
 
66
79
  def sorted_pacts
@@ -307,6 +307,14 @@ module PactBroker
307
307
  "#{base_url}/groups/#{url_encode(pacticipant_name)}"
308
308
  end
309
309
 
310
+ def environments_url(base_url = '')
311
+ "#{base_url}/environments"
312
+ end
313
+
314
+ def environment_url(environment, base_url = '')
315
+ "#{environments_url(base_url)}/#{environment.uuid}"
316
+ end
317
+
310
318
  def hal_browser_url target_url, base_url = ''
311
319
  "#{base_url}/hal-browser/browser.html#" + target_url
312
320
  end
@@ -4,9 +4,14 @@ module PactBroker
4
4
  PACT_BADGE_PATH = %r{^/pacts/provider/[^/]+/consumer/.*/badge(?:\.[A-Za-z]+)?$}.freeze
5
5
  MATRIX_BADGE_PATH = %r{^/matrix/provider/[^/]+/latest/[^/]+/consumer/[^/]+/latest/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
6
6
  CAN_I_DEPLOY_BADGE_PATH = %r{^/pacticipants/[^/]+/latest-version/[^/]+/can-i-deploy/to/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
7
+ VERIFICATION_RESULTS = %r{^/pacts/provider/[^/]+/consumer/[^/]+/pact-version/[^/]+/verification-results/[^/]+}
7
8
 
8
9
  extend self
9
10
 
11
+ def is_verification_results_path?(path)
12
+ path.start_with?('/pacts') && (path =~ VERIFICATION_RESULTS)
13
+ end
14
+
10
15
  def is_badge_path?(path)
11
16
  # Optimise by checking include? first - regexp slow
12
17
  path.include?('/badge') && (path =~ PACT_BADGE_PATH || path =~ MATRIX_BADGE_PATH || path =~ CAN_I_DEPLOY_BADGE_PATH)