pact_broker 2.76.1 → 2.79.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) 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 +50 -0
  8. data/DEVELOPER_DOCUMENTATION.md +13 -0
  9. data/DEVELOPER_SETUP.md +62 -3
  10. data/Dockerfile +1 -0
  11. data/ISSUES.md +12 -4
  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/docker-compose-issue-repro-with-pact-broker-docker-image.yml +16 -5
  26. data/lib/pact_broker/api.rb +7 -2
  27. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  28. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  29. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  30. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  31. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  32. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  33. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  34. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  35. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  36. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +18 -0
  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 +1 -1
  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 +22 -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/views/index/environment.markdown +37 -0
  58. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  59. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  60. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  61. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  62. data/lib/pact_broker/domain/index_item.rb +18 -4
  63. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  64. data/lib/pact_broker/domain/tag.rb +131 -71
  65. data/lib/pact_broker/domain/verification.rb +3 -2
  66. data/lib/pact_broker/domain/version.rb +58 -23
  67. data/lib/pact_broker/domain/webhook.rb +12 -9
  68. data/lib/pact_broker/hash_refinements.rb +4 -0
  69. data/lib/pact_broker/index/service.rb +55 -49
  70. data/lib/pact_broker/locale/en.yml +3 -1
  71. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  72. data/lib/pact_broker/metrics/service.rb +1 -1
  73. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  74. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  75. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  76. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  77. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  78. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  79. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  80. data/lib/pact_broker/pacts/repository.rb +5 -240
  81. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  82. data/lib/pact_broker/pacts/selector.rb +56 -1
  83. data/lib/pact_broker/pacts/selectors.rb +16 -0
  84. data/lib/pact_broker/pacts/service.rb +6 -8
  85. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  86. data/lib/pact_broker/pacts/verifiable_pact.rb +23 -2
  87. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  88. data/lib/pact_broker/repositories/helpers.rb +4 -0
  89. data/lib/pact_broker/services.rb +9 -0
  90. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  91. data/lib/pact_broker/tags/repository.rb +3 -1
  92. data/lib/pact_broker/tags/service.rb +0 -3
  93. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  94. data/lib/pact_broker/test/http_test_data_builder.rb +86 -25
  95. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  96. data/lib/pact_broker/ui/view_models/index_item.rb +19 -2
  97. data/lib/pact_broker/ui/view_models/matrix_line.rb +38 -2
  98. data/lib/pact_broker/ui/views/index/show-with-tags.haml +14 -6
  99. data/lib/pact_broker/ui/views/matrix/show.haml +12 -2
  100. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  101. data/lib/pact_broker/verifications/service.rb +2 -1
  102. data/lib/pact_broker/version.rb +1 -1
  103. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  104. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  105. data/lib/pact_broker/versions/repository.rb +22 -2
  106. data/lib/pact_broker/versions/service.rb +5 -1
  107. data/lib/pact_broker/webhooks/execution.rb +3 -2
  108. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  109. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  110. data/lib/pact_broker/webhooks/service.rb +8 -7
  111. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  112. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  113. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  114. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  115. data/lib/pact_broker/webhooks/webhook_execution_result.rb +6 -1
  116. data/lib/pact_broker/webhooks/webhook_request_logger.rb +7 -1
  117. data/lib/rack/pact_broker/set_base_url.rb +35 -5
  118. data/lib/sequel/plugins/upsert.rb +18 -4
  119. data/public/javascripts/clipboard.js +8 -2
  120. data/public/stylesheets/index.css +22 -1
  121. data/public/stylesheets/matrix.css +0 -21
  122. data/regression/can_i_deploy_spec.rb +5 -4
  123. data/regression/index_spec.rb +26 -0
  124. data/regression/regression_helper.rb +29 -3
  125. data/regression/script/clear.sh +3 -0
  126. data/regression/script/run.sh +3 -0
  127. data/script/demonstrate-version-branches.rb +33 -0
  128. data/script/pry.rb +2 -2
  129. data/script/reproduce-issue-starting-up.rb +13 -23
  130. data/script/reproduce-issue.rb +2 -1
  131. data/script/trigger-release.sh +1 -1
  132. data/script/webhook-server.ru +5 -5
  133. data/spec/features/create_environment_spec.rb +47 -0
  134. data/spec/features/create_tag_spec.rb +32 -0
  135. data/spec/features/create_version_spec.rb +70 -0
  136. data/spec/features/delete_environment_spec.rb +16 -0
  137. data/spec/features/end_deployment_spec.rb +29 -0
  138. data/spec/features/get_environment_spec.rb +19 -0
  139. data/spec/features/get_environments_spec.rb +20 -0
  140. data/spec/features/record_deployment_spec.rb +28 -0
  141. data/spec/features/update_environment_spec.rb +44 -0
  142. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  143. data/spec/fixtures/dashboard.json +4 -2
  144. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  145. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  146. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  147. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  148. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  149. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  150. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  151. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  152. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  153. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  154. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  155. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  156. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  157. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  158. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  159. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  160. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  161. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  162. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  163. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  164. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  165. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +20 -7
  166. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  167. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  168. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  169. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  170. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  171. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  172. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  173. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  174. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  175. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  176. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  177. data/spec/lib/rack/pact_broker/set_base_url_spec.rb +86 -0
  178. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  179. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  180. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  181. data/spec/spec_helper.rb +17 -5
  182. data/spec/support/approvals.rb +24 -0
  183. data/spec/support/shared_examples_for_responses.rb +11 -0
  184. data/tasks/database.rb +1 -1
  185. data/tasks/db.rake +1 -0
  186. data/tasks/rspec.rake +1 -1
  187. metadata +68 -4
  188. data/docker-compose-issue-repro.yml +0 -22
@@ -0,0 +1,17 @@
1
+ require_relative 'migration_helper'
2
+
3
+ include PactBroker::MigrationHelper
4
+
5
+ Sequel.migration do
6
+ change do
7
+ alter_table(:tags) do
8
+ # TODO set_column_not_null(:pacticipant_id)
9
+ # TODO set_column_not_null(:version_order)
10
+ add_column(:pacticipant_id, Integer)
11
+ add_column(:version_order, Integer)
12
+ add_index(:version_order, name: "tags_version_order_index")
13
+ add_index(:version_id, name: "tags_version_id_index")
14
+ add_index(:pacticipant_id, name: "tags_pacticipant_id_index")
15
+ end
16
+ end
17
+ end
@@ -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
@@ -23,7 +23,9 @@ services:
23
23
  environment:
24
24
  DATABASE_URL: postgres://postgres:postgres@postgres/postgres
25
25
  PACT_BROKER_HIDE_PACTFLOW_MESSAGES: 'true'
26
- command: dockerize -wait tcp://postgres:5432 /home/start.sh
26
+ PACT_BROKER_BASE_URL: 'http://localhost:9292 http://pact-broker:9292'
27
+ command: -wait tcp://postgres:5432 /usr/local/bin/start
28
+ entrypoint: dockerize
27
29
  volumes:
28
30
  - ./lib:/home/lib
29
31
  - ./db:/home/db
@@ -31,5 +33,11 @@ services:
31
33
  - ./tasks:/home/tasks
32
34
  - ./Rakefile:/home/Rakefile
33
35
 
36
+ shell:
37
+ image: ruby:2.5.3-alpine
38
+ depends_on:
39
+ - pact-broker
40
+ entrypoint: /bin/sh
41
+
34
42
  volumes:
35
43
  postgres-volume:
@@ -11,23 +11,34 @@ services:
11
11
  POSTGRES_DB: postgres
12
12
 
13
13
  pact-broker:
14
- image: pactfoundation/pact-broker:2.73.0.0
14
+ image: pactfoundation/pact-broker:2.76.0.0
15
15
  ports:
16
16
  - "9292:9292"
17
- depends_on:
18
- - postgres
17
+ # depends_on:
18
+ # - postgres
19
19
  environment:
20
20
  PACT_BROKER_PORT: '9292'
21
- PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
21
+ #PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
22
+ PACT_BROKER_DATABASE_URL: "sqlite:////tmp/pact_broker.sqlite3"
22
23
  PACT_BROKER_LOG_LEVEL: INFO
23
24
  PACT_BROKER_SQL_LOG_LEVEL: DEBUG
25
+ PACT_BROKER_WEBHOOK_SCHEME_WHITELIST: "http https"
26
+ PACT_BROKER_WEBHOOK_HOST_WHITELIST: "/.*/"
24
27
 
25
28
  repro-issue:
26
29
  build: .
27
30
  depends_on:
28
31
  - pact-broker
29
- command: dockerize -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
32
+ command: -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
33
+ entrypoint: dockerize
30
34
  environment:
31
35
  - PACT_BROKER_BASE_URL=http://pact-broker:9292
32
36
  volumes:
33
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
@@ -75,6 +75,7 @@ module PactBroker
75
75
  name: line.consumer_name,
76
76
  version: {
77
77
  number: line.consumer_version_number,
78
+ branch: line.consumer_version_branch,
78
79
  _links: {
79
80
  self: {
80
81
  href: version_url(base_url, consumer_version)
@@ -91,7 +92,7 @@ module PactBroker
91
92
  end
92
93
 
93
94
  def tags(tags, base_url)
94
- tags.collect do | tag |
95
+ tags.sort_by(&:created_at).collect do | tag |
95
96
  {
96
97
  name: tag.name,
97
98
  latest: tag.latest?,
@@ -118,6 +119,7 @@ module PactBroker
118
119
  if !line.provider_version_number.nil?
119
120
  hash[:version] = {
120
121
  number: line.provider_version_number,
122
+ branch: line.provider_version_branch,
121
123
  _links: {
122
124
  self: {
123
125
  href: version_url(base_url, provider_version)
@@ -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
@@ -68,6 +68,11 @@ module PactBroker
68
68
  alias_method :path_info, :identifier_from_path
69
69
 
70
70
  def base_url
71
+ # Have to use something for the base URL here - we can't use an empty string as we can in the UI.
72
+ # Can't work out if cache poisoning is a vulnerability for APIs or not.
73
+ # Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
74
+ # but the documentation recommends that the
75
+ # base_url should be set in the configuration to mitigate this.
71
76
  request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp('/')
72
77
  end
73
78
 
@@ -149,6 +154,10 @@ module PactBroker
149
154
  identifier_from_path[:consumer_version_number]
150
155
  end
151
156
 
157
+ def pacticipant_version_number
158
+ identifier_from_path[:pacticipant_version_number]
159
+ end
160
+
152
161
  def consumer_specified?
153
162
  identifier_from_path.key?(:consumer_name)
154
163
  end
@@ -239,6 +248,15 @@ module PactBroker
239
248
  def decorator_class(name)
240
249
  application_context.decorator_configuration.class_for(name)
241
250
  end
251
+
252
+ def validation_errors_for_schema?(schema, params_to_validate = params)
253
+ if (errors = schema.call(params_to_validate)).any?
254
+ set_json_validation_error_messages(errors)
255
+ true
256
+ else
257
+ false
258
+ end
259
+ end
242
260
  end
243
261
  end
244
262
  end