pact_broker 1.1.0 → 1.2.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +8 -11
  4. data/lib/pact_broker/api.rb +2 -0
  5. data/lib/pact_broker/api/decorators/decorator_context.rb +8 -1
  6. data/lib/pact_broker/api/decorators/pact_decorator.rb +18 -3
  7. data/lib/pact_broker/api/decorators/pact_version_decorator.rb +39 -0
  8. data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +48 -0
  9. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +3 -3
  10. data/lib/pact_broker/api/decorators/webhook_decorator.rb +1 -1
  11. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +1 -1
  12. data/lib/pact_broker/api/decorators/webhooks_decorator.rb +1 -1
  13. data/lib/pact_broker/api/pact_broker_urls.rb +16 -6
  14. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +35 -6
  15. data/lib/pact_broker/api/resources/base_resource.rb +80 -33
  16. data/lib/pact_broker/api/resources/group.rb +26 -24
  17. data/lib/pact_broker/api/resources/index.rb +52 -51
  18. data/lib/pact_broker/api/resources/latest_pact.rb +22 -22
  19. data/lib/pact_broker/api/resources/latest_pacts.rb +18 -17
  20. data/lib/pact_broker/api/resources/pact.rb +34 -39
  21. data/lib/pact_broker/api/resources/pact_versions.rb +35 -0
  22. data/lib/pact_broker/api/resources/pact_webhooks.rb +54 -61
  23. data/lib/pact_broker/api/resources/pacticipant.rb +40 -39
  24. data/lib/pact_broker/api/resources/pacticipant_resource_methods.rb +19 -0
  25. data/lib/pact_broker/api/resources/pacticipants.rb +52 -17
  26. data/lib/pact_broker/api/resources/relationships.rb +18 -17
  27. data/lib/pact_broker/api/resources/tag.rb +30 -29
  28. data/lib/pact_broker/api/resources/webhook.rb +29 -28
  29. data/lib/pact_broker/api/resources/webhook_execution.rb +0 -1
  30. data/lib/pact_broker/api/resources/webhook_resource_methods.rb +24 -0
  31. data/lib/pact_broker/api/resources/webhooks.rb +18 -17
  32. data/lib/pact_broker/app.rb +1 -0
  33. data/lib/pact_broker/configuration.rb +2 -2
  34. data/lib/pact_broker/doc/views/webhooks.markdown +1 -1
  35. data/lib/pact_broker/functions/find_potential_duplicate_pacticipant_names.rb +43 -0
  36. data/lib/pact_broker/locale/en.yml +7 -0
  37. data/lib/pact_broker/messages.rb +20 -1
  38. data/lib/pact_broker/models/pact.rb +8 -0
  39. data/lib/pact_broker/models/pacticipant.rb +9 -0
  40. data/lib/pact_broker/models/version.rb +1 -0
  41. data/lib/pact_broker/repositories/pact_repository.rb +6 -0
  42. data/lib/pact_broker/repositories/pacticipant_repository.rb +4 -0
  43. data/lib/pact_broker/repositories/webhook_repository.rb +2 -3
  44. data/lib/pact_broker/services/pact_service.rb +20 -0
  45. data/lib/pact_broker/services/pacticipant_service.rb +28 -0
  46. data/lib/pact_broker/services/webhook_service.rb +7 -2
  47. data/lib/pact_broker/version.rb +1 -1
  48. data/pact_broker.gemspec +1 -1
  49. data/public/stylesheets/github.css +1 -1
  50. data/public/stylesheets/pact.css +12 -0
  51. data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +10 -0
  52. data/spec/lib/pact_broker/api/decorators/pact_version_decorator_spec.rb +49 -0
  53. data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +9 -1
  54. data/spec/lib/pact_broker/api/resources/group_spec.rb +1 -1
  55. data/spec/lib/pact_broker/api/resources/latest_pact_spec.rb +1 -1
  56. data/spec/lib/pact_broker/api/resources/pact_spec.rb +35 -6
  57. data/spec/lib/pact_broker/api/resources/pact_webhooks_spec.rb +6 -4
  58. data/spec/lib/pact_broker/api/resources/pacticipants_spec.rb +91 -0
  59. data/spec/lib/pact_broker/configuration_spec.rb +3 -3
  60. data/spec/lib/pact_broker/functions/find_potential_duplicate_pacticipant_names_spec.rb +82 -0
  61. data/spec/lib/pact_broker/messages_spec.rb +31 -0
  62. data/spec/lib/pact_broker/models/pacticipant_spec.rb +32 -0
  63. data/spec/lib/pact_broker/repositories/pact_repository_spec.rb +29 -0
  64. data/spec/lib/pact_broker/repositories/pacticipant_repository_spec.rb +29 -0
  65. data/spec/lib/pact_broker/repositories/webhook_repository_spec.rb +7 -18
  66. data/spec/lib/pact_broker/services/pact_service_spec.rb +20 -0
  67. data/spec/lib/pact_broker/services/pacticipant_service_spec.rb +87 -2
  68. data/spec/support/provider_state_builder.rb +7 -7
  69. data/tasks/rspec.rake +1 -1
  70. metadata +27 -2
@@ -1,38 +1,40 @@
1
1
  require 'pact_broker/api/resources/base_resource'
2
2
  require 'pact_broker/api/decorators/relationships_csv_decorator'
3
3
 
4
- module PactBroker::Api
4
+ module PactBroker
5
5
 
6
- module Resources
6
+ module Api
7
+ module Resources
7
8
 
8
- class Group < BaseResource
9
+ class Group < BaseResource
9
10
 
10
- def content_types_provided
11
- [["text/csv", :to_csv]]
12
- end
11
+ def content_types_provided
12
+ [["text/csv", :to_csv]]
13
+ end
13
14
 
14
- def allowed_methods
15
- ["GET"]
16
- end
15
+ def allowed_methods
16
+ ["GET"]
17
+ end
17
18
 
18
- def to_csv
19
- generate_csv(group_service.find_group_containing @pacticipant)
20
- end
19
+ def to_csv
20
+ generate_csv(group_service.find_group_containing @pacticipant)
21
+ end
21
22
 
22
- def generate_csv group
23
- PactBroker::Api::Decorators::RelationshipsCsvDecorator.new(group).to_csv
24
- end
23
+ def generate_csv group
24
+ PactBroker::Api::Decorators::RelationshipsCsvDecorator.new(group).to_csv
25
+ end
25
26
 
26
- def pacticipant_name
27
- identifier_from_path[:pacticipant_name]
28
- end
27
+ def pacticipant_name
28
+ identifier_from_path[:pacticipant_name]
29
+ end
29
30
 
30
- def resource_exists?
31
- @pacticipant = pacticipant_service.find_pacticipant_by_name(pacticipant_name)
32
- @pacticipant != nil
33
- end
31
+ def resource_exists?
32
+ @pacticipant = pacticipant_service.find_pacticipant_by_name(pacticipant_name)
33
+ @pacticipant != nil
34
+ end
34
35
 
36
+ end
35
37
  end
36
- end
37
38
 
38
- end
39
+ end
40
+ end
@@ -1,59 +1,60 @@
1
1
  require 'pact_broker/api/resources/base_resource'
2
2
  require 'json'
3
3
 
4
- module PactBroker::Api
4
+ module PactBroker
5
+ module Api
6
+ module Resources
7
+
8
+ class Index < BaseResource
9
+
10
+ def content_types_provided
11
+ [["application/hal+json", :to_json]]
12
+ end
13
+
14
+ def allowed_methods
15
+ ["GET"]
16
+ end
17
+
18
+ # TODO change to use request.base_url to avoid params getting included!!!
19
+ def to_json
20
+ {
21
+ _links: {
22
+ 'pb:self' =>
23
+ {
24
+ href: request.uri.to_s,
25
+ title: 'The Pact Broker index page',
26
+ templated: false
27
+ },
28
+ 'pb:latest-pacts' =>
29
+ {
30
+ href: request.uri.to_s + 'pacts/latest',
31
+ title: 'Retrieve latest pacts',
32
+ templated: false
33
+ },
34
+ 'pb:pacticipants' =>
35
+ {
36
+ href: request.uri.to_s + 'pacticipants',
37
+ title: 'Retrieve pacticipants',
38
+ templated: false
39
+ },
40
+ 'pb:webhooks' =>
41
+ {
42
+ href: request.uri.to_s + 'webhooks',
43
+ title: 'Webhooks',
44
+ templated: false
45
+ },'curies' =>
46
+ [{
47
+ name: 'pb',
48
+ href: request.uri.to_s + 'doc/{rel}',
49
+ templated: true
50
+ }]
51
+ }
52
+ }.to_json
53
+ end
5
54
 
6
- module Resources
7
55
 
8
- class Index < BaseResource
9
-
10
- def content_types_provided
11
- [["application/hal+json", :to_json]]
12
- end
13
-
14
- def allowed_methods
15
- ["GET"]
16
- end
17
-
18
- # TODO change to use request.base_url to avoid params getting included!!!
19
- def to_json
20
- {
21
- _links: {
22
- 'pb:self' =>
23
- {
24
- href: request.uri.to_s,
25
- title: 'The Pact Broker index page',
26
- templated: false
27
- },
28
- 'pb:latest-pacts' =>
29
- {
30
- href: request.uri.to_s + 'pacts/latest',
31
- title: 'Retrieve latest pacts',
32
- templated: false
33
- },
34
- 'pb:pacticipants' =>
35
- {
36
- href: request.uri.to_s + 'pacticipants',
37
- title: 'Retrieve pacticipants',
38
- templated: false
39
- },
40
- 'pb:webhooks' =>
41
- {
42
- href: request.uri.to_s + 'webhooks',
43
- title: 'Webhooks',
44
- templated: false
45
- },'curies' =>
46
- [{
47
- name: 'pb',
48
- href: request.uri.to_s + 'doc/{rel}',
49
- templated: true
50
- }]
51
- }
52
- }.to_json
53
56
  end
54
-
55
-
56
57
  end
57
- end
58
58
 
59
- end
59
+ end
60
+ end
@@ -1,36 +1,36 @@
1
1
  require 'pact_broker/api/resources/base_resource'
2
2
  require 'pact_broker/configuration'
3
3
 
4
- module PactBroker::Api
4
+ module PactBroker
5
+ module Api
6
+ module Resources
5
7
 
6
- module Resources
8
+ class LatestPact < BaseResource
7
9
 
8
- class LatestPact < BaseResource
10
+ def content_types_provided
11
+ [["application/json", :to_json],
12
+ ["text/html", :to_html]]
13
+ end
9
14
 
10
- def content_types_provided
11
- [["application/json", :to_json],
12
- ["text/html", :to_html]]
13
- end
15
+ def allowed_methods
16
+ ["GET"]
17
+ end
14
18
 
15
- def allowed_methods
16
- ["GET"]
17
- end
19
+ def resource_exists?
20
+ @pact = pact_service.find_latest_pact(identifier_from_path)
21
+ @pact != nil
22
+ end
18
23
 
19
- def resource_exists?
20
- @pact = pact_service.find_latest_pact(identifier_from_path)
21
- @pact != nil
22
- end
24
+ def to_json
25
+ response.headers['X-Pact-Consumer-Version'] = @pact.consumer_version_number
26
+ PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
27
+ end
23
28
 
24
- def to_json
25
- response.headers['X-Pact-Consumer-Version'] = @pact.consumer_version_number
26
- PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
27
- end
29
+ def to_html
30
+ PactBroker.configuration.html_pact_renderer.call(@pact)
31
+ end
28
32
 
29
- def to_html
30
- PactBroker.configuration.html_pact_renderer.call(@pact.json_content)
31
33
  end
32
-
33
34
  end
34
35
  end
35
-
36
36
  end
@@ -1,28 +1,29 @@
1
1
  require 'pact_broker/api/resources/base_resource'
2
2
 
3
- module PactBroker::Api
3
+ module PactBroker
4
+ module Api
5
+ module Resources
4
6
 
5
- module Resources
7
+ class LatestPacts < BaseResource
6
8
 
7
- class LatestPacts < BaseResource
9
+ def content_types_provided
10
+ [["application/hal+json", :to_json]]
11
+ end
8
12
 
9
- def content_types_provided
10
- [["application/hal+json", :to_json]]
11
- end
13
+ def allowed_methods
14
+ ["GET"]
15
+ end
12
16
 
13
- def allowed_methods
14
- ["GET"]
15
- end
17
+ def to_json
18
+ generate_json(pact_service.find_latest_pacts)
19
+ end
16
20
 
17
- def to_json
18
- generate_json(pact_service.find_latest_pacts)
19
- end
21
+ def generate_json pacts
22
+ PactBroker::Api::Decorators::PactCollectionDecorator.new(pacts).to_json(base_url: base_url)
23
+ end
20
24
 
21
- def generate_json pacts
22
- PactBroker::Api::Decorators::PactCollectionDecorator.new(pacts).to_json(base_url: base_url)
23
25
  end
24
-
25
26
  end
26
- end
27
27
 
28
- end
28
+ end
29
+ end
@@ -1,60 +1,55 @@
1
1
  require 'cgi'
2
2
  require 'pact_broker/api/resources/base_resource'
3
+ require 'pact_broker/api/resources/pacticipant_resource_methods'
3
4
  require 'pact_broker/api/decorators/pact_decorator'
4
5
  require 'pact_broker/json'
5
6
 
6
- module PactBroker::Api
7
+ module PactBroker
7
8
 
8
- module Resources
9
+ module Api
10
+ module Resources
9
11
 
10
- class Pact < BaseResource
12
+ class Pact < BaseResource
11
13
 
12
- def content_types_provided
13
- [["application/json", :to_json]]
14
- end
14
+ include PacticipantResourceMethods
15
15
 
16
- def content_types_accepted
17
- [["application/json", :from_json]]
18
- end
16
+ def content_types_provided
17
+ [["application/json", :to_json]]
18
+ end
19
19
 
20
- def allowed_methods
21
- ["GET", "PUT"]
22
- end
20
+ def content_types_accepted
21
+ [["application/json", :from_json]]
22
+ end
23
+
24
+ def allowed_methods
25
+ ["GET", "PUT"]
26
+ end
23
27
 
24
- def malformed_request?
25
- if request.put?
26
- begin
27
- JSON.parse(pact_content, PactBroker::PACT_PARSING_OPTIONS) #Not load! Otherwise it will try to load Ruby classes.
28
+ def malformed_request?
29
+ if request.put?
30
+ return invalid_json? ||
31
+ potential_duplicate_pacticipants?([identifier_from_path[:consumer_name], identifier_from_path[:provider_name]])
32
+ else
28
33
  false
29
- rescue StandardError => e
30
- logger.error "Error parsing JSON #{e} - #{pact_content}"
31
- response.headers['Content-Type'] = 'application/json'
32
- response.body = {error: "Invalid JSON - #{e.message}"}.to_json
33
- true
34
34
  end
35
35
  end
36
- end
37
36
 
38
- def resource_exists?
39
- @pact = pact_service.find_pact(identifier_from_path)
40
- @pact != nil
41
- end
37
+ def resource_exists?
38
+ @pact = pact_service.find_pact(identifier_from_path)
39
+ @pact != nil
40
+ end
42
41
 
43
- def from_json
44
- @pact, created = pact_service.create_or_update_pact(identifier_from_path.merge(:json_content => pact_content))
45
- response.headers["Location"] = pact_url(base_url, @pact) if created
46
- response.body = to_json
47
- end
42
+ def from_json
43
+ @pact, created = pact_service.create_or_update_pact(identifier_from_path.merge(:json_content => request_body))
44
+ response.headers["Location"] = pact_url(base_url, @pact) if created
45
+ response.body = to_json
46
+ end
48
47
 
49
- def to_json
50
- PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
51
- end
48
+ def to_json
49
+ PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
50
+ end
52
51
 
53
- def pact_content
54
- request.body.to_s
55
52
  end
56
-
57
53
  end
58
54
  end
59
-
60
- end
55
+ end
@@ -0,0 +1,35 @@
1
+ require 'pact_broker/api/resources/base_resource'
2
+ require 'pact_broker/configuration'
3
+ require 'pact_broker/api/decorators/pact_versions_decorator'
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Resources
8
+
9
+ class PactVersions < BaseResource
10
+
11
+ def content_types_provided
12
+ [["application/json", :to_json]]
13
+ end
14
+
15
+ def allowed_methods
16
+ ["GET"]
17
+ end
18
+
19
+ def resource_exists?
20
+ pacticipant_service.find_pacticipant_by_name(consumer_name) &&
21
+ pacticipant_service.find_pacticipant_by_name(provider_name)
22
+ end
23
+
24
+ def to_json
25
+ PactBroker::Api::Decorators::PactVersionsDecorator.new(pacts).to_json(decorator_context(identifier_from_path))
26
+ end
27
+
28
+ def pacts
29
+ pact_service.find_all_pacts_between consumer_name, :and => provider_name
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,85 +3,78 @@ require 'pact_broker/api/resources/base_resource'
3
3
  require 'pact_broker/api/decorators/webhook_decorator'
4
4
  require 'pact_broker/api/decorators/webhooks_decorator'
5
5
 
6
- module PactBroker::Api
6
+ module PactBroker
7
7
 
8
- module Resources
8
+ module Api
9
+ module Resources
9
10
 
10
- class PactWebhooks < BaseResource
11
+ class PactWebhooks < BaseResource
11
12
 
12
- def allowed_methods
13
- ["POST", "GET"]
14
- end
13
+ def allowed_methods
14
+ ["POST", "GET"]
15
+ end
15
16
 
16
- def content_types_provided
17
- [["application/hal+json", :to_json]]
18
- end
17
+ def content_types_provided
18
+ [["application/hal+json", :to_json]]
19
+ end
19
20
 
20
- def resource_exists?
21
- (@consumer = find_pacticipant(identifier_from_path[:consumer_name], "consumer")) &&
22
- (@provider = find_pacticipant(identifier_from_path[:provider_name], "provider"))
23
- end
21
+ def content_types_accepted
22
+ [["application/json", :from_json]]
23
+ end
24
+
25
+ def resource_exists?
26
+ (@consumer = find_pacticipant(identifier_from_path[:consumer_name], "consumer")) &&
27
+ (@provider = find_pacticipant(identifier_from_path[:provider_name], "provider"))
28
+ end
24
29
 
25
- def malformed_request?
26
- if request.post?
27
- begin
28
- if (errors = webhook.validate).any?
29
- set_json_validation_error_messages errors
30
- return true
31
- end
32
- rescue
33
- set_json_error_message 'Invalid JSON'
34
- return true
30
+ def malformed_request?
31
+ if request.post?
32
+ return invalid_json? || validation_errors?(webhook)
35
33
  end
34
+ false
36
35
  end
37
- false
38
- end
39
36
 
40
- def process_post
41
- saved_webhook = webhook_service.create webhook, consumer, provider
42
- response.headers['Content-Type'] = 'application/json'
43
- response.headers['Location'] = webhook_url saved_webhook, base_url
44
- response.body = Decorators::WebhookDecorator.new(saved_webhook).to_json(base_url: base_url)
45
- true
46
- end
37
+ def create_path
38
+ webhook_url next_uuid, base_url
39
+ end
47
40
 
48
- def to_json
49
- Decorators::WebhooksDecorator.new(webhooks).to_json(decorator_context(resource_title: 'Pact webhooks'))
50
- end
41
+ def post_is_create?
42
+ true
43
+ end
51
44
 
52
- private
45
+ def from_json
46
+ saved_webhook = webhook_service.create next_uuid, webhook, consumer, provider
47
+ response.body = Decorators::WebhookDecorator.new(saved_webhook).to_json(base_url: base_url)
48
+ true
49
+ end
53
50
 
54
- attr_reader :consumer, :provider
51
+ def to_json
52
+ Decorators::WebhooksDecorator.new(webhooks).to_json(decorator_context(resource_title: 'Pact webhooks'))
53
+ end
55
54
 
56
- def webhooks
57
- webhook_service.find_by_consumer_and_provider consumer, provider
58
- end
55
+ private
59
56
 
60
- def webhook
61
- @webhook ||= Decorators::WebhookDecorator.new(PactBroker::Models::Webhook.new).from_json(request.body.to_s)
62
- end
57
+ attr_reader :consumer, :provider
63
58
 
64
- def set_json_error_message message
65
- response.headers['Content-Type'] = 'application/json'
66
- response.body = {error: message}.to_json
67
- end
59
+ def webhooks
60
+ webhook_service.find_by_consumer_and_provider consumer, provider
61
+ end
68
62
 
69
- def set_json_validation_error_messages errors
70
- response.headers['Content-Type'] = 'application/json'
71
- response.body = {errors: errors}.to_json
72
- end
63
+ def webhook
64
+ @webhook ||= Decorators::WebhookDecorator.new(PactBroker::Models::Webhook.new).from_json(request_body)
65
+ end
73
66
 
74
- def find_pacticipant name, role
75
- pacticipant = pacticipant_service.find_pacticipant_by_name name
76
- if pacticipant.nil?
77
- set_json_error_message "No #{role} with name '#{name}' found"
78
- nil
79
- else
80
- pacticipant
67
+ def next_uuid
68
+ @next_uuid ||= webhook_service.next_uuid
69
+ end
70
+
71
+ def find_pacticipant name, role
72
+ pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
73
+ set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
74
+ end
81
75
  end
82
- end
83
76
 
77
+ end
84
78
  end
85
79
  end
86
-
87
- end
80
+ end