pact_broker 2.106.0 → 2.107.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/Gemfile +3 -0
- data/db/migrations/20230131_add_cons_ver_id_ndx_to_latest_pp_id_for_cons_ver.rb +8 -4
- data/db/migrations/20230216_add_branch_heads_branch_version_id_index.rb +21 -0
- data/db/migrations/20230428_add_index_for_webhook_executions_pact_publication_id.rb +17 -0
- data/lib/pact_broker/api/contracts/base_contract.rb +22 -7
- data/lib/pact_broker/api/contracts/can_i_deploy_query_schema.rb +34 -0
- data/lib/pact_broker/api/contracts/configuration.rb +2 -0
- data/lib/pact_broker/api/contracts/consumer_version_selector_contract.rb +140 -0
- data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +50 -0
- data/lib/pact_broker/api/contracts/dry_validation_macros.rb +79 -0
- data/lib/pact_broker/api/contracts/dry_validation_methods.rb +71 -0
- data/lib/pact_broker/api/contracts/environment_schema.rb +19 -33
- data/lib/pact_broker/api/contracts/pacticipant_create_schema.rb +4 -17
- data/lib/pact_broker/api/contracts/pacticipant_schema.rb +15 -24
- data/lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb +37 -146
- data/lib/pact_broker/api/contracts/pacts_for_verification_query_string_schema.rb +7 -20
- data/lib/pact_broker/api/contracts/publish_contracts_contract_contract.rb +62 -0
- data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +25 -124
- data/lib/pact_broker/api/contracts/put_pact_params_contract.rb +21 -26
- data/lib/pact_broker/api/contracts/utf_8_validation.rb +2 -0
- data/lib/pact_broker/api/contracts/validation_helpers.rb +71 -0
- data/lib/pact_broker/api/contracts/verification_contract.rb +10 -29
- data/lib/pact_broker/api/contracts/webhook_contract.rb +20 -172
- data/lib/pact_broker/api/contracts/webhook_pacticipant_contract.rb +33 -0
- data/lib/pact_broker/api/contracts/webhook_request_contract.rb +125 -0
- data/lib/pact_broker/api/contracts.rb +3 -0
- data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/matrix_text_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/pact_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +2 -1
- data/lib/pact_broker/api/decorators/pacts_for_verification_query_decorator.rb +4 -1
- data/lib/pact_broker/api/decorators/pagination_links.rb +6 -6
- data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +6 -6
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +2 -3
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +5 -12
- data/lib/pact_broker/api/resources/all_webhooks.rb +5 -11
- data/lib/pact_broker/api/resources/base_resource.rb +3 -20
- data/lib/pact_broker/api/resources/branch_version.rb +3 -3
- data/lib/pact_broker/api/resources/can_i_deploy.rb +4 -19
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment.rb +1 -4
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag.rb +0 -2
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag_badge.rb +1 -2
- data/lib/pact_broker/api/resources/currently_deployed_versions_for_environment.rb +2 -2
- data/lib/pact_broker/api/resources/currently_supported_versions_for_environment.rb +2 -2
- data/lib/pact_broker/api/resources/dashboard.rb +3 -3
- data/lib/pact_broker/api/resources/deployed_version.rb +1 -1
- data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +2 -2
- data/lib/pact_broker/api/resources/environment.rb +1 -1
- data/lib/pact_broker/api/resources/environments.rb +2 -2
- data/lib/pact_broker/api/resources/error_handling_methods.rb +2 -2
- data/lib/pact_broker/api/resources/integrations.rb +1 -1
- data/lib/pact_broker/api/resources/label.rb +1 -1
- data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
- data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
- data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +1 -1
- data/lib/pact_broker/api/resources/matrix.rb +2 -2
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
- data/lib/pact_broker/api/resources/pact.rb +7 -4
- data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/pact_webhooks.rb +7 -14
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +6 -2
- data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
- data/lib/pact_broker/api/resources/pacticipant_webhooks.rb +7 -5
- data/lib/pact_broker/api/resources/pacticipants.rb +2 -2
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
- data/lib/pact_broker/api/resources/provider_pacts.rb +1 -1
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +4 -13
- data/lib/pact_broker/api/resources/publish_contracts.rb +8 -3
- data/lib/pact_broker/api/resources/released_version.rb +1 -1
- data/lib/pact_broker/api/resources/released_versions_for_version_and_environment.rb +2 -2
- data/lib/pact_broker/api/resources/tag.rb +1 -1
- data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +2 -2
- data/lib/pact_broker/api/resources/verification.rb +2 -2
- data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/verifications.rb +4 -6
- data/lib/pact_broker/api/resources/version.rb +1 -1
- data/lib/pact_broker/api/resources/versions.rb +1 -1
- data/lib/pact_broker/api/resources/webhook.rb +7 -6
- data/lib/pact_broker/api/resources/webhook_execution.rb +6 -4
- data/lib/pact_broker/api.rb +3 -12
- data/lib/pact_broker/certificates/certificate.rb +1 -0
- data/lib/pact_broker/config/setting.rb +1 -0
- data/lib/pact_broker/contracts/service.rb +1 -0
- data/lib/pact_broker/date_helper.rb +1 -1
- data/lib/pact_broker/db/clean_incremental.rb +1 -1
- data/lib/pact_broker/db/delete_overwritten_data.rb +6 -2
- data/lib/pact_broker/deployments/currently_deployed_version_id.rb +2 -0
- data/lib/pact_broker/deployments/deployed_version.rb +2 -0
- data/lib/pact_broker/deployments/deployed_version_service.rb +5 -1
- data/lib/pact_broker/deployments/environment.rb +2 -0
- data/lib/pact_broker/deployments/environment_service.rb +4 -3
- data/lib/pact_broker/deployments/released_version.rb +2 -0
- data/lib/pact_broker/deployments/released_version_service.rb +4 -0
- data/lib/pact_broker/diagnostic/resources/base_resource.rb +1 -1
- data/lib/pact_broker/doc/views/index/publish-contracts.markdown +5 -5
- data/lib/pact_broker/domain/label.rb +1 -0
- data/lib/pact_broker/domain/tag.rb +2 -0
- data/lib/pact_broker/domain/verification.rb +1 -1
- data/lib/pact_broker/domain/version.rb +4 -1
- data/lib/pact_broker/domain/webhook.rb +1 -1
- data/lib/pact_broker/index/service.rb +1 -1
- data/lib/pact_broker/integrations/integration.rb +1 -0
- data/lib/pact_broker/locale/en.yml +35 -14
- data/lib/pact_broker/matrix/query_ids.rb +4 -4
- data/lib/pact_broker/matrix/resolved_selector.rb +6 -1
- data/lib/pact_broker/matrix/service.rb +1 -0
- data/lib/pact_broker/messages.rb +5 -1
- data/lib/pact_broker/pacticipants/repository.rb +12 -3
- data/lib/pact_broker/pacticipants/service.rb +7 -0
- data/lib/pact_broker/pacts/pact_params.rb +6 -17
- data/lib/pact_broker/pacts/pact_version.rb +1 -0
- data/lib/pact_broker/policies.rb +4 -4
- data/lib/pact_broker/test/http_test_data_builder.rb +46 -2
- data/lib/pact_broker/ui/app.rb +2 -2
- data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +1 -1
- data/lib/pact_broker/verifications/pact_version_provider_tag_successful_verification.rb +1 -0
- data/lib/pact_broker/verifications/service.rb +0 -6
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/branch.rb +1 -0
- data/lib/pact_broker/versions/branch_head.rb +2 -1
- data/lib/pact_broker/versions/branch_version.rb +11 -0
- data/lib/pact_broker/webhooks/execution.rb +1 -1
- data/lib/pact_broker/webhooks/repository.rb +1 -1
- data/lib/pact_broker/webhooks/service.rb +3 -25
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
- data/lib/pact_broker/webhooks/webhook_event.rb +1 -0
- data/lib/pact_broker/webmachine.rb +22 -0
- data/lib/rack/pact_broker/invalid_uri_protection.rb +1 -1
- data/lib/rack/pact_broker/use_when.rb +6 -5
- data/lib/sequel/plugins/age.rb +13 -0
- data/lib/webmachine/application_monkey_patch.rb +5 -0
- data/lib/webmachine/describe_routes.rb +35 -8
- data/lib/webmachine/render_error_monkey_patch.rb +1 -1
- data/pact_broker.gemspec +7 -17
- metadata +65 -67
- data/lib/pact/doc/README.md +0 -5
- data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +0 -36
- data/lib/pact_broker/api/contracts/dry_validation_workarounds.rb +0 -39
- data/lib/pact_broker/api/contracts/pacticipant_name_contract.rb +0 -24
- data/lib/pact_broker/api/contracts/pacticipant_name_validation.rb +0 -30
- data/lib/pact_broker/api/contracts/request_validations.rb +0 -33
- data/lib/pact_broker/api/resources/webhook_resource_methods.rb +0 -17
- data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +0 -46
@@ -24,10 +24,12 @@ module PactBroker
|
|
24
24
|
VERSION_COLUMNS = [:id, :number, :repository_ref, :pacticipant_id, :order, :created_at, :updated_at, :build_url]
|
25
25
|
|
26
26
|
class Version < Sequel::Model(Sequel::Model.db[:versions].select(*VERSION_COLUMNS.collect{ | column | Sequel.qualify(:versions, column) }))
|
27
|
+
set_primary_key :id
|
28
|
+
|
27
29
|
plugin :timestamps, update_on_create: true
|
30
|
+
plugin :age
|
28
31
|
plugin :upsert, { identifying_columns: [:pacticipant_id, :number], ignore_columns_on_update: [:id, :created_at, :order] }
|
29
32
|
|
30
|
-
set_primary_key :id
|
31
33
|
one_to_many :pact_publications, order: :revision_number, class: "PactBroker::Pacts::PactPublication", key: :consumer_version_id
|
32
34
|
associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
|
33
35
|
one_to_many :tags, :reciprocal => :version, order: :created_at
|
@@ -41,6 +43,7 @@ module PactBroker
|
|
41
43
|
end
|
42
44
|
|
43
45
|
one_to_many :deployed_versions, class: "PactBroker::Deployments::DeployedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id]
|
46
|
+
one_to_many :released_versions, class: "PactBroker::Deployments::ReleasedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id]
|
44
47
|
|
45
48
|
many_to_one :latest_version_for_pacticipant, read_only: true, key: :id,
|
46
49
|
class: Version,
|
@@ -50,7 +50,7 @@ module PactBroker
|
|
50
50
|
def execute pact, verification, event_context, options
|
51
51
|
logger.info "Executing #{self} event_context=#{event_context}"
|
52
52
|
template_params = template_parameters(pact, verification, event_context, options)
|
53
|
-
webhook_request = request.build(template_params, options.slice(:user_agent, :disable_ssl_verification, :cert_store))
|
53
|
+
webhook_request = request.build(template_params, **options.slice(:user_agent, :disable_ssl_verification, :cert_store))
|
54
54
|
http_response, error = execute_request(webhook_request)
|
55
55
|
success = success?(http_response, options)
|
56
56
|
http_request = webhook_request.http_request
|
@@ -109,7 +109,7 @@ module PactBroker
|
|
109
109
|
# rubocop: disable Metrics/CyclomaticComplexity
|
110
110
|
def self.latest_verification_for_pseudo_branch(pact_publication, is_overall_latest, latest_verifications_for_cv_tags, tags_option, options)
|
111
111
|
if options[:view] == "branch" || (options[:view] == "all" && pact_publication.consumer_version.branch_heads.any?)
|
112
|
-
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches
|
112
|
+
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches(forbid_lazy_load: false)
|
113
113
|
elsif tags_option == true
|
114
114
|
latest_verifications_for_cv_tags
|
115
115
|
.select{ | v | v.consumer_id == pact_publication.consumer_id && v.provider_id == pact_publication.provider_id && pact_publication.head_pact_tags.collect(&:name).include?(v.consumer_version_tag_name) }
|
@@ -8,6 +8,7 @@ require "pact_broker/verifications/latest_verification_for_consumer_and_provider
|
|
8
8
|
module PactBroker
|
9
9
|
module Integrations
|
10
10
|
class Integration < Sequel::Model(Sequel::Model.db[:integrations].select(:id, :consumer_id, :provider_id))
|
11
|
+
set_primary_key :id
|
11
12
|
plugin :insert_ignore, identifying_columns: [:consumer_id, :provider_id]
|
12
13
|
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
13
14
|
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
@@ -2,17 +2,10 @@ en:
|
|
2
2
|
errors:
|
3
3
|
not_blank?: "can't be blank"
|
4
4
|
filled?: "can't be blank"
|
5
|
-
valid_method?: "is not a recognised HTTP method"
|
6
5
|
valid_url?: "is not a valid URL eg. http://example.org"
|
7
6
|
base64?: "is not valid Base64"
|
8
|
-
valid_version_number?: "Version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
9
|
-
name_in_path_matches_name_in_pact?: "does not match %{left} name in path ('%{right}')."
|
10
|
-
valid_consumer_version_number?: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
11
|
-
non_templated_host?: "cannot have a template parameter in the host"
|
12
|
-
pacticipant_exists?: "does not match an existing pacticipant"
|
13
7
|
single_line?: "cannot contain multiple lines"
|
14
8
|
no_spaces?: "cannot contain spaces"
|
15
|
-
environment_with_name_exists?: "with name '%{value}' does not exist"
|
16
9
|
none?: "cannot be provided"
|
17
10
|
|
18
11
|
pact_broker:
|
@@ -68,33 +61,61 @@ en:
|
|
68
61
|
version_branch: Configure the version branch to be the value of your repository branch.
|
69
62
|
errors:
|
70
63
|
validation:
|
71
|
-
|
64
|
+
no_spaces: "cannot contain spaces"
|
65
|
+
single_line: "cannot contain multiple lines"
|
66
|
+
environment_not_found: "with name '%{value}' does not exist"
|
67
|
+
blank: "cannot be blank"
|
68
|
+
cannot_be_provided_at_same_time: "%{name_1} and %{name_2} cannot be provided at the same time"
|
69
|
+
blank_with_name: "%{name} cannot be blank"
|
72
70
|
attribute_missing: "Missing required attribute '%{attribute}'"
|
73
71
|
invalid_http_method: "Invalid HTTP method '%{method}'"
|
74
72
|
invalid_url: "Invalid URL '%{url}'. Expected format: http://example.org"
|
75
73
|
pact_missing_pacticipant_name: "was not found at expected path $.%{pacticipant}.name in the submitted pact file."
|
76
|
-
pact_content_modification_not_allowed: "Cannot change the content of the pact for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}, as race conditions will cause unreliable results for can-i-deploy. Each pact must be published with a unique consumer version number. For more information see https://docs.pact.io/go/versioning"
|
74
|
+
pact_content_modification_not_allowed: "Cannot change the content of the pact for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}, as race conditions will cause unreliable results for can-i-deploy. Each pact must be published with a unique consumer version number. Some Pact libraries generate random data when a concrete value for a type matcher is not specified, and this can cause the contract to mutate - ensure you have given example values for all type matchers. For more information see https://docs.pact.io/go/versioning"
|
77
75
|
consumer_version_number_missing: "Please specify the consumer version number by setting the X-Pact-Consumer-Version header."
|
78
76
|
consumer_version_number_header_invalid: "X-Pact-Consumer-Version '%{consumer_version_number}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
79
|
-
consumer_version_number_invalid: "Consumer version number '%{consumer_version_number}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
80
77
|
pacticipant_name_mismatch: "in pact ('%{name_in_pact}') does not match %{pacticipant} name in path ('%{name}')."
|
81
|
-
consumer_name_in_content_mismatch_pacticipant_name: "consumer name in contract content ('%{consumer_name_in_content}') must match pacticipantName ('%{pacticipant_name}')"
|
82
78
|
consumer_name_in_contract_mismatch_pacticipant_name: "consumerName ('%{consumer_name_in_contract}') must match pacticipantName ('%{pacticipant_name}')"
|
83
|
-
|
79
|
+
consumer_name_in_content_mismatch: "consumer name in contract content ('%{consumer_name_in_content}') must match consumerName in contract params ('%{consumer_name}')"
|
80
|
+
provider_name_in_content_mismatch: "provider name in contract content ('%{provider_name_in_content}') must match providerName in contract params ('%{provider_name}')"
|
84
81
|
connection_encoding_not_utf8: "The Sequel connection encoding (%{encoding}) is strongly recommended to be \"utf8\". If you need to set it to %{encoding} for some particular reason, then disable this check by setting config.validate_database_connection_config = false"
|
85
82
|
invalid_webhook_uuid: The UUID can only contain the characters A-Z, a-z, 0-9, _ and -, and must be 16 or more characters.
|
86
83
|
pacticipant_not_found: No pacticipant with name '%{name}' found
|
87
|
-
environment_name_must_be_unique:
|
84
|
+
environment_name_must_be_unique: "name '%{name}' is already used by an existing environment."
|
88
85
|
must_specify_environment_or_tag: Must specify either an environment or a 'to' tag.
|
89
86
|
cannot_specify_tag_and_environment: Cannot specify both a 'to' tag and an environment.
|
90
87
|
cannot_specify_latest_and_environment: Cannot specify both latest=true and an environment.
|
91
88
|
cannot_specify_more_than_one_destination_identifier: Cannot specify more than one of tag, environment and mainBranch.
|
92
89
|
environment_with_name_not_found: "Environment with name '%{name}' does not exist"
|
93
90
|
cannot_modify_version_branch: "The branch for a pacticipant version cannot be changed once set (currently '%{old_branch}', proposed value '%{new_branch}'). Your pact publication/verification publication configurations may be in conflict with each other if you are seeing this error. If the current branch value is incorrect, you must delete the pacticipant version resource at %{version_url} and publish the pacts/verification results again with a consistent branch name."
|
94
|
-
invalid_content_for_content_type: "
|
91
|
+
invalid_content_for_content_type: "content could not be parsed as %{content_type}"
|
95
92
|
cannot_set_currently_deployed_true: The currentlyDeployed property cannot be set back to true. Please record a new deployment.
|
96
93
|
cannot_set_currently_supported_true: The currentlySupported property cannot be set back to true. Please record a new deployment.
|
97
94
|
invalid_limit: The limit must be 1 or greater.
|
95
|
+
pacts_for_verification_selector_fallback_tag: "fallbackTag can only be set if latest is true"
|
96
|
+
pacts_for_verification_selector_matching_branch_requires_provider_version_branch: the providerVersionBranch must be specified when the selector matchingBranch=true is used
|
97
|
+
pacts_for_verification_selector_tag_and_branch_disallowed: "cannot specify both a tag and a branch"
|
98
|
+
pacts_for_verification_selector_fallback_tag_requires_tag: "a tag must be specified when a fallbackTag is specified"
|
99
|
+
pacts_for_verification_selector_fallback_branch_requires_branch: "a branch must be specified when a fallbackBranch is specified"
|
100
|
+
pacts_for_verification_selector_branch_and_latest_false_disallowed: cannot specify a branch with latest=false
|
101
|
+
pacts_for_verification_selector_main_branch_and_latest_false_disallowed: cannot specify mainBranch=true with latest=false
|
102
|
+
pacts_for_verification_selector_fallback_branch_and_latest_false_disallowed: fallbackBranch can only be set if latest is true
|
103
|
+
pacts_for_verification_selector_required_params_missing: must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true
|
104
|
+
pacts_for_verification_selector_main_branch_with_other_param_disallowed: cannot specify mainBranch=true with any other criteria apart from consumer
|
105
|
+
pacts_for_verification_selector_matching_branch_with_other_param_disallowed: cannot specify matchingBranch=true with any other criteria apart from consumer
|
106
|
+
pacts_for_verification_selector_deployed_and_released_disallowed: cannot specify both deployed=true and released=true
|
107
|
+
pacts_for_verification_selector_deployed_and_deployed_or_released_disallowed: cannot specify both deployed=true and deployedOrReleased=true
|
108
|
+
pacts_for_verification_selector_released_and_deployed_or_released_disallowed: cannot specify both released=true and deployedOrReleased=true
|
109
|
+
pacts_for_verification_selector_provider_version_branch_empty: when pending or WIP pacts are enabled and there are no tags provided, the provider version branch must not be an empty string, as it is used in the calculations for WIP/pending. A value must be provided (recommended), or it must not be set at all.
|
110
|
+
pact_name_in_path_mismatch_name_in_pact: "name in pact '%{name_in_pact}' does not match name in URL path '%{name_in_path}'."
|
111
|
+
base64: "is not valid Base64"
|
112
|
+
non_utf_8_char_in_contract: "contract content has a non UTF-8 character at char %{char_number} and cannot be parsed as JSON. Fragment preceding invalid character is: '%{fragment}'"
|
113
|
+
invalid_consumer_version_number: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
114
|
+
invalid_version_number: "Version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
115
|
+
invalid_url: "is not a valid URL eg. http://example.org"
|
116
|
+
pacticipant_with_name_not_found: "does not match an existing pacticipant"
|
117
|
+
invalid_http_method: "is not a recognised HTTP method"
|
118
|
+
webhook_templated_host_not_allowed: "cannot have a template parameter in the host"
|
98
119
|
duplicate_pacticipant: |
|
99
120
|
This is the first time a pact has been published for "%{new_name}".
|
100
121
|
The name "%{new_name}" is very similar to the following existing pacticipants:
|
@@ -17,10 +17,10 @@ module PactBroker
|
|
17
17
|
|
18
18
|
def self.from_selectors(selectors)
|
19
19
|
most_specific_criteria = selectors.collect(&:most_specific_criterion)
|
20
|
-
all_pacticipant_ids = selectors.collect(&:pacticipant_id)
|
21
|
-
specified_pacticipant_ids = selectors.select(&:specified?).collect(&:pacticipant_id)
|
22
|
-
pacticipant_version_ids = collect_ids(most_specific_criteria, :pacticipant_version_id)
|
23
|
-
pacticipant_ids = collect_ids(most_specific_criteria, :pacticipant_id)
|
20
|
+
all_pacticipant_ids = selectors.collect(&:pacticipant_id).uniq
|
21
|
+
specified_pacticipant_ids = selectors.select(&:specified?).collect(&:pacticipant_id).uniq
|
22
|
+
pacticipant_version_ids = collect_ids(most_specific_criteria, :pacticipant_version_id).uniq
|
23
|
+
pacticipant_ids = collect_ids(most_specific_criteria, :pacticipant_id).uniq
|
24
24
|
QueryIds.new(all_pacticipant_ids, specified_pacticipant_ids, pacticipant_ids, pacticipant_version_ids)
|
25
25
|
end
|
26
26
|
|
@@ -1,12 +1,17 @@
|
|
1
|
+
require "pact_broker/hash_refinements"
|
2
|
+
|
1
3
|
# A selector with the pacticipant id, name, version number, and version id set
|
2
4
|
# This is created from either specified or inferred data, based on the user's query
|
3
5
|
# eg.
|
4
6
|
# can-i-deploy --pacticipant Foo --version 1 (this is a specified selector)
|
5
7
|
# --to prod (this is used to create inferred selectors)
|
8
|
+
|
6
9
|
module PactBroker
|
7
10
|
module Matrix
|
8
11
|
class ResolvedSelector < Hash
|
9
12
|
|
13
|
+
using PactBroker::HashRefinements
|
14
|
+
|
10
15
|
# A version ID of -1 will not match any rows, which is what we want to ensure that
|
11
16
|
# no matrix rows are returned for a version that does not exist.
|
12
17
|
NULL_VERSION_ID = -1
|
@@ -124,7 +129,7 @@ module PactBroker
|
|
124
129
|
end
|
125
130
|
|
126
131
|
def only_pacticipant_name_specified?
|
127
|
-
!!pacticipant_name &&
|
132
|
+
!!pacticipant_name && self[:original_selector].without(:pacticipant_name).none?{ |_key, value| value }
|
128
133
|
end
|
129
134
|
|
130
135
|
def latest_tagged?
|
data/lib/pact_broker/messages.rb
CHANGED
@@ -16,13 +16,17 @@ module PactBroker
|
|
16
16
|
# variables to interpolate.
|
17
17
|
# @return [String] the interpolated string
|
18
18
|
def message(key, options={})
|
19
|
-
::I18n.t(key, { :scope => :pact_broker }.merge(options))
|
19
|
+
::I18n.t(key, **{ :scope => :pact_broker }.merge(options))
|
20
20
|
end
|
21
21
|
|
22
22
|
def validation_message key, options = {}
|
23
23
|
message("errors.validation." + key, options)
|
24
24
|
end
|
25
25
|
|
26
|
+
def validation_message_at_index key, index, options = {}
|
27
|
+
message("errors.validation." + key, options).chomp(".") + " (at index #{index})"
|
28
|
+
end
|
29
|
+
|
26
30
|
def pluralize(word, count)
|
27
31
|
if count == 1
|
28
32
|
word
|
@@ -2,13 +2,15 @@ require "sequel"
|
|
2
2
|
require "pact_broker/domain/pacticipant"
|
3
3
|
require "pact_broker/repositories/helpers"
|
4
4
|
require "pact_broker/error"
|
5
|
+
require "pact_broker/repositories/scopes"
|
5
6
|
|
6
7
|
module PactBroker
|
7
8
|
module Pacticipants
|
8
9
|
class Repository
|
9
10
|
|
10
|
-
include PactBroker::Repositories::Helpers
|
11
11
|
include PactBroker::Repositories
|
12
|
+
include PactBroker::Repositories::Helpers
|
13
|
+
include PactBroker::Repositories::Scopes
|
12
14
|
|
13
15
|
def find_by_name name
|
14
16
|
pacticipants = PactBroker::Domain::Pacticipant.where(name_like(:name, name)).all
|
@@ -22,6 +24,13 @@ module PactBroker
|
|
22
24
|
pacticipant
|
23
25
|
end
|
24
26
|
|
27
|
+
# @param [Array<String>] the array of names by which to find the pacticipants
|
28
|
+
def find_by_names(names)
|
29
|
+
return [] if names.empty?
|
30
|
+
name_likes = names.collect{ | name | name_like(:name, name) }
|
31
|
+
scope_for(PactBroker::Domain::Pacticipant).where(Sequel.|(*name_likes)).all
|
32
|
+
end
|
33
|
+
|
25
34
|
def find_by_id id
|
26
35
|
PactBroker::Domain::Pacticipant.where(id: id).single_record
|
27
36
|
end
|
@@ -31,7 +40,7 @@ module PactBroker
|
|
31
40
|
end
|
32
41
|
|
33
42
|
def find(options = {}, pagination_options = {})
|
34
|
-
query = PactBroker::Domain::Pacticipant.select_all_qualified
|
43
|
+
query = scope_for(PactBroker::Domain::Pacticipant).select_all_qualified
|
35
44
|
query = query.label(options[:label_name]) if options[:label_name]
|
36
45
|
query.order_ignore_case(Sequel[:pacticipants][:name]).eager(:labels).eager(:latest_version).all_with_pagination_options(pagination_options)
|
37
46
|
end
|
@@ -96,7 +105,7 @@ module PactBroker
|
|
96
105
|
def search_by_name(pacticipant_name)
|
97
106
|
terms = pacticipant_name.split.map { |v| v.gsub("_", "\\_") }
|
98
107
|
string_match_query = Sequel.|( *terms.map { |term| Sequel.ilike(Sequel[:pacticipants][:name], "%#{term}%") })
|
99
|
-
PactBroker::Domain::Pacticipant.where(string_match_query)
|
108
|
+
scope_for(PactBroker::Domain::Pacticipant).where(string_match_query)
|
100
109
|
end
|
101
110
|
|
102
111
|
def set_main_branch(pacticipant, main_branch)
|
@@ -40,6 +40,13 @@ module PactBroker
|
|
40
40
|
pacticipant_repository.find_by_name(name)
|
41
41
|
end
|
42
42
|
|
43
|
+
# Used by pf
|
44
|
+
# @param [Array<String>]
|
45
|
+
# @return [Array<PactBroker::Domain::Pacticipant>]
|
46
|
+
def self.find_pacticipants_by_names(names)
|
47
|
+
pacticipant_repository.find_by_names(names)
|
48
|
+
end
|
49
|
+
|
43
50
|
def self.find_pacticipant_by_name!(name)
|
44
51
|
pacticipant_repository.find_by_name!(name)
|
45
52
|
end
|
@@ -81,24 +81,13 @@ module PactBroker
|
|
81
81
|
self[:provider_name_in_pact]
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
85
|
-
|
84
|
+
def to_hash_for_validation
|
85
|
+
{
|
86
|
+
consumer_version_number: consumer_version_number,
|
87
|
+
consumer: { name: consumer_name, name_in_pact: consumer_name_in_pact },
|
88
|
+
provider: { name: provider_name, name_in_pact: provider_name_in_pact }
|
89
|
+
}
|
86
90
|
end
|
87
|
-
|
88
|
-
def provider
|
89
|
-
PacticipantName.new(provider_name, provider_name_in_pact, "provider")
|
90
|
-
end
|
91
|
-
|
92
|
-
class PacticipantName < Struct.new(:name, :name_in_pact, :pacticipant)
|
93
|
-
def message_args
|
94
|
-
{
|
95
|
-
name: name,
|
96
|
-
name_in_pact: name_in_pact,
|
97
|
-
pacticipant: pacticipant
|
98
|
-
}
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
91
|
end
|
103
92
|
end
|
104
93
|
end
|
data/lib/pact_broker/policies.rb
CHANGED
@@ -7,19 +7,19 @@ module PactBroker
|
|
7
7
|
@resource = resource
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def read?
|
11
11
|
true
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def update?
|
15
15
|
true
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def delete?
|
19
19
|
true
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def create?
|
23
23
|
true
|
24
24
|
end
|
25
25
|
|
@@ -3,20 +3,59 @@ require "logger"
|
|
3
3
|
require "erb"
|
4
4
|
require "yaml"
|
5
5
|
require "base64"
|
6
|
+
require "securerandom"
|
6
7
|
|
7
8
|
module PactBroker
|
8
9
|
module Test
|
9
10
|
class HttpTestDataBuilder
|
10
11
|
|
12
|
+
class SetRequestId < Faraday::Middleware
|
13
|
+
def initialize(app, correlation_id, logger)
|
14
|
+
super(app)
|
15
|
+
@correlation_id = correlation_id
|
16
|
+
@logger = logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_request(env)
|
20
|
+
request_id = "#{@correlation_id}-#{Time.now.to_f.to_s[7... -1]}"
|
21
|
+
env.request_headers["X-Request-Id"] = request_id
|
22
|
+
@logger.info("X-Request-Id: #{request_id}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class LogRequestLength < Faraday::Middleware
|
27
|
+
def initialize(app, logger)
|
28
|
+
super(app)
|
29
|
+
@app = app
|
30
|
+
@logger = logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(env)
|
34
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
35
|
+
response = @app.call(env)
|
36
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
37
|
+
elapsed = ending - starting
|
38
|
+
@logger.info "Response time: #{elapsed}"
|
39
|
+
response
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
11
43
|
attr_reader :client, :last_consumer_name, :last_provider_name, :last_consumer_version_number, :last_provider_version_number, :last_provider_version_tag, :last_provider_version_branch
|
12
44
|
|
13
45
|
def initialize(pact_broker_base_url, auth = {})
|
46
|
+
@correlation_id = SecureRandom.hex(10)
|
47
|
+
|
48
|
+
stream = ENV["DEBUG"] == "true" ? $stdout : StringIO.new
|
49
|
+
logger = ::Logger.new(stream)
|
50
|
+
|
14
51
|
@client = Faraday.new(url: pact_broker_base_url) do |faraday|
|
52
|
+
faraday.use LogRequestLength, logger
|
53
|
+
faraday.use SetRequestId, @correlation_id, logger
|
15
54
|
faraday.request :json
|
16
55
|
faraday.response :json, :content_type => /\bjson$/
|
17
56
|
if ENV["DEBUG"] == "true"
|
18
|
-
faraday.response :logger,
|
19
|
-
|
57
|
+
faraday.response :logger, logger, headers: false, body: true do | l |
|
58
|
+
l.filter(/(Authorization: ).*/,'\1[REMOVED]')
|
20
59
|
end
|
21
60
|
end
|
22
61
|
faraday.basic_auth(auth[:username], auth[:password]) if auth[:username]
|
@@ -30,6 +69,11 @@ module PactBroker
|
|
30
69
|
self
|
31
70
|
end
|
32
71
|
|
72
|
+
def print_correlation_id
|
73
|
+
puts "Correlation ID is #{@correlation_id}"
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
33
77
|
def separate
|
34
78
|
puts "\n=============================================================\n\n"
|
35
79
|
end
|
data/lib/pact_broker/ui/app.rb
CHANGED
@@ -26,7 +26,7 @@ module PactBroker
|
|
26
26
|
class App
|
27
27
|
|
28
28
|
def initialize
|
29
|
-
@app = ::Rack::Builder.new
|
29
|
+
@app = ::Rack::Builder.new do
|
30
30
|
|
31
31
|
map "/ui/relationships" do
|
32
32
|
run PactBroker::UI::Controllers::Index
|
@@ -69,7 +69,7 @@ module PactBroker
|
|
69
69
|
use PathInfoFixer
|
70
70
|
run PactBroker::UI::Controllers::Index
|
71
71
|
end
|
72
|
-
|
72
|
+
end
|
73
73
|
end
|
74
74
|
|
75
75
|
def call env
|
data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb
CHANGED
@@ -3,8 +3,8 @@ require "pact_broker/domain/verification"
|
|
3
3
|
module PactBroker
|
4
4
|
module Verifications
|
5
5
|
class LatestVerificationIdForPactVersionAndProviderVersion < Sequel::Model(:latest_verification_id_for_pact_version_and_provider_version)
|
6
|
-
unrestrict_primary_key
|
7
6
|
set_primary_key [:pact_version_id, :provider_version_id]
|
7
|
+
unrestrict_primary_key
|
8
8
|
|
9
9
|
plugin :upsert, identifying_columns: [:pact_version_id, :provider_version_id]
|
10
10
|
|
@@ -5,6 +5,7 @@ require "pact_broker/domain/verification"
|
|
5
5
|
module PactBroker
|
6
6
|
module Verifications
|
7
7
|
class PactVersionProviderTagSuccessfulVerification < Sequel::Model
|
8
|
+
set_primary_key :id
|
8
9
|
plugin :insert_ignore, identifying_columns: [:pact_version_id, :provider_version_tag_name, :wip]
|
9
10
|
end
|
10
11
|
end
|
@@ -57,12 +57,6 @@ module PactBroker
|
|
57
57
|
verification_repository.delete(verification.id)
|
58
58
|
end
|
59
59
|
|
60
|
-
def errors params
|
61
|
-
contract = PactBroker::Api::Contracts::VerificationContract.new(PactBroker::Domain::Verification.new)
|
62
|
-
contract.validate(params)
|
63
|
-
contract.errors
|
64
|
-
end
|
65
|
-
|
66
60
|
def find params
|
67
61
|
verification_repository.find(params.fetch(:consumer_name), params.fetch(:provider_name), params.fetch(:pact_version_sha), params.fetch(:verification_number))
|
68
62
|
end
|
data/lib/pact_broker/version.rb
CHANGED
@@ -4,10 +4,11 @@ require "pact_broker/repositories/helpers"
|
|
4
4
|
module PactBroker
|
5
5
|
module Versions
|
6
6
|
class BranchHead < Sequel::Model
|
7
|
-
plugin :upsert, identifying_columns: [:branch_id]
|
8
7
|
set_primary_key :branch_id
|
9
8
|
unrestrict_primary_key
|
10
9
|
|
10
|
+
plugin :upsert, identifying_columns: [:branch_id]
|
11
|
+
|
11
12
|
associate(:many_to_one, :branch, :class => "PactBroker::Versions::Branch", :key => :branch_id, :primary_key => :id)
|
12
13
|
associate(:many_to_one, :branch_version, :class => "PactBroker::Versions::BranchVersion", :key => :branch_version_id, :primary_key => :id)
|
13
14
|
associate(:many_to_one, :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id)
|
@@ -4,6 +4,7 @@ require "pact_broker/repositories/helpers"
|
|
4
4
|
module PactBroker
|
5
5
|
module Versions
|
6
6
|
class BranchVersion < Sequel::Model(:branch_versions)
|
7
|
+
set_primary_key :id
|
7
8
|
plugin :timestamps, update_on_create: true
|
8
9
|
plugin :insert_ignore, identifying_columns: [:branch_id, :version_id]
|
9
10
|
plugin :upsert, identifying_columns: [:branch_id, :version_id]
|
@@ -38,6 +39,16 @@ module PactBroker
|
|
38
39
|
def pacticipant
|
39
40
|
branch.pacticipant
|
40
41
|
end
|
42
|
+
|
43
|
+
# For Pactflow
|
44
|
+
def main_branch?
|
45
|
+
branch_name == branch.pacticipant.main_branch
|
46
|
+
end
|
47
|
+
|
48
|
+
# For Pactflow
|
49
|
+
def number_of_versions_from_head
|
50
|
+
@number_of_versions_from_head ||= BranchVersion.where(branch_id: branch_id).where(Sequel.lit("version_order > ?", version_order) ).count
|
51
|
+
end
|
41
52
|
end
|
42
53
|
end
|
43
54
|
end
|
@@ -159,7 +159,7 @@ module PactBroker
|
|
159
159
|
|
160
160
|
def find_latest_triggered_webhooks consumer, provider
|
161
161
|
# policy already applied to pact
|
162
|
-
|
162
|
+
scope_for(TriggeredWebhook)
|
163
163
|
.where(consumer: consumer, provider: provider)
|
164
164
|
.latest_triggered_webhooks
|
165
165
|
.all
|
@@ -29,6 +29,7 @@ module PactBroker
|
|
29
29
|
extend PactBroker::Messages
|
30
30
|
|
31
31
|
delegate [
|
32
|
+
:create,
|
32
33
|
:find_by_uuid,
|
33
34
|
:find_all,
|
34
35
|
:update_triggered_webhook_status,
|
@@ -37,34 +38,15 @@ module PactBroker
|
|
37
38
|
:find_latest_triggered_webhooks_for_pact,
|
38
39
|
:fail_retrying_triggered_webhooks,
|
39
40
|
:find_triggered_webhooks_for_pact,
|
40
|
-
:find_triggered_webhooks_for_verification
|
41
|
+
:find_triggered_webhooks_for_verification,
|
42
|
+
:delete_by_uuid
|
41
43
|
] => :webhook_repository
|
42
44
|
|
43
|
-
# Not actually a UUID. Ah well.
|
44
|
-
def valid_uuid_format?(uuid)
|
45
|
-
!!(uuid =~ /^[A-Za-z0-9_\-]{16,}$/)
|
46
|
-
end
|
47
45
|
|
48
46
|
def next_uuid
|
49
47
|
SecureRandom.urlsafe_base64
|
50
48
|
end
|
51
49
|
|
52
|
-
def errors webhook, uuid = nil
|
53
|
-
contract = PactBroker::Api::Contracts::WebhookContract.new(webhook)
|
54
|
-
contract.validate(webhook.attributes)
|
55
|
-
messages = contract.errors.messages
|
56
|
-
|
57
|
-
if uuid && !valid_uuid_format?(uuid)
|
58
|
-
messages["uuid"] = [message("errors.validation.invalid_webhook_uuid")]
|
59
|
-
end
|
60
|
-
|
61
|
-
OpenStruct.new(messages: messages, empty?: messages.empty?, any?: messages.any?)
|
62
|
-
end
|
63
|
-
|
64
|
-
def create uuid, webhook, consumer, provider
|
65
|
-
webhook_repository.create uuid, webhook, consumer, provider
|
66
|
-
end
|
67
|
-
|
68
50
|
def update_by_uuid uuid, params
|
69
51
|
webhook = webhook_repository.find_by_uuid(uuid)
|
70
52
|
maintain_redacted_params(webhook, params)
|
@@ -72,10 +54,6 @@ module PactBroker
|
|
72
54
|
webhook_repository.update_by_uuid uuid, webhook
|
73
55
|
end
|
74
56
|
|
75
|
-
def delete_by_uuid uuid
|
76
|
-
webhook_repository.delete_by_uuid uuid
|
77
|
-
end
|
78
|
-
|
79
57
|
def delete_all_webhhook_related_objects_by_pacticipant pacticipant
|
80
58
|
webhook_repository.delete_by_pacticipant(pacticipant)
|
81
59
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "webmachine"
|
2
|
+
require "webmachine/application_monkey_patch"
|
3
|
+
require "webmachine/adapters/rack_mapped"
|
4
|
+
require "webmachine/application_monkey_patch"
|
5
|
+
require "webmachine/render_error_monkey_patch"
|
6
|
+
|
7
|
+
|
8
|
+
module Webmachine
|
9
|
+
def self.build_rack_api(application_context)
|
10
|
+
api = Webmachine::Application.new do |app|
|
11
|
+
yield app
|
12
|
+
end
|
13
|
+
|
14
|
+
api.application_context = application_context
|
15
|
+
|
16
|
+
api.configure do |config|
|
17
|
+
config.adapter = :RackMapped
|
18
|
+
end
|
19
|
+
|
20
|
+
api.adapter
|
21
|
+
end
|
22
|
+
end
|