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: support deployments and releases #426

Merged
merged 16 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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,13 @@
Sequel.migration do
change do
create_table(:currently_deployed_version_ids, charset: 'utf8') do
primary_key :id
String :target_for_index, null: false
foreign_key :pacticipant_id, :pacticipants, null: false, on_delete: :cascade
foreign_key :environment_id, :environments, null: false, on_delete: :cascade
foreign_key :version_id, :versions, null: false, on_delete: :cascade
foreign_key :deployed_version_id, null: false, on_delete: :cascade
index [:pacticipant_id, :environment_id, :target_for_index], unique: true, name: "currently_deployed_version_pacticipant_environment_target_index"
end
end
end
21 changes: 21 additions & 0 deletions db/migrations/20210415_add_target_column_to_deployed_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Sequel.migration do
up do
alter_table(:deployed_versions) do
add_column(:target, String)
add_column(:target_for_index, String, default: "", null: false)
set_column_allow_null(:replaced_previous_deployed_version)
set_column_allow_null(:currently_deployed)
drop_index [:pacticipant_id, :currently_deployed], name: "deployed_versions_pacticipant_id_currently_deployed_index"
end
end

down do
alter_table(:deployed_versions) do
drop_column(:target)
drop_column(:target_for_index)
set_column_not_null(:replaced_previous_deployed_version)
set_column_not_null(:currently_deployed)
add_index [:pacticipant_id, :currently_deployed], name: "deployed_versions_pacticipant_id_currently_deployed_index"
end
end
end
17 changes: 17 additions & 0 deletions db/migrations/20210419_create_released_versions_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Sequel.migration do
change do
create_table(:released_versions, charset: 'utf8') do
primary_key :id
String :uuid, null: false
foreign_key :version_id, :versions, null: false
Integer :pacticipant_id, null: false
foreign_key :environment_id, :environments, null: false
DateTime :created_at
DateTime :updated_at
DateTime :support_ended_at
index [:uuid], unique: true, name: "released_versions_uuid_index"
index [:version_id, :environment_id], unique: true, name: "released_versions_version_id_environment_id_index"
index [:support_ended_at], name: "released_version_support_ended_at_index"
end
end
end
2 changes: 2 additions & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_
add ['environments'], Api::Resources::Environments, { resource_name: "environments" }
add ['environments', :environment_uuid], Api::Resources::Environment, { resource_name: "environment" }
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" }
end

add ['integrations'], Api::Resources::Integrations, {resource_name: "integrations"}
Expand Down
3 changes: 2 additions & 1 deletion lib/pact_broker/api/decorators/deployed_version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ module PactBroker
module Api
module Decorators
class DeployedVersionDecorator < BaseDecorator
property :uuid
property :version, :extend => EmbeddedVersionDecorator, writeable: false, embedded: true
property :environment, :extend => EnvironmentDecorator, writeable: false, embedded: true
property :currently_deployed, camelize: true
property :replaced_previous_deployed_version, camelize: true
property :target, camelize: true
include Timestamps
property :undeployedAt, getter: lambda { |_| undeployed_at ? FormatDateTime.call(undeployed_at) : nil }, writeable: false
end
Expand Down
14 changes: 14 additions & 0 deletions lib/pact_broker/api/decorators/released_version_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'pact_broker/api/decorators/base_decorator'

module PactBroker
module Api
module Decorators
class ReleasedVersionDecorator < BaseDecorator
property :uuid
property :currently_supported, camelize: true

include Timestamps
end
end
end
end
10 changes: 10 additions & 0 deletions lib/pact_broker/api/decorators/version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ class VersionDecorator < BaseDecorator
end
end

links :'pb:record-release' do | context |
context.fetch(:environments, []).collect do | environment |
{
title: "Record release to #{environment.display_name}",
name: environment.name,
href: released_versions_for_version_and_environment_url(represented, environment, context.fetch(:base_url))
}
end
end

curies do | options |
[{
name: :pb,
Expand Down
8 changes: 8 additions & 0 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,18 @@ def deployed_versions_for_version_and_environment_url(version, environment, base
"#{version_url(base_url, version)}/deployed-versions/environment/#{environment.uuid}"
end

def released_versions_for_version_and_environment_url(version, environment, base_url = '')
"#{version_url(base_url, version)}/released-versions/environment/#{environment.uuid}"
end

def deployed_version_url(deployed_version, base_url = '')
"/deployed-versions/#{deployed_version.uuid}"
end

def released_version_url(released_version, base_url = '')
"/released-versions/#{released_version.uuid}"
end

def hal_browser_url target_url, base_url = ''
"#{base_url}/hal-browser/browser.html#" + target_url
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ module PactBroker
module Api
module Resources
class DeployedVersionsForVersionAndEnvironment < BaseResource
def initialize
super
@existing_deployed_version = version && environment && deployed_version_service.find_currently_deployed_version_for_version_and_environment_and_target(version, environment, target)
end

def content_types_accepted
[["application/json", :from_json]]
end
Expand All @@ -25,20 +30,12 @@ def post_is_create?
true
end

def malformed_request?
if request.post?
malformed_post_request?
else
false
end
end

def create_path
deployed_version_url(OpenStruct.new(uuid: deployed_version_uuid), base_url)
deployed_version_url(existing_deployed_version || OpenStruct.new(uuid: deployed_version_uuid), base_url)
end

def from_json
@deployed_version = deployed_version_service.create(deployed_version_uuid, version, environment, replaced_previous_deployed_version)
@deployed_version = existing_deployed_version || deployed_version_service.create(deployed_version_uuid, version, environment, target)
response.body = decorator_class(:deployed_version_decorator).new(deployed_version).to_json(decorator_options)
end

Expand All @@ -52,7 +49,7 @@ def policy_name

private

attr_reader :deployed_version
attr_reader :deployed_version, :existing_deployed_version

def version
@version ||= version_service.find_by_pacticipant_name_and_number(identifier_from_path)
Expand All @@ -74,22 +71,14 @@ def deployed_version_uuid
@deployed_version_uuid ||= deployed_version_service.next_uuid
end

def replaced_previous_deployed_version
params(default: {})[:replacedPreviousDeployedVersion]
# TODO disallow an empty string because that is used as a NULL indicator in the database
def target
params(default: {})[:target]&.to_s
end

def title
"Deployed versions for #{pacticipant_name} version #{pacticipant_version_number}"
end

def malformed_post_request?
if ![true, false].include?(replaced_previous_deployed_version)
set_json_validation_error_messages({ replacedPreviousDeployedVersion: ["must be one of true, false"] })
true
else
false
end
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/api/resources/environments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def from_json
end

def policy_name
:'deployments::environment'
:'deployments::environments'
end

def to_json
Expand Down
52 changes: 52 additions & 0 deletions lib/pact_broker/api/resources/released_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'pact_broker/api/resources/base_resource'
require 'pact_broker/api/decorators/released_version_decorator'

module PactBroker
module Api
module Resources
class ReleasedVersion < BaseResource
def content_types_provided
[["application/hal+json", :to_json]]
end

def allowed_methods
["GET", "OPTIONS"]
end

def resource_exists?
!!released_version
end

def to_json
decorator_class(:released_version_decorator).new(released_version).to_json(decorator_options)
end

def policy_name
:'versions::versions'
end

# For PF
def policy_record_context
# Not sure whether the context should be empty or the pacticipant should be nil
if released_version
{ pacticipant: released_version.pacticipant }
else
{}
end
end

private

attr_reader :released_version

def released_version
@released_version ||= released_version_service.find_by_uuid(uuid)
end

def uuid
identifier_from_path[:uuid]
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
require 'pact_broker/api/resources/base_resource'
require 'pact_broker/api/decorators/versions_decorator'

module PactBroker
module Api
module Resources
class ReleasedVersionsForVersionAndEnvironment < BaseResource
def initialize
super
@existing_released_version = version && environment && released_version_service.find_released_version_for_version_and_environment(version, environment)
end

def content_types_accepted
[["application/json", :from_json]]
end

def content_types_provided
[["application/hal+json", :to_json]]
end

def allowed_methods
["GET", "POST", "OPTIONS"]
end

def resource_exists?
!!version && !!environment
end

def post_is_create?
true
end

def create_path
released_version_url(existing_released_version || OpenStruct.new(uuid: next_released_version_uuid), base_url)
end

def from_json
@released_version = existing_released_version || released_version_service.create(next_released_version_uuid, version, environment)
response.body = decorator_class(:released_version_decorator).new(released_version).to_json(decorator_options)
true
end

def to_json
decorator_class(:released_versions_decorator).new(released_versions).to_json(decorator_options(title: title))
end

def policy_name
:'versions::versions'
end

def finish_request
if request.post? && existing_released_version
response.code = 200
end
super
end

private

attr_reader :released_version, :existing_released_version

def version
@version ||= version_service.find_by_pacticipant_name_and_number(identifier_from_path)
end

def environment
@environment ||= environment_service.find(environment_uuid)
end

def released_versions
@released_versions ||= begin
if existing_released_version
[existing_released_version]
else
[]
end
end
end

def environment_uuid
identifier_from_path[:environment_uuid]
end

def next_released_version_uuid
@released_version_uuid ||= released_version_service.next_uuid
end

def title
"Released versions for #{pacticipant.display_name} version #{pacticipant_version_number} in #{environment.display_name}"
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/pact_broker/deployments/currently_deployed_version_id.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'sequel'
require 'pact_broker/repositories/helpers'

module PactBroker
module Deployments
class CurrentlyDeployedVersionId < Sequel::Model
plugin :upsert, identifying_columns: [:pacticipant_id, :environment_id, :target_for_index]

dataset_module do
include PactBroker::Repositories::Helpers
end
end
end
end
Loading