pact_broker 2.77.0 → 2.78.0

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/db/migrations/20210210_create_environments_table.rb +16 -0
  4. data/lib/pact_broker/api.rb +5 -0
  5. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  6. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  7. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  8. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  9. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  10. data/lib/pact_broker/api/decorators/version_decorator.rb +12 -1
  11. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  12. data/lib/pact_broker/api/resources/default_base_resource.rb +9 -0
  13. data/lib/pact_broker/api/resources/environment.rb +76 -0
  14. data/lib/pact_broker/api/resources/environments.rb +75 -0
  15. data/lib/pact_broker/api/resources/index.rb +14 -0
  16. data/lib/pact_broker/api/resources/version.rb +2 -2
  17. data/lib/pact_broker/configuration.rb +1 -0
  18. data/lib/pact_broker/deployments/environment.rb +15 -0
  19. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  20. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  21. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  22. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  23. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  24. data/lib/pact_broker/locale/en.yml +3 -1
  25. data/lib/pact_broker/services.rb +9 -0
  26. data/lib/pact_broker/test/test_data_builder.rb +14 -0
  27. data/lib/pact_broker/version.rb +1 -1
  28. data/lib/pact_broker/versions/repository.rb +15 -4
  29. data/lib/pact_broker/versions/service.rb +2 -2
  30. data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
  31. data/spec/features/create_environment_spec.rb +47 -0
  32. data/spec/features/create_tag_spec.rb +32 -0
  33. data/spec/features/create_version_spec.rb +30 -4
  34. data/spec/features/delete_environment_spec.rb +16 -0
  35. data/spec/features/end_deployment_spec.rb +29 -0
  36. data/spec/features/get_environment_spec.rb +19 -0
  37. data/spec/features/get_environments_spec.rb +20 -0
  38. data/spec/features/record_deployment_spec.rb +28 -0
  39. data/spec/features/update_environment_spec.rb +44 -0
  40. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  41. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  42. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  43. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  44. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  45. data/spec/lib/pact_broker/versions/repository_spec.rb +14 -4
  46. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  47. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  48. data/spec/support/shared_examples_for_responses.rb +11 -0
  49. metadata +33 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: caab9fa9fc2bef074e4523e89122015a55d85572df00564956dc25553273f095
4
- data.tar.gz: aa1638d95186e934c08cac4d5842c8e10c762b95e9db1f5f9e3ca3c4533dbde4
3
+ metadata.gz: 4260e4320105662bc678b63a94054f7485609557b2e967e58ac59512fca69f81
4
+ data.tar.gz: 4d40a31b9f93c9e08a67e2b1e50cff0fc0c59e0344d3a8672b629d425a93444a
5
5
  SHA512:
6
- metadata.gz: 82a534408c7557f0dd8b5a605d3c68da1d79d8dabaefb721608ff99a4fcb16e6e04815d5b2286fc50d87dce99c8170eebcef653e46d4b423f4048ffeccce0075
7
- data.tar.gz: fdb5a29c0ccdb0dce1d60ea7853925154a1d82384fd2c720a46a612b2a20f173ce65f08f67349d6095e6f2ca8f14721d660c2b4a35ca77a3ce3e7e8c9fb12269
6
+ metadata.gz: b2dec2c3934c80e7edf5d85370aecf511e8ce8e403486c964182b8f2f397f91bdad7ac886c1dd2955f6d4c9cac52bbac81c22b89d824d7d19fe57d224715ecb5
7
+ data.tar.gz: 8d60c2beaa8719efe9bfd7551ddda158d4c4f06cdf92884fdbb1312e8a7a306b5fc5754f5f467bd922e688eb37c899ea60c1758de48fce7696553ee57b84fd32
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ <a name="v2.78.0"></a>
2
+ ### v2.78.0 (2021-02-15)
3
+
4
+ #### Features
5
+
6
+ * support create, update and delete of environment resources (#379) ([410f2e80](/../../commit/410f2e80))
7
+ * allow version to be created with tags ([798afce9](/../../commit/798afce9))
8
+ * Follow up for #239 + adding list of success codes to SAVABLE_SETTING_NAMES variable (#388) ([08c0ad09](/../../commit/08c0ad09))
9
+
1
10
  <a name="v2.77.0"></a>
2
11
  ### v2.77.0 (2021-02-11)
3
12
 
@@ -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
@@ -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
@@ -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
@@ -10,7 +10,7 @@ module PactBroker
10
10
  property :branch
11
11
  property :build_url, as: :buildUrl
12
12
 
13
- collection :tags, embedded: true, writeable: false, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator
13
+ collection :tags, embedded: true, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator, class: OpenStruct
14
14
 
15
15
  include Timestamps
16
16
 
@@ -63,6 +63,17 @@ module PactBroker
63
63
  }]
64
64
  end
65
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
+
66
77
  private
67
78
 
68
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
@@ -243,6 +243,15 @@ module PactBroker
243
243
  def decorator_class(name)
244
244
  application_context.decorator_configuration.class_for(name)
245
245
  end
246
+
247
+ def validation_errors_for_schema?(schema, params_to_validate = params)
248
+ if (errors = schema.call(params_to_validate)).any?
249
+ set_json_validation_error_messages(errors)
250
+ true
251
+ else
252
+ false
253
+ end
254
+ end
246
255
  end
247
256
  end
248
257
  end
@@ -0,0 +1,76 @@
1
+ require 'pact_broker/api/resources/base_resource'
2
+ require 'pact_broker/api/resources/environment'
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Resources
7
+ class Environment < BaseResource
8
+ def content_types_provided
9
+ [["application/hal+json", :to_json]]
10
+ end
11
+
12
+ def content_types_accepted
13
+ [["application/json", :from_json]]
14
+ end
15
+
16
+ def allowed_methods
17
+ ["GET", "PUT", "DELETE", "OPTIONS"]
18
+ end
19
+
20
+ def resource_exists?
21
+ !!environment
22
+ end
23
+
24
+ def malformed_request?
25
+ if request.put? && environment
26
+ invalid_json? || validation_errors_for_schema?(schema, params.merge(uuid: uuid))
27
+ else
28
+ false
29
+ end
30
+ end
31
+
32
+ def from_json
33
+ if environment
34
+ @environment = update_environment
35
+ response.body = to_json
36
+ else
37
+ response.code = 404
38
+ end
39
+ end
40
+
41
+ def policy_name
42
+ :'deployments::environment'
43
+ end
44
+
45
+ def to_json
46
+ decorator_class(:environment_decorator).new(environment).to_json(decorator_options)
47
+ end
48
+
49
+ def parsed_environment
50
+ @parsed_environment ||= decorator_class(:environment_decorator).new(PactBroker::Deployments::Environment.new).from_json(request_body)
51
+ end
52
+
53
+ def environment
54
+ @environment ||= environment_service.find(uuid)
55
+ end
56
+
57
+ def delete_resource
58
+ environment_service.delete(uuid)
59
+ true
60
+ end
61
+
62
+ def uuid
63
+ identifier_from_path[:environment_uuid]
64
+ end
65
+
66
+ def update_environment
67
+ environment_service.update(uuid, parsed_environment)
68
+ end
69
+
70
+ def schema
71
+ PactBroker::Api::Contracts::EnvironmentSchema
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,75 @@
1
+ require 'pact_broker/api/resources/base_resource'
2
+ require 'pact_broker/api/resources/environment'
3
+ require 'pact_broker/api/contracts/environment_schema'
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Resources
8
+ class Environments < BaseResource
9
+ def content_types_provided
10
+ [["application/hal+json", :to_json]]
11
+ end
12
+
13
+ def content_types_accepted
14
+ [["application/json", :from_json]]
15
+ end
16
+
17
+ def allowed_methods
18
+ ["GET", "POST", "OPTIONS"]
19
+ end
20
+
21
+ def resource_exists?
22
+ true
23
+ end
24
+
25
+ def post_is_create?
26
+ true
27
+ end
28
+
29
+ def malformed_request?
30
+ if request.post?
31
+ invalid_json? || validation_errors_for_schema?(schema, params.merge(uuid: uuid))
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def create_path
38
+ environment_url(OpenStruct.new(uuid: uuid), base_url)
39
+ end
40
+
41
+ def from_json
42
+ response.body = decorator_class(:environment_decorator).new(create_environment).to_json(decorator_options)
43
+ end
44
+
45
+ def policy_name
46
+ :'deployments::environment'
47
+ end
48
+
49
+ def to_json
50
+ decorator_class(:environments_decorator).new(environments).to_json(decorator_options)
51
+ end
52
+
53
+ def parsed_environment
54
+ @parsed_environment ||= decorator_class(:environment_decorator).new(PactBroker::Deployments::Environment.new).from_json(request_body)
55
+ end
56
+
57
+ def create_environment
58
+ environment_service.create(uuid, parsed_environment)
59
+ end
60
+
61
+ def uuid
62
+ @uuid ||= environment_service.next_uuid
63
+ end
64
+
65
+ def environments
66
+ @environments ||= environment_service.find_all
67
+ end
68
+
69
+ def schema
70
+ PactBroker::Api::Contracts::EnvironmentSchema
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -150,6 +150,20 @@ module PactBroker
150
150
  }]
151
151
  }
152
152
 
153
+ if PactBroker.feature_enabled?(:environments)
154
+ links_hash['pb:environments'] = {
155
+ title: "Environments",
156
+ href: environments_url(base_url),
157
+ templated: false
158
+ }
159
+
160
+ links_hash['pb:environment'] = {
161
+ title: "Environment",
162
+ href: environments_url(base_url) + "/{uuid}",
163
+ templated: true
164
+ }
165
+ end
166
+
153
167
  if PactBroker.feature_enabled?('disable_pacts_for_verification', true)
154
168
  links_hash.delete('pb:provider-pacts-for-verification')
155
169
  links_hash.delete('beta:provider-pacts-for-verification')
@@ -24,8 +24,8 @@ module PactBroker
24
24
 
25
25
  def from_json
26
26
  response_code = version ? 200 : 201
27
- parsed_version = Decorators::VersionDecorator.new(PactBroker::Domain::Version.new).from_json(request_body)
28
- @version = version_service.create_or_update(pacticipant_name, pacticipant_version_number, parsed_version)
27
+ parsed_version = Decorators::VersionDecorator.new(OpenStruct.new).from_json(request_body)
28
+ @version = version_service.create_or_overwrite(pacticipant_name, pacticipant_version_number, parsed_version)
29
29
  response.body = to_json
30
30
  response_code
31
31
  end