pact_broker 2.77.0 → 2.78.0

Sign up to get free protection for your applications and to get access to all the features.
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