pact_broker 2.75.0 → 2.78.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +12 -0
- data/.github/workflows/test-ruby-3.yml +19 -0
- data/.github/workflows/test.yml +19 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +48 -0
- data/DEVELOPER_SETUP.md +62 -3
- data/Dockerfile +1 -0
- data/ISSUES.md +13 -5
- data/README.md +1 -1
- data/config.ru +1 -0
- data/db/ddl_statements/head_pact_tags.rb +24 -1
- data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
- data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
- data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
- data/db/migrations/20210117_add_branch_to_version.rb +9 -0
- data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
- data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
- data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
- data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
- data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
- data/db/migrations/20210210_create_environments_table.rb +16 -0
- data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +44 -0
- data/lib/pact_broker/api.rb +7 -2
- data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
- data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
- data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
- data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
- data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
- data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +8 -2
- data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
- data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
- data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
- data/lib/pact_broker/api/paths.rb +5 -0
- data/lib/pact_broker/api/resources/default_base_resource.rb +15 -2
- data/lib/pact_broker/api/resources/environment.rb +76 -0
- data/lib/pact_broker/api/resources/environments.rb +75 -0
- data/lib/pact_broker/api/resources/index.rb +20 -0
- data/lib/pact_broker/api/resources/latest_version.rb +27 -0
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
- data/lib/pact_broker/api/resources/verifications.rb +5 -2
- data/lib/pact_broker/api/resources/version.rb +15 -9
- data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
- data/lib/pact_broker/app.rb +3 -0
- data/lib/pact_broker/certificates/certificate.rb +1 -1
- data/lib/pact_broker/config/setting.rb +1 -1
- data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
- data/lib/pact_broker/configuration.rb +18 -1
- data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
- data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
- data/lib/pact_broker/db/migrate_data.rb +1 -0
- data/lib/pact_broker/db/seed_example_data.rb +13 -13
- data/lib/pact_broker/deployments/environment.rb +15 -0
- data/lib/pact_broker/deployments/environment_service.rb +39 -0
- data/lib/pact_broker/doc/controllers/app.rb +1 -1
- data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
- data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
- data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
- data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
- data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
- data/lib/pact_broker/domain/index_item.rb +18 -4
- data/lib/pact_broker/domain/pacticipant.rb +9 -5
- data/lib/pact_broker/domain/tag.rb +131 -71
- data/lib/pact_broker/domain/verification.rb +3 -2
- data/lib/pact_broker/domain/version.rb +58 -23
- data/lib/pact_broker/domain/webhook.rb +12 -9
- data/lib/pact_broker/hash_refinements.rb +4 -0
- data/lib/pact_broker/index/service.rb +55 -49
- data/lib/pact_broker/locale/en.yml +3 -1
- data/lib/pact_broker/matrix/quick_row.rb +8 -0
- data/lib/pact_broker/metrics/service.rb +1 -1
- data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
- data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
- data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
- data/lib/pact_broker/pacts/pact_publication.rb +38 -84
- data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
- data/lib/pact_broker/pacts/pact_version.rb +1 -2
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
- data/lib/pact_broker/pacts/repository.rb +5 -231
- data/lib/pact_broker/pacts/selected_pact.rb +4 -0
- data/lib/pact_broker/pacts/selector.rb +56 -1
- data/lib/pact_broker/pacts/selectors.rb +16 -0
- data/lib/pact_broker/pacts/service.rb +6 -8
- data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
- data/lib/pact_broker/pacts/verifiable_pact.rb +45 -2
- data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
- data/lib/pact_broker/repositories/helpers.rb +4 -0
- data/lib/pact_broker/services.rb +9 -0
- data/lib/pact_broker/tags/eager_loaders.rb +47 -0
- data/lib/pact_broker/tags/repository.rb +3 -1
- data/lib/pact_broker/tags/service.rb +0 -3
- data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
- data/lib/pact_broker/test/http_test_data_builder.rb +101 -35
- data/lib/pact_broker/test/test_data_builder.rb +50 -3
- data/lib/pact_broker/ui/app.rb +6 -0
- data/lib/pact_broker/ui/controllers/base_controller.rb +5 -1
- data/lib/pact_broker/ui/controllers/pacts.rb +18 -0
- data/lib/pact_broker/ui/view_models/index_item.rb +9 -0
- data/lib/pact_broker/ui/view_models/matrix_line.rb +36 -0
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +8 -0
- data/lib/pact_broker/ui/views/matrix/show.haml +10 -0
- data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
- data/lib/pact_broker/verifications/service.rb +2 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/eager_loaders.rb +71 -0
- data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
- data/lib/pact_broker/versions/repository.rb +22 -2
- data/lib/pact_broker/versions/service.rb +5 -1
- data/lib/pact_broker/webhooks/execution.rb +3 -2
- data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
- data/lib/pact_broker/webhooks/service.rb +8 -7
- data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
- data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
- data/lib/pact_broker/webhooks/webhook.rb +1 -1
- data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
- data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
- data/lib/pact_broker/webhooks/webhook_request_logger.rb +5 -1
- data/lib/rack/pact_broker/set_base_url.rb +22 -0
- data/lib/sequel/plugins/upsert.rb +18 -4
- data/public/stylesheets/index.css +22 -1
- data/public/stylesheets/matrix.css +0 -21
- data/regression/can_i_deploy_spec.rb +5 -4
- data/regression/index_spec.rb +26 -0
- data/regression/regression_helper.rb +29 -3
- data/regression/script/clear.sh +3 -0
- data/regression/script/run.sh +3 -0
- data/script/demonstrate-version-branches.rb +33 -0
- data/script/pry.rb +2 -2
- data/script/reproduce-issue-starting-up.rb +13 -23
- data/script/reproduce-issue.rb +18 -14
- data/script/trigger-release.sh +1 -1
- data/script/webhook-server.ru +5 -5
- data/spec/features/create_environment_spec.rb +47 -0
- data/spec/features/create_tag_spec.rb +32 -0
- data/spec/features/create_version_spec.rb +70 -0
- data/spec/features/delete_environment_spec.rb +16 -0
- data/spec/features/end_deployment_spec.rb +29 -0
- data/spec/features/get_environment_spec.rb +19 -0
- data/spec/features/get_environments_spec.rb +20 -0
- data/spec/features/record_deployment_spec.rb +28 -0
- data/spec/features/update_environment_spec.rb +44 -0
- data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
- data/spec/fixtures/dashboard.json +4 -2
- data/spec/integration/ui/index_spec.rb +4 -4
- data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
- data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
- data/spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb +6 -6
- data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
- data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
- data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +1 -12
- data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
- data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
- data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
- data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
- data/spec/lib/pact_broker/configuration_spec.rb +12 -0
- data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
- data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
- data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
- data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
- data/spec/lib/pact_broker/index/service_spec.rb +89 -15
- data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
- data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
- data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
- data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +46 -7
- data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
- data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
- data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
- data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
- data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
- data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
- data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
- data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
- data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
- data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
- data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
- data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
- data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
- data/spec/spec_helper.rb +17 -5
- data/spec/support/approvals.rb +24 -0
- data/spec/support/shared_examples_for_responses.rb +11 -0
- data/tasks/db.rake +1 -0
- data/tasks/rspec.rake +1 -1
- metadata +69 -4
- data/docker-compose-issue-repro.yml +0 -22
@@ -5,6 +5,10 @@ module PactBroker
|
|
5
5
|
def column_exists?(connection, table, column)
|
6
6
|
connection.table_exists?(table) && connection.schema(table).find{|col| col.first == column }
|
7
7
|
end
|
8
|
+
|
9
|
+
def columns_exist?(connection, table, columns)
|
10
|
+
columns.all?{ | column | column_exists?(connection, table, column) }
|
11
|
+
end
|
8
12
|
end
|
9
13
|
end
|
10
14
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'pact_broker/db/data_migrations/helpers'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module DB
|
5
|
+
module DataMigrations
|
6
|
+
class SetExtraColumnsForTags
|
7
|
+
extend Helpers
|
8
|
+
|
9
|
+
def self.call(connection)
|
10
|
+
if columns_exist?(connection, :tags, [:version_id, :pacticipant_id]) &&
|
11
|
+
columns_exist?(connection, :versions, [:id, :pacticipant_id])
|
12
|
+
connection[:tags].update(
|
13
|
+
pacticipant_id: connection[:versions].select(:pacticipant_id)
|
14
|
+
.where(Sequel[:versions][:id] => Sequel[:tags][:version_id])
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
if columns_exist?(connection, :tags, [:version_id, :version_order]) &&
|
19
|
+
columns_exist?(connection, :versions, [:id, :order])
|
20
|
+
connection[:tags].update(
|
21
|
+
version_order: connection[:versions].select(:order)
|
22
|
+
.where(Sequel[:versions][:id] => Sequel[:tags][:version_id])
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -21,6 +21,7 @@ module PactBroker
|
|
21
21
|
DataMigrations::DeleteDeprecatedWebhookExecutions.call(database_connection)
|
22
22
|
DataMigrations::SetCreatedAtForLatestPactPublications.call(database_connection)
|
23
23
|
DataMigrations::SetCreatedAtForLatestVerifications.call(database_connection)
|
24
|
+
DataMigrations::SetExtraColumnsForTags.call(database_connection)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
@@ -16,25 +16,25 @@ module PactBroker
|
|
16
16
|
PactBroker::Test::TestDataBuilder.new
|
17
17
|
.create_consumer(consumer_name, created_at: days_ago(16))
|
18
18
|
.create_provider(provider_name, created_at: days_ago(16))
|
19
|
-
.create_consumer_version("e15da45d3943bf10793a6d04cfb9f5dabe430fe2", created_at: days_ago(16))
|
19
|
+
.create_consumer_version("e15da45d3943bf10793a6d04cfb9f5dabe430fe2", branch: "main", created_at: days_ago(16))
|
20
20
|
.create_consumer_version_tag("prod", created_at: days_ago(16))
|
21
|
-
.create_consumer_version_tag("
|
21
|
+
.create_consumer_version_tag("main", created_at: days_ago(16))
|
22
22
|
.create_pact(json_content: pact_1, created_at: days_ago(16))
|
23
|
-
.create_verification(provider_version: "1315e0b1924cb6f42751f977789be3559373033a", execution_date: days_ago(15))
|
24
|
-
.create_provider_version_tag("
|
23
|
+
.create_verification(provider_version: "1315e0b1924cb6f42751f977789be3559373033a", branch: "main", execution_date: days_ago(15))
|
24
|
+
.create_provider_version_tag("main", created_at: days_ago(14))
|
25
25
|
.create_provider_version_tag("prod", created_at: days_ago(14))
|
26
|
-
.create_verification(provider_version: "480e5aeb30467856ca995d0024d2c1800b0719e5", success: false, number: 2, execution_date: days_ago(14))
|
27
|
-
.create_provider_version_tag("
|
28
|
-
.create_consumer_version("725c6ccb7cf7efc51b4394f9828585eea9c379d9", created_at: days_ago(7))
|
26
|
+
.create_verification(provider_version: "480e5aeb30467856ca995d0024d2c1800b0719e5", branch: "main", success: false, number: 2, execution_date: days_ago(14))
|
27
|
+
.create_provider_version_tag("main", created_at: days_ago(14))
|
28
|
+
.create_consumer_version("725c6ccb7cf7efc51b4394f9828585eea9c379d9", branch: "feat/new-thing", created_at: days_ago(7))
|
29
29
|
.create_consumer_version_tag("feat-new-thing", created_at: days_ago(7))
|
30
30
|
.create_pact(json_content: pact_2, created_at: days_ago(7))
|
31
|
-
.create_consumer_version("7bd4d9173522826dc3e8704fd62dde0424f4c827", created_at: days_ago(1))
|
32
|
-
.create_consumer_version_tag("
|
31
|
+
.create_consumer_version("7bd4d9173522826dc3e8704fd62dde0424f4c827", branch: "main", created_at: days_ago(1))
|
32
|
+
.create_consumer_version_tag("main", created_at: days_ago(1))
|
33
33
|
.create_pact(json_content: pact_3, created_at: days_ago(1))
|
34
|
-
.create_verification(provider_version: "4fdf20082263d4c5038355a3b734be1c0054d1e1", execution_date: days_ago(1))
|
35
|
-
.create_provider_version_tag("
|
36
|
-
.create_consumer_version("5556b8149bf8bac76bc30f50a8a2dd4c22c85f30", created_at: days_ago(0.5))
|
37
|
-
.create_consumer_version_tag("
|
34
|
+
.create_verification(provider_version: "4fdf20082263d4c5038355a3b734be1c0054d1e1", branch: "main", execution_date: days_ago(1))
|
35
|
+
.create_provider_version_tag("main", created_at: days_ago(1))
|
36
|
+
.create_consumer_version("5556b8149bf8bac76bc30f50a8a2dd4c22c85f30", branch: "main", created_at: days_ago(0.5))
|
37
|
+
.create_consumer_version_tag("main", created_at: days_ago(0.5))
|
38
38
|
.republish_same_pact(created_at: days_ago(0.5))
|
39
39
|
end
|
40
40
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'sequel/plugins/serialization'
|
3
|
+
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module Deployments
|
7
|
+
class Environment < Sequel::Model
|
8
|
+
OPEN_STRUCT_TO_JSON = lambda { |thing| Sequel.object_to_json(thing.collect(&:to_h)) }
|
9
|
+
JSON_TO_OPEN_STRUCT = lambda { | json | Sequel.parse_json(json).collect{ | hash| OpenStruct.new(hash) } }
|
10
|
+
plugin :upsert, identifying_columns: [:uuid]
|
11
|
+
plugin :serialization
|
12
|
+
serialize_attributes [OPEN_STRUCT_TO_JSON, JSON_TO_OPEN_STRUCT], :contacts
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pact_broker/deployments/environment'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Deployments
|
6
|
+
module EnvironmentService
|
7
|
+
|
8
|
+
def self.next_uuid
|
9
|
+
SecureRandom.uuid
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(uuid, environment)
|
13
|
+
environment.uuid = uuid
|
14
|
+
environment.save
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.update(uuid, environment)
|
18
|
+
environment.uuid = uuid
|
19
|
+
environment.upsert
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.find_all
|
23
|
+
PactBroker::Deployments::Environment.order(Sequel.function(:lower, :display_name)).all
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.find(uuid)
|
27
|
+
PactBroker::Deployments::Environment.where(uuid: uuid).single_record
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find_by_name(name)
|
31
|
+
PactBroker::Deployments::Environment.where(name: name).single_record
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.delete(uuid)
|
35
|
+
PactBroker::Deployments::Environment.where(uuid: uuid).delete
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -51,7 +51,7 @@ module PactBroker
|
|
51
51
|
# https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
|
52
52
|
# Either use the explicitly configured base url or an empty string,
|
53
53
|
# rather than request.base_url, which uses the X-Forwarded headers.
|
54
|
-
env["pactbroker.base_url"] ||
|
54
|
+
env["pactbroker.base_url"] || ''
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Environment
|
2
|
+
|
3
|
+
Allowed methods: `GET`, `PUT`, `DELETE`
|
4
|
+
|
5
|
+
Path: `/environment/{uuid}`
|
6
|
+
|
7
|
+
## Viewing an environment
|
8
|
+
|
9
|
+
Example:
|
10
|
+
|
11
|
+
curl http://${PACT_BROKER_HOST}/environments/79060381-269c-4769-9894-9ec3cab44729 \
|
12
|
+
-H "Accept: application/hal+json"
|
13
|
+
{
|
14
|
+
"uuid": "79060381-269c-4769-9894-9ec3cab44729",
|
15
|
+
"name": "test",
|
16
|
+
"displayName": "Test",
|
17
|
+
"production": false
|
18
|
+
}
|
19
|
+
|
20
|
+
## Updating an environment
|
21
|
+
|
22
|
+
Example:
|
23
|
+
|
24
|
+
curl -X PUT http://${PACT_BROKER_HOST}/environments/79060381-269c-4769-9894-9ec3cab44729 \
|
25
|
+
-H "Content-Type: application/json" \
|
26
|
+
-H "Accept: application/hal+json" \
|
27
|
+
-d '{
|
28
|
+
"name": "test",
|
29
|
+
"displayName": "Test",
|
30
|
+
"production": false
|
31
|
+
}'
|
32
|
+
|
33
|
+
## Deleting an environment
|
34
|
+
|
35
|
+
Example:
|
36
|
+
|
37
|
+
curl -v -X DELETE http://${PACT_BROKER_HOST}/environments/79060381-269c-4769-9894-9ec3cab44729
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Environments
|
2
|
+
|
3
|
+
Allowed methods: `GET`, `POST`
|
4
|
+
|
5
|
+
Path: `/environments`
|
6
|
+
|
7
|
+
## Creating an environment
|
8
|
+
|
9
|
+
Send a POST to `/environments` with the environment payload.
|
10
|
+
|
11
|
+
Example:
|
12
|
+
|
13
|
+
curl http://${PACT_BROKER_HOST}/environments \
|
14
|
+
-H "Content-Type: application/json" \
|
15
|
+
-H "Accept: application/hal+json" \
|
16
|
+
-d '{
|
17
|
+
"name": "test",
|
18
|
+
"displayName": "Test",
|
19
|
+
"production": false
|
20
|
+
}'
|
21
|
+
|
22
|
+
Alternatively, you can use the HAL Browser.
|
23
|
+
|
24
|
+
* Click on the `API Browser` link at the top of the Pact Broker index page.
|
25
|
+
* In the `Links` section on the left, locate the `pb:environments` relation, and click on the yellow `!` "Perform non-GET request" button.
|
26
|
+
* In the `Body:` text box, fill in the required JSON properties.
|
27
|
+
* Click `Make Request`.
|
28
|
+
|
29
|
+
Properties:
|
30
|
+
|
31
|
+
* `uuid`: System generated unique identifier.
|
32
|
+
* `name`: Must be unique. No spaces allowed. This will be the name used in the `can-i-deploy` and `record-deployment` CLI commands. eg. "payments-sit-1"
|
33
|
+
* `displayName`: A more verbose name for the environment. "Payments Team SIT 1"
|
34
|
+
* `production`: Whether or not this environment is a production environment.
|
35
|
+
|
36
|
+
If all the services in the Broker are deployed to the same "public" internet, then there only needs to be one Production environment. If there are multiple segregated production environments (eg. when maintaining on-premises software for multiple customers ) then you should create a separate production Environment for each logical deployment environment.
|
37
|
+
|
38
|
+
## Listing environments
|
39
|
+
|
40
|
+
`GET /environments`
|
41
|
+
|
42
|
+
{
|
43
|
+
"_embedded": {
|
44
|
+
"environments": [
|
45
|
+
{
|
46
|
+
"uuid": "79060381-269c-4769-9894-9ec3cab44729",
|
47
|
+
"name": "production",
|
48
|
+
"displayName": "Production",
|
49
|
+
"production": true
|
50
|
+
}
|
51
|
+
]
|
52
|
+
}
|
53
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Pacticipant version
|
2
|
+
|
3
|
+
Allowed methods: `GET`, `PUT`, `DELETE`
|
4
|
+
|
5
|
+
Path: `/pacticipants/{pacticipant}/versions/{version}`
|
6
|
+
|
7
|
+
## Example
|
8
|
+
|
9
|
+
PUT http://broker/pacticipants/Bar/versions/1e70030c6579915e5ff56b107a0fd25cf5df7464
|
10
|
+
{
|
11
|
+
"branch": "main",
|
12
|
+
"buildUrl": "http://ci.mydomain/my-job/1"
|
13
|
+
}
|
@@ -13,13 +13,13 @@ module PactBroker
|
|
13
13
|
:latest_verification_latest_tags
|
14
14
|
|
15
15
|
# rubocop:disable Metrics/ParameterLists
|
16
|
-
def self.create(consumer, provider, latest_pact, latest, latest_verification, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = [])
|
17
|
-
new(consumer, provider, latest_pact, latest, latest_verification, webhooks, triggered_webhooks, tags, latest_verification_latest_tags)
|
16
|
+
def self.create(consumer, provider, latest_pact, latest, latest_verification, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = [], latest_for_branch = nil)
|
17
|
+
new(consumer, provider, latest_pact, latest, latest_verification, webhooks, triggered_webhooks, tags, latest_verification_latest_tags, latest_for_branch)
|
18
18
|
end
|
19
19
|
# rubocop:enable Metrics/ParameterLists
|
20
20
|
|
21
21
|
# rubocop:disable Metrics/ParameterLists
|
22
|
-
def initialize(consumer, provider, latest_pact = nil, latest = true, latest_verification = nil, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = [])
|
22
|
+
def initialize(consumer, provider, latest_pact = nil, latest = true, latest_verification = nil, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = [], latest_for_branch = nil)
|
23
23
|
@consumer = consumer
|
24
24
|
@provider = provider
|
25
25
|
@latest_pact = latest_pact
|
@@ -29,6 +29,7 @@ module PactBroker
|
|
29
29
|
@triggered_webhooks = triggered_webhooks
|
30
30
|
@tags = tags
|
31
31
|
@latest_verification_latest_tags = latest_verification_latest_tags
|
32
|
+
@latest_for_branch = latest_for_branch
|
32
33
|
end
|
33
34
|
# rubocop:enable Metrics/ParameterLists
|
34
35
|
|
@@ -37,7 +38,8 @@ module PactBroker
|
|
37
38
|
other.latest_pact == latest_pact &&
|
38
39
|
other.latest? == latest? &&
|
39
40
|
other.latest_verification == latest_verification &&
|
40
|
-
other.webhooks == webhooks
|
41
|
+
other.webhooks == webhooks &&
|
42
|
+
other.latest_for_branch? == latest_for_branch?
|
41
43
|
end
|
42
44
|
|
43
45
|
def == other
|
@@ -68,6 +70,14 @@ module PactBroker
|
|
68
70
|
@latest_pact.consumer_version
|
69
71
|
end
|
70
72
|
|
73
|
+
def consumer_version_branch
|
74
|
+
consumer_version.branch
|
75
|
+
end
|
76
|
+
|
77
|
+
def latest_for_branch?
|
78
|
+
@latest_for_branch
|
79
|
+
end
|
80
|
+
|
71
81
|
def provider_version
|
72
82
|
@latest_verification ? @latest_verification.provider_version : nil
|
73
83
|
end
|
@@ -76,6 +86,10 @@ module PactBroker
|
|
76
86
|
@latest_verification ? @latest_verification.provider_version_number : nil
|
77
87
|
end
|
78
88
|
|
89
|
+
def provider_version_branch
|
90
|
+
provider_version&.branch
|
91
|
+
end
|
92
|
+
|
79
93
|
# these are the consumer tag names for which this pact publication
|
80
94
|
# is the latest with that tag
|
81
95
|
def tag_names
|
@@ -27,6 +27,10 @@ module PactBroker
|
|
27
27
|
filter = name_like(Sequel[:labels][:name], label_name)
|
28
28
|
join(:labels, {pacticipant_id: :id}).where(filter)
|
29
29
|
end
|
30
|
+
|
31
|
+
def find_by_name(name)
|
32
|
+
where(name_like(:name, name))
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def before_destroy
|
@@ -51,17 +55,17 @@ module PactBroker
|
|
51
55
|
messages << message('errors.validation.attribute_missing', attribute: 'name') unless name
|
52
56
|
messages
|
53
57
|
end
|
58
|
+
|
59
|
+
def any_versions?
|
60
|
+
PactBroker::Domain::Version.where(pacticipant: self).any?
|
61
|
+
end
|
54
62
|
end
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
66
|
# Table: pacticipants
|
63
67
|
# Columns:
|
64
|
-
# id | integer | PRIMARY KEY DEFAULT
|
68
|
+
# id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
|
65
69
|
# name | text |
|
66
70
|
# repository_url | text |
|
67
71
|
# created_at | timestamp without time zone | NOT NULL
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pact_broker/db'
|
2
2
|
require 'pact_broker/repositories/helpers'
|
3
|
+
require 'pact_broker/tags/eager_loaders'
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Domain
|
@@ -10,47 +11,43 @@ module PactBroker
|
|
10
11
|
unrestrict_primary_key
|
11
12
|
associate(:many_to_one, :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id)
|
12
13
|
|
14
|
+
# The tag for the latest version that has a tag with a matching name
|
15
|
+
many_to_one :head_tag, read_only: true, key: [:name, :pacticipant_id],
|
16
|
+
class: Tag,
|
17
|
+
dataset: lambda {
|
18
|
+
Tag.where(name: name, pacticipant_id: pacticipant_id)
|
19
|
+
.order(Sequel.desc(:version_order))
|
20
|
+
.limit(1)
|
21
|
+
},
|
22
|
+
eager_loader: PactBroker::Tags::EagerLoaders::HeadTag
|
23
|
+
|
13
24
|
dataset_module do
|
14
25
|
include PactBroker::Repositories::Helpers
|
15
26
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
}
|
27
|
+
def join_pact_publications
|
28
|
+
join(:pact_publications, { Sequel[:tags][:version_id] => Sequel[:pact_publications][:consumer_version_id] } )
|
29
|
+
end
|
20
30
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
def for(pacticipant_name, version_number, tag_name)
|
32
|
+
where(
|
33
|
+
version_id: db[:versions].select(:id).where(
|
34
|
+
number: version_number,
|
35
|
+
pacticipant_id: db[:pacticipants].select(:id).where(name_like(:name, pacticipant_name))
|
36
|
+
),
|
37
|
+
name: tag_name
|
38
|
+
).single_record
|
39
|
+
end
|
26
40
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
41
|
+
def latest_tags
|
42
|
+
self_join = {
|
43
|
+
Sequel[:tags][:pacticipant_id] => Sequel[:tags_2][:pacticipant_id],
|
44
|
+
Sequel[:tags][:name] => Sequel[:tags_2][:name]
|
45
|
+
}
|
31
46
|
|
32
47
|
PactBroker::Domain::Tag
|
33
48
|
.select_all_qualified
|
34
|
-
.
|
35
|
-
|
36
|
-
)
|
37
|
-
.join(latest_tags, latest_tags_versions_join, { table_alias: :latest_tags })
|
38
|
-
end
|
39
|
-
|
40
|
-
# Ron's fancy join
|
41
|
-
# performs every so slightly better
|
42
|
-
def latest_tags_2
|
43
|
-
tag_versions = PactBroker::Domain::Tag
|
44
|
-
.select_all_qualified
|
45
|
-
.select_append(Sequel[:versions][:pacticipant_id])
|
46
|
-
.select_append(Sequel[:versions][:order])
|
47
|
-
.join(:versions,
|
48
|
-
{ Sequel[:tags][:version_id] => Sequel[:versions][:id] }
|
49
|
-
)
|
50
|
-
|
51
|
-
tag_versions
|
52
|
-
.left_join(tag_versions, { Sequel[:tags][:name] => Sequel[:tags_2][:name], Sequel[:versions][:pacticipant_id] => Sequel[:tags_2][:pacticipant_id] }, { table_alias: :tags_2 }) do | table, joined_table, js |
|
53
|
-
Sequel.qualify(table, :order) > Sequel.qualify(joined_table, :order)
|
49
|
+
.left_join(:tags, self_join, { table_alias: :tags_2 }) do
|
50
|
+
Sequel[:tags_2][:version_order] > Sequel[:tags][:version_order]
|
54
51
|
end
|
55
52
|
.where(Sequel[:tags_2][:name] => nil)
|
56
53
|
end
|
@@ -58,32 +55,40 @@ module PactBroker
|
|
58
55
|
# Does NOT care about whether or not there is a pact publication
|
59
56
|
# for the version
|
60
57
|
def latest_tags_for_pacticipant_ids(pacticipant_ids)
|
61
|
-
|
62
|
-
Sequel[:tags][:
|
63
|
-
Sequel[:
|
58
|
+
self_join = {
|
59
|
+
Sequel[:tags][:pacticipant_id] => Sequel[:tags_2][:pacticipant_id],
|
60
|
+
Sequel[:tags][:name] => Sequel[:tags_2][:name],
|
61
|
+
Sequel[:tags_2][:pacticipant_id] => pacticipant_ids,
|
64
62
|
}
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
64
|
+
Tag
|
65
|
+
.select_all_qualified
|
66
|
+
.left_join(:tags, self_join, { table_alias: :tags_2 }) do
|
67
|
+
Sequel[:tags_2][:version_order] > Sequel[:tags][:version_order]
|
68
|
+
end
|
69
|
+
.where(Sequel[:tags_2][:name] => nil)
|
70
|
+
.where(Sequel[:tags][:pacticipant_id] => pacticipant_ids)
|
71
|
+
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
def latest_tags_for_pacticipant_ids_and_tag_names(pacticipant_ids, tag_names)
|
74
|
+
self_join = {
|
75
|
+
Sequel[:tags][:pacticipant_id] => Sequel[:tags_2][:pacticipant_id],
|
76
|
+
Sequel[:tags][:name] => Sequel[:tags_2][:name],
|
77
|
+
Sequel[:tags_2][:pacticipant_id] => pacticipant_ids,
|
78
|
+
Sequel[:tags_2][:name] => tag_names
|
79
|
+
}
|
77
80
|
|
78
|
-
|
81
|
+
Tag
|
79
82
|
.select_all_qualified
|
80
|
-
.
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
.
|
83
|
+
.left_join(:tags, self_join, { table_alias: :tags_2 }) do
|
84
|
+
Sequel[:tags_2][:version_order] > Sequel[:tags][:version_order]
|
85
|
+
end
|
86
|
+
.where(Sequel[:tags_2][:name] => nil)
|
87
|
+
.where(Sequel[:tags][:pacticipant_id] => pacticipant_ids)
|
88
|
+
.where(Sequel[:tags][:name] => tag_names)
|
85
89
|
end
|
86
90
|
|
91
|
+
# ignores tags that don't have a pact publication
|
87
92
|
def head_tags_for_consumer_id(consumer_id)
|
88
93
|
lp = :latest_pact_publication_ids_for_consumer_versions
|
89
94
|
tags_versions_join = {
|
@@ -98,7 +103,7 @@ module PactBroker
|
|
98
103
|
# head tags for this consumer
|
99
104
|
# the latest tag, pacticipant_id, version order
|
100
105
|
# for versions that have a pact publication
|
101
|
-
|
106
|
+
Tag
|
102
107
|
.select_group(Sequel[:tags][:name], Sequel[:versions][:pacticipant_id])
|
103
108
|
.select_append{ max(order).as(latest_consumer_version_order) }
|
104
109
|
.join(:versions, tags_versions_join)
|
@@ -106,25 +111,74 @@ module PactBroker
|
|
106
111
|
end
|
107
112
|
|
108
113
|
def head_tags_for_pact_publication(pact_publication)
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
+
Tag.where(version_id: pact_publication.consumer_version_id).all.select do | tag |
|
115
|
+
tag_pp_join = {
|
116
|
+
Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id],
|
117
|
+
Sequel[:pact_publications][:consumer_id] => pact_publication.consumer_id,
|
118
|
+
Sequel[:pact_publications][:provider_id] => pact_publication.provider_id,
|
119
|
+
Sequel[:tags][:name] => tag.name
|
120
|
+
}
|
121
|
+
Tag.join(:pact_publications, tag_pp_join) do
|
122
|
+
Sequel[:tags][:version_order] > tag.version_order
|
123
|
+
end
|
124
|
+
.where(pacticipant_id: pact_publication.consumer_id)
|
125
|
+
.limit(1)
|
126
|
+
.empty?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
114
130
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
131
|
+
def before_save
|
132
|
+
if version
|
133
|
+
if version.order && self.version_order.nil?
|
134
|
+
self.version_order = version.order
|
135
|
+
end
|
136
|
+
|
137
|
+
if self.pacticipant_id.nil?
|
138
|
+
if version.pacticipant_id
|
139
|
+
self.pacticipant_id = version.pacticipant_id
|
140
|
+
elsif version&.pacticipant&.id
|
141
|
+
self.pacticipant_id = version.pacticipant.id
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
if version_order.nil? || pacticipant_id.nil?
|
147
|
+
raise PactBroker::Error.new("Need to set version_order and pacticipant_id for tags now")
|
148
|
+
else
|
149
|
+
super
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def latest_for_pacticipant?
|
154
|
+
head_tag == self
|
155
|
+
end
|
156
|
+
|
157
|
+
alias_method :latest?, :latest_for_pacticipant?
|
158
|
+
|
159
|
+
def latest_for_pact_publication?(pact_publication)
|
160
|
+
tag_pp_join = {
|
161
|
+
Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id],
|
162
|
+
Sequel[:pact_publications][:consumer_id] => pact_publication.consumer_id,
|
163
|
+
Sequel[:pact_publications][:provider_id] => pact_publication.provider_id,
|
164
|
+
Sequel[:tags][:name] => name
|
165
|
+
}
|
166
|
+
own_version_order = self.version_order
|
167
|
+
Tag.join(:pact_publications, tag_pp_join) do
|
168
|
+
Sequel[:tags][:version_order] > own_version_order
|
122
169
|
end
|
170
|
+
.where(pacticipant_id: pact_publication.consumer_id)
|
171
|
+
.limit(1)
|
172
|
+
.empty?
|
123
173
|
end
|
124
174
|
|
125
175
|
def <=> other
|
126
176
|
name <=> other.name
|
127
177
|
end
|
178
|
+
|
179
|
+
def pacticipant
|
180
|
+
version.pacticipant
|
181
|
+
end
|
128
182
|
end
|
129
183
|
end
|
130
184
|
end
|
@@ -132,12 +186,18 @@ end
|
|
132
186
|
# Table: tags
|
133
187
|
# Primary Key: (name, version_id)
|
134
188
|
# Columns:
|
135
|
-
# name
|
136
|
-
# version_id
|
137
|
-
# created_at
|
138
|
-
# updated_at
|
189
|
+
# name | text |
|
190
|
+
# version_id | integer |
|
191
|
+
# created_at | timestamp without time zone | NOT NULL
|
192
|
+
# updated_at | timestamp without time zone | NOT NULL
|
193
|
+
# pacticipant_id | integer |
|
194
|
+
# version_order | integer |
|
139
195
|
# Indexes:
|
140
|
-
# tags_pk
|
141
|
-
# ndx_tag_name
|
196
|
+
# tags_pk | PRIMARY KEY btree (version_id, name)
|
197
|
+
# ndx_tag_name | btree (name)
|
198
|
+
# tags_pacticipant_id_index | btree (pacticipant_id)
|
199
|
+
# tags_pacticipant_id_name_version_order_desc_index | btree (pacticipant_id, name, version_order DESC)
|
200
|
+
# tags_version_id_index | btree (version_id)
|
201
|
+
# tags_version_order_index | btree (version_order)
|
142
202
|
# Foreign key constraints:
|
143
203
|
# tags_version_id_fkey | (version_id) REFERENCES versions(id)
|