Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: currently supported selector #451

Merged
merged 19 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b0fdc88
wip
bethesque May 30, 2021
157c998
Merge branch 'master' into feat/currently-supported-selector
bethesque Jun 11, 2021
728d52b
Merge branch 'master' into feat/currently-supported-selector
bethesque Jul 1, 2021
2472de4
feat: add support for selecting currently released and supported pact…
bethesque Jul 1, 2021
6948a53
feat: support specifying an environment in a consumer version selecto…
bethesque Jul 1, 2021
3221e5d
chore: add warning when pact selector invalid keys used
bethesque Jul 1, 2021
62e7309
chore: rename currentlyDeployed:true selector to deployed:true, and c…
bethesque Jul 1, 2021
8018765
refactor: rename pact selector environment to environment name, and a…
bethesque Jul 1, 2021
84d2c47
chore: update verifiable pact description for pacts for currently sup…
bethesque Jul 1, 2021
5a41c46
feat: show released versions in matrix
bethesque Jul 1, 2021
37bc1aa
feat: show environments on index page with tags
bethesque Jul 1, 2021
8c55b96
feat: update colours and add text to badges on index and matrix
bethesque Jul 1, 2021
6275608
chore: drop unused columns from deployed_versions
bethesque Jul 1, 2021
2831554
feat: add environment query box to matrix UI
bethesque Jul 1, 2021
db83170
chore: update paths and relations for currently deployed version and …
bethesque Jul 1, 2021
01df081
style: rubocop
bethesque Jul 2, 2021
9ac49b5
chore: sort selected pacts deterministically
bethesque Jul 2, 2021
6d73b1a
test: why is this test even running
bethesque Jul 2, 2021
e60e254
Merge branch 'master' into feat/currently-supported-selector
bethesque Jul 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Sequel.migration do
up do
alter_table(:deployed_versions) do
drop_column(:replaced_previous_deployed_version)
drop_column(:currently_deployed)
end
end

down do
alter_table(:deployed_versions) do
add_column(:replaced_previous_deployed_version, TrueClass)
add_column(:currently_deployed, TrueClass)
end
end
end
4 changes: 2 additions & 2 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_
if PactBroker.feature_enabled?(:environments)
add ["environments"], Api::Resources::Environments, { resource_name: "environments" }
add ["environments", :environment_uuid], Api::Resources::Environment, { resource_name: "environment" }
add ["environments", :environment_uuid, "currently-deployed-versions"], Api::Resources::CurrentlyDeployedVersionsForEnvironment, { resource_name: "environment_deployed_versions" }
add ["environments", :environment_uuid, "currently-supported-versions"], Api::Resources::CurrentlySupportedVersionsForEnvironment, { resource_name: "environment_supported_versions" }
add ["environments", :environment_uuid, "deployed-versions", "currently-deployed"], Api::Resources::CurrentlyDeployedVersionsForEnvironment, { resource_name: "environment_currently_deployed_deployed_versions" }
add ["environments", :environment_uuid, "released-versions", "currently-supported"], Api::Resources::CurrentlySupportedVersionsForEnvironment, { resource_name: "environment_currently_supported_released_versions" }
add ["pacticipants", :pacticipant_name, "versions", :pacticipant_version_number, "deployed-versions", "environment", :environment_uuid], Api::Resources::DeployedVersionsForVersionAndEnvironment, { resource_name: "deployed_versions_for_version_and_environment" }
add ["pacticipants", :pacticipant_name, "versions", :pacticipant_version_number, "released-versions", "environment", :environment_uuid], Api::Resources::ReleasedVersionsForVersionAndEnvironment, { resource_name: "released_versions_for_version_and_environment" }
add ["released-versions", :uuid], Api::Resources::ReleasedVersion, { resource_name: "released_version" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class VerifiablePactsJSONQuerySchema
optional(:fallbackTag).filled(:str?)
optional(:fallbackBranch).filled(:str?)
optional(:consumer).filled(:str?, :not_blank?)
optional(:currentlyDeployed).filled(included_in?: [true])
optional(:deployed).filled(included_in?: [true])
optional(:released).filled(included_in?: [true])
optional(:environment).filled(:str?)

# rule(fallbackTagMustBeForLatest: [:fallbackTag, :latest]) do | fallback_tag, latest |
Expand Down Expand Up @@ -89,9 +90,10 @@ def self.validate_consumer_version_selector(selector, index)
if not_provided?(selector[:tag]) &&
not_provided?(selector[:branch]) &&
not_provided?(selector[:environment]) &&
selector[:currentlyDeployed] != true &&
selector[:deployed] != true &&
selector[:released] != true &&
selector[:latest] != true
errors << "must specify a value for environment or tag, or specify latest=true, or specify currentlyDeployed=true (at index #{index})"
errors << "must specify a value for environment or tag, or specify latest=true, or specify deployed=true or released=true (at index #{index})"
end

if selector[:tag] && selector[:branch]
Expand All @@ -110,8 +112,12 @@ def self.validate_consumer_version_selector(selector, index)
errors << "cannot specify a branch with latest=false (at index #{index})"
end

if selector[:deployed] && selector[:released]
errors << "cannot specify both deployed=true and released=true (at index #{index})"
end

non_environment_fields = selector.slice(:latest, :tag, :fallbackTag, :branch, :fallbackBranch).keys.sort
environment_related_fields = selector.slice(:environment, :currentlyDeployed).keys.sort
environment_related_fields = selector.slice(:environment, :deployed, :released).keys.sort

if (non_environment_fields.any? && environment_related_fields.any?)
errors << "cannot specify the #{pluralize("field", non_environment_fields.count)} #{non_environment_fields.join("/")} with the #{pluralize("field", environment_related_fields.count)} #{environment_related_fields.join("/")} (at index #{index})"
Expand Down
6 changes: 3 additions & 3 deletions lib/pact_broker/api/decorators/environment_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ class EnvironmentDecorator < BaseDecorator
}
end

link :'pb:currently-deployed-versions' do | user_options |
link :'pb:currently-deployed-deployed-versions' do | user_options |
{
title: "Versions currently deployed to #{represented.display_name} environment",
href: currently_deployed_versions_for_environment_url(represented, user_options.fetch(:base_url))
}
end

link :'pb:currently-supported-versions' do | user_options |
link :'pb:currently-supported-released-versions' do | user_options |
{
title: "Versions currently supported in #{represented.display_name} environment",
title: "Versions released and supported in #{represented.display_name} environment",
href: currently_supported_versions_for_environment_url(represented, user_options.fetch(:base_url))
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ class VerifiablePactsQueryDecorator < BaseDecorator
property :fallback_tag
property :fallback_branch
property :consumer
property :environment, setter: -> (fragment:, represented:, **) {
represented.environment = fragment
represented.currently_deployed = true
}
property :currently_deployed
property :environment_name, as: :environment
property :currently_deployed, as: :deployed
property :currently_supported, as: :released
end

property :include_pending_status, default: false,
Expand Down
4 changes: 2 additions & 2 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,11 +319,11 @@ def deployed_versions_for_version_and_environment_url(version, environment, base
end

def currently_deployed_versions_for_environment_url(environment, base_url = "")
"#{base_url}/environments/#{environment.uuid}/currently-deployed-versions"
"#{base_url}/environments/#{environment.uuid}/deployed-versions/currently-deployed"
end

def currently_supported_versions_for_environment_url(environment, base_url = "")
"#{base_url}/environments/#{environment.uuid}/currently-supported-versions"
"#{base_url}/environments/#{environment.uuid}/released-versions/currently-supported"
end

def record_undeployment_url(deployed_version, base_url = "")
Expand Down
4 changes: 1 addition & 3 deletions lib/pact_broker/deployments/deployed_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

module PactBroker
module Deployments
DEPLOYED_VERSION_COLUMNS = [:id, :uuid, :version_id, :pacticipant_id, :environment_id, :target, :target_for_index, :created_at, :updated_at, :undeployed_at]
DEPLOYED_VERSION_DATASET = Sequel::Model.db[:deployed_versions].select(*DEPLOYED_VERSION_COLUMNS)
class DeployedVersion < Sequel::Model(DEPLOYED_VERSION_DATASET)
class DeployedVersion < Sequel::Model
many_to_one :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id
many_to_one :environment, :class => "PactBroker::Deployments::Environment", :key => :environment_id, :primary_key => :id
one_to_one :currently_deployed_version_id, :class => "PactBroker::Deployments::CurrentlyDeployedVersionId", key: :deployed_version_id, primary_key: :id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ Returns a deduplicated list of pacts to be verified by the specified provider.

### Body

Example: This data structure represents the way a user might specify "I want to verify the latest 'main' pact, all the pacts for the consumer versionst that are currently deployed, and when I publish the verification results, the provider version will be be on the "main" branch.
Example: This data structure represents the way a user might specify "I want to verify the latest 'main' pact, all the pacts for the consumer versions that are currently deployed, and when I publish the verification results, the provider version will be be on the "main" branch.

{
"consumerVersionSelectors": [
{
"branch": "main"
},
{
"currentlyDeployed": true
"deployed": true
}
],
"providerVersionBranch": "main",
Expand All @@ -30,9 +30,11 @@ Example: This data structure represents the way a user might specify "I want to

`consumerVersionSelectors.fallbackBranch`: the name of the branch to fallback to if the specified `branch` does not exist. This is useful when the consumer and provider use matching branch names to coordinate the development of new features.

`consumerVersionSelectors.currentlyDeployed`: if the key is specified, can only be set to `true`. Returns the pacts for all versions of the consumer that are currently deployed to any environment. Use of this selector requires that the deployment of the consumer application is recorded in the Pact Broker using the `pact-broker record-deployment` CLI.
`consumerVersionSelectors.deployed`: if the key is specified, can only be set to `true`. Returns the pacts for all versions of the consumer that are currently deployed to any environment. Use of this selector requires that the deployment of the consumer application is recorded in the Pact Broker using the `pact-broker record-deployment` CLI.

`consumerVersionSelectors.environment`: the name of the environment containing the consumer versions for which to return the pacts. Used to further qualify `{ "currentlyDeployed": true }`. Normally, this would not be needed, as it is recommended to verify the pacts for all currently deployed versions. If the `environment` is set, `currentlyDeployed` must be set to `true`, or the key ommitted (in which case it will be inferred to be `true`).
`consumerVersionSelectors.released`: if the key is specified, can only be set to `true`. Returns the pacts for all versions of the consumer that are released and currently supported in any environment. Use of this selector requires that the deployment of the consumer application is recorded in the Pact Broker using the `pact-broker record-release` CLI.

`consumerVersionSelectors.environment`: the name of the environment containing the consumer versions for which to return the pacts. Used to further qualify `{ "deployed": true }` or `{ "released": true }`. Normally, this would not be needed, as it is recommended to verify the pacts for all currently deployed/currently supported released versions.

`consumerVersionSelectors.latest`: true. Used in conjuction with the `tag` and `branch` properties. When used with a `branch`, it may be `true` or the key ommitted (in which case it will be inferred to be `true`). This is because it only makes sense to verify the latest pact for a branch. If a `tag` is specified, and `latest` is `true`, then the latest pact for each of the consumers with that tag will be returned. If a `tag` is specified and the latest flag is *not* set to `true`, *all* the pacts with the specified tag will be returned. (This might seem a bit weird, but it's done this way to match the syntax used for the matrix query params. See https://docs.pact.io/selectors).

Expand Down
19 changes: 17 additions & 2 deletions lib/pact_broker/domain/index_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def consumer_version_branch
end

def consumer_version_environment_names
consumer_version.current_deployed_versions.collect(&:environment).collect(&:name)
(consumer_version.current_deployed_versions.collect(&:environment).collect(&:name) + consumer_version.current_supported_released_versions.collect(&:environment).collect(&:name)).uniq
end

def latest_for_branch?
Expand All @@ -97,7 +97,12 @@ def provider_version_branch
end

def provider_version_environment_names
provider_version&.current_deployed_versions&.collect(&:environment)&.collect(&:name) || []
if provider_version
(provider_deployed_environment_names + provider_released_environment_names).uniq
else
[]
end

end

# these are the consumer tag names for which this pact publication
Expand Down Expand Up @@ -187,6 +192,16 @@ def to_a
def last_activity_date
@last_activity_date ||= [latest_pact.created_at, latest_verification ? latest_verification.execution_date : nil].compact.max
end

private

def provider_deployed_environment_names
provider_version.current_deployed_versions.collect(&:environment)&.collect(&:name)
end

def provider_released_environment_names
provider_version.current_supported_released_versions.collect(&:environment)&.collect(&:name)
end
end
end
end
6 changes: 6 additions & 0 deletions lib/pact_broker/domain/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ def pending?
!pact_version.verified_successfully_by_any_provider_version?
end

def <=> other
self_fields = [consumer_name.downcase, provider_name.downcase, consumer_version.order || 0]
other_fields = [other.consumer_name.downcase, other.provider_name.downcase, other.consumer_version.order || 0]
self_fields <=> other_fields
end

private

attr_accessor :db_model
Expand Down
15 changes: 14 additions & 1 deletion lib/pact_broker/domain/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class Version < Sequel::Model
one_to_many :current_deployed_versions, class: "PactBroker::Deployments::DeployedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id] do | ds |
ds.currently_deployed
end
one_to_many :current_supported_released_versions, class: "PactBroker::Deployments::ReleasedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id] do | ds |
ds.currently_supported
end

one_to_many :deployed_versions, class: "PactBroker::Deployments::DeployedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id]

Expand Down Expand Up @@ -88,12 +91,22 @@ def where_pacticipant_name(pacticipant_name)
# end
end

def currently_in_environment(environment_name, pacticipant_name)
currently_deployed_to_environment(environment_name, pacticipant_name).union(currently_supported_in_environment(environment_name, pacticipant_name))
end

def currently_deployed_to_environment(environment_name, pacticipant_name)
deployed_version_query = PactBroker::Deployments::DeployedVersion.currently_deployed.for_environment_name(environment_name)
deployed_version_query = deployed_version_query.for_pacticipant_name(pacticipant_name) if pacticipant_name
where(id: deployed_version_query.select(:version_id))
end

def currently_supported_in_environment(environment_name, pacticipant_name)
supported_version_query = PactBroker::Deployments::ReleasedVersion.currently_supported.for_environment_name(environment_name)
supported_version_query = supported_version_query.for_pacticipant_name(pacticipant_name) if pacticipant_name
where(id: supported_version_query.select(:version_id))
end

def where_tag(tag)
if tag == true
join(:tags, Sequel[:tags][:version_id] => Sequel[first_source_alias][:id])
Expand Down Expand Up @@ -139,7 +152,7 @@ def delete
def for_selector(selector)
query = self
query = query.where_pacticipant_name(selector.pacticipant_name) if selector.pacticipant_name
query = query.currently_deployed_to_environment(selector.environment_name, selector.pacticipant_name) if selector.environment_name
query = query.currently_in_environment(selector.environment_name, selector.pacticipant_name) if selector.environment_name
query = query.where_tag(selector.tag) if selector.tag
query = query.where_branch(selector.branch) if selector.branch
query = query.where_number(selector.pacticipant_version_number) if selector.pacticipant_version_number
Expand Down
10 changes: 5 additions & 5 deletions lib/pact_broker/index/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def self.find_index_items options = {}
.eager(:provider)
.eager(:pact_version)
.eager(integration: [{latest_verification: :provider_version}, :latest_triggered_webhooks])
.eager(consumer_version: [{ current_deployed_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }])
.eager(latest_verification: { provider_version: [{ current_deployed_versions: :environment }, :latest_version_for_branch, { tags: :head_tag } ] })
.eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }])
.eager(latest_verification: { provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :latest_version_for_branch, { tags: :head_tag } ] })
.eager(:head_pact_publications_for_tags)

index_items = pact_publications.all.collect do | pact_publication |
Expand Down Expand Up @@ -108,8 +108,8 @@ def self.find_index_items_for_api(consumer_name: nil, provider_name: nil, **_ign
.eager(:consumer)
.eager(:provider)
.eager(:pact_version)
.eager(consumer_version: [{ current_deployed_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }])
.eager(latest_verification: { provider_version: [{ current_deployed_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }]})
.eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }])
.eager(latest_verification: { provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :latest_version_for_branch, { tags: :head_tag }]})
.eager(:head_pact_publications_for_tags)

pact_publications.all.collect do | pact_publication |
Expand Down Expand Up @@ -188,7 +188,7 @@ def self.latest_verifications_for_consumer_version_tags(options)
.all
elsif options[:tags] # server side rendered index page with tags=true
PactBroker::Verifications::LatestVerificationForConsumerVersionTag
.eager(provider_version: { current_deployed_versions: :environment })
.eager(provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }])
.all
else
nil # should not be used
Expand Down
1 change: 1 addition & 0 deletions lib/pact_broker/matrix/parse_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def self.parse_selector(i)
p.latest = true if i["latest"] == "true"
p.branch = i["branch"] if i["branch"] && i["branch"] != ""
p.tag = i["tag"] if i["tag"] && i["tag"] != ""
p.environment_name = i["environment"] if i["environment"] && i["environment"] != ""
p
end
# rubocop: enable Metrics/CyclomaticComplexity
Expand Down
3 changes: 2 additions & 1 deletion lib/pact_broker/pacts/pact_publication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ def to_version_domain_lightweight
pacticipant: consumer,
order: consumer_version.order,
branch: consumer_version.branch,
current_deployed_versions: consumer_version.associations[:current_deployed_versions]
current_deployed_versions: consumer_version.associations[:current_deployed_versions],
current_supported_released_versions: consumer_version.associations[:current_supported_released_versions],
)
end

Expand Down
Loading