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 creating version with branch #371

Merged
merged 30 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
616a9e3
wip: allow patch to version resource
bethesque May 12, 2020
10a2fbd
feat: support PUT for creating version with branch and buildUrl
bethesque Jan 17, 2021
f193e83
chore: correct the fields that are updated when using upsert
bethesque Jan 17, 2021
f28035c
chore: add versions_pacticipant_id_branch_order_index
bethesque Jan 17, 2021
5af0af1
test: manually set created_at and updated_at for upsert test
bethesque Jan 18, 2021
51825bb
test: upsert spec
bethesque Jan 18, 2021
4df553d
Merge branch 'master' into feat/support-creating-version-with-branch
bethesque Jan 29, 2021
9144cd3
feat: support WIP pacts for provider branch
bethesque Jan 30, 2021
55926f9
refactor: clean up original wip pacts code
bethesque Jan 31, 2021
2aaef4e
refactor: verifiable pact class
bethesque Jan 31, 2021
99a9cc2
chore: set correct selectors
bethesque Jan 31, 2021
32735e6
chore: implement sort for Selector with branch
bethesque Jan 31, 2021
1ed69e9
feat: support provider branch in the response text for the 'pacts for…
bethesque Jan 31, 2021
f8804e4
feat: include wip pacts by consumer branch
bethesque Feb 1, 2021
0de5948
Merge branch 'master' into feat/support-creating-version-with-branch
bethesque Feb 2, 2021
3c3ad86
chore: update wip pacts message for latest from branch
bethesque Feb 2, 2021
6f1039e
refactor: add method to PactPublication to find by consumer version s…
bethesque Feb 2, 2021
3ec4eab
refactor: use PactPublication find for selector method to find pacts …
bethesque Feb 2, 2021
15d57a0
chore: support branches in http test data builder
bethesque Feb 2, 2021
a4a10ab
tests: remove unncessary tests
bethesque Feb 2, 2021
a90dc86
refactor: make code climate happier
bethesque Feb 2, 2021
047457e
refactor: separate 'pacts for verification' code into separate class
bethesque Feb 2, 2021
a54aaa0
test: add tests missed in previous commit
bethesque Feb 2, 2021
dc1e31c
style: whitespace [ci-skip]
bethesque Feb 2, 2021
1e70030
chore: remove unused method [ci-skip]
bethesque Feb 2, 2021
0746e72
feat: add pb:pacticipant-version relation to index
bethesque Feb 2, 2021
c04e3a1
chore: update feature toggle experimental_no_provider_versions_makes_…
bethesque Feb 2, 2021
ebc1cfc
chore: update http test data builder [ci-skip]
bethesque Feb 2, 2021
00f845a
chore: add script to demonstrate pacticipant branches [ci-skip]
bethesque Feb 2, 2021
a7e4547
chore: update GA test workflow
bethesque Feb 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
19 changes: 19 additions & 0 deletions .github/workflows/test-ruby-3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Tests for Ruby 3.0 - these are hardcoded to succeed so every commit doesn't look like it's failing

on: [push, pull_request]

jobs:
sqlite:
if: "!contains(github.event.head_commit.message, '[ci-skip]')"
runs-on: "ubuntu-latest"
strategy:
fail-fast: false
matrix:
ruby_version: ["3.0"]
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby_version }}
- run: "bundle install"
- run: "bundle exec rake || true"
7 changes: 1 addition & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
name: Test

on: push
on: [push, pull_request]

jobs:
sqlite:
if: "!contains(github.event.head_commit.message, '[ci-skip]')"
runs-on: "ubuntu-latest"
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
ruby_version: ["2.7"]
experimental: [false]
include:
- ruby_version: "3.0"
experimental: true
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
Expand Down
9 changes: 9 additions & 0 deletions db/migrations/20210117_add_branch_to_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Sequel.migration do
change do
alter_table(:versions) do
add_column(:branch, String)
add_column(:build_url, String)
add_index([:pacticipant_id, :branch, :order], name: "versions_pacticipant_id_branch_order_index")
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 @@ -71,10 +71,10 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_
add ['pacticipants', :pacticipant_name], Api::Resources::Pacticipant, {resource_name: "pacticipant"}
add ['pacticipants', :pacticipant_name, 'versions'], Api::Resources::Versions, {resource_name: "pacticipant_versions"}
add ['pacticipants', :pacticipant_name, 'versions', :pacticipant_version_number], Api::Resources::Version, {resource_name: "pacticipant_version"}
add ['pacticipants', :pacticipant_name, 'latest-version', :tag], Api::Resources::Version, {resource_name: "latest_tagged_pacticipant_version"}
add ['pacticipants', :pacticipant_name, 'latest-version', :tag], Api::Resources::LatestVersion, {resource_name: "latest_tagged_pacticipant_version"}
add ['pacticipants', :pacticipant_name, 'latest-version', :tag, 'can-i-deploy', 'to', :to], Api::Resources::CanIDeployPacticipantVersion, { resource_name: "can_i_deploy_latest_tagged_version" }
add ['pacticipants', :pacticipant_name, 'latest-version', :tag, 'can-i-deploy', 'to', :to, 'badge'], Api::Resources::CanIDeployBadge, { resource_name: "can_i_deploy_badge" }
add ['pacticipants', :pacticipant_name, 'latest-version'], Api::Resources::Version, {resource_name: "latest_pacticipant_version"}
add ['pacticipants', :pacticipant_name, 'latest-version'], Api::Resources::LatestVersion, {resource_name: "latest_pacticipant_version"}
add ['pacticipants', :pacticipant_name, 'versions', :pacticipant_version_number, 'tags', :tag_name], Api::Resources::Tag, {resource_name: "pacticipant_version_tag"}
add ['pacticipants', :pacticipant_name, 'labels', :label_name], Api::Resources::Label, {resource_name: "pacticipant_label"}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ class VerifiablePactsQueryDecorator < BaseDecorator
using PactBroker::HashRefinements

collection :provider_version_tags, default: []
property :provider_version_branch

collection :consumer_version_selectors, default: PactBroker::Pacts::Selectors.new, class: PactBroker::Pacts::Selector do
property :tag
property :branch
property :latest,
setter: ->(fragment:, represented:, **) {
represented.latest = (fragment == 'true' || fragment == true)
Expand Down
6 changes: 4 additions & 2 deletions lib/pact_broker/api/decorators/version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ module Api
module Decorators
class VersionDecorator < BaseDecorator

property :number
property :number, writeable: false
property :branch
property :build_url, as: :buildUrl

collection :tags, embedded: true, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator
collection :tags, embedded: true, writeable: false, :extend => PactBroker::Api::Decorators::EmbeddedTagDecorator

include Timestamps

Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/api/resources/default_base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def consumer_version_number
identifier_from_path[:consumer_version_number]
end

def pacticipant_version_number
identifier_from_path[:pacticipant_version_number]
end

def consumer_specified?
identifier_from_path.key?(:consumer_name)
end
Expand Down
6 changes: 6 additions & 0 deletions lib/pact_broker/api/resources/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ def links
title: "Get, create or delete a tag for a pacticipant version",
templated: true
},
'pb:pacticipant-version' =>
{
href: base_url + '/pacticipants/{pacticipant}/versions/{version}',
title: "Get, create or delete a pacticipant version",
templated: true
},
'pb:metrics' =>
{
href: base_url + '/metrics',
Expand Down
27 changes: 27 additions & 0 deletions lib/pact_broker/api/resources/latest_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'pact_broker/api/resources/version'

module PactBroker
module Api
module Resources
class LatestVersion < Version
def content_types_accepted
[]
end

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

private

def version
if identifier_from_path[:tag]
@version ||= version_service.find_by_pacticipant_name_and_latest_tag(identifier_from_path[:pacticipant_name], identifier_from_path[:tag])
else
@version ||= version_service.find_latest_by_pacticpant_name(identifier_from_path)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def process_post
def pacts
@pacts ||= pact_service.find_for_verification(
provider_name,
parsed_query_params.provider_version_branch,
parsed_query_params.provider_version_tags,
parsed_query_params.consumer_version_selectors,
{
Expand Down
24 changes: 15 additions & 9 deletions lib/pact_broker/api/resources/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@ def content_types_provided
[["application/hal+json", :to_json]]
end

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

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

def resource_exists?
!!version
end

def from_json
response_code = version ? 200 : 201
parsed_version = Decorators::VersionDecorator.new(PactBroker::Domain::Version.new).from_json(request_body)
@version = version_service.create_or_update(pacticipant_name, pacticipant_version_number, parsed_version)
response.body = to_json
response_code
end

def to_json
decorator_class(:version_decorator).new(version).to_json(decorator_options)
end

def delete_resource
version_service.delete version
version_service.delete(version)
true
end

Expand All @@ -34,13 +46,7 @@ def policy_name
private

def version
if identifier_from_path[:tag]
@version ||= version_service.find_by_pacticipant_name_and_latest_tag(identifier_from_path[:pacticipant_name], identifier_from_path[:tag])
elsif identifier_from_path[:pacticipant_version_number]
@version ||= version_service.find_by_pacticipant_name_and_number(identifier_from_path)
else
@version ||= version_service.find_latest_by_pacticpant_name(identifier_from_path)
end
@version ||= version_service.find_by_pacticipant_name_and_number(identifier_from_path)
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions lib/pact_broker/doc/views/index/pacticipant-version.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Pacticipant version

Allowed methods: `GET`, `PUT`, `DELETE`

Path: `/pacticipants/{pacticipant}/versions/{version}`

## Example

PUT http://broker/pacticipants/Bar/versions/1e70030c6579915e5ff56b107a0fd25cf5df7464
{
"branch": "main",
"buildUrl": "http://ci.mydomain/my-job/1"
}
8 changes: 8 additions & 0 deletions lib/pact_broker/domain/pacticipant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def label label_name
filter = name_like(Sequel[:labels][:name], label_name)
join(:labels, {pacticipant_id: :id}).where(filter)
end

def find_by_name(name)
where(name_like(:name, name))
end
end

def before_destroy
Expand All @@ -51,6 +55,10 @@ def validate
messages << message('errors.validation.attribute_missing', attribute: 'name') unless name
messages
end

def any_versions?
PactBroker::Domain::Version.where(pacticipant: self).any?
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/domain/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def latest?

class Version < Sequel::Model
plugin :timestamps, update_on_create: true
plugin :insert_ignore, identifying_columns: [:pacticipant_id, :number]
plugin :upsert, identifying_columns: [:pacticipant_id, :number]

set_primary_key :id
one_to_many :pact_publications, order: :revision_number, class: "PactBroker::Pacts::PactPublication", key: :consumer_version_id
Expand Down
81 changes: 2 additions & 79 deletions lib/pact_broker/pacts/pact_publication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'pact_broker/repositories/helpers'
require 'pact_broker/integrations/integration'
require 'pact_broker/tags/head_pact_tags'
require 'pact_broker/pacts/pact_publication_dataset_module'

module PactBroker
module Pacts
Expand All @@ -27,86 +28,8 @@ class PactPublication < Sequel::Model(:pact_publications)

dataset_module do
include PactBroker::Repositories::Helpers
include PactPublicationDatasetModule

def remove_overridden_revisions
join(:latest_pact_publication_ids_for_consumer_versions, { Sequel[:lp][:pact_publication_id] => Sequel[:pact_publications][:id] }, { table_alias: :lp})
end

def join_consumer_versions(table_alias = :cv)
join(:versions, { Sequel[:pact_publications][:consumer_version_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
end

def join_consumer_version_tags(table_alias = :ct)
join(:tags, { Sequel[table_alias][:version_id] => Sequel[:pact_publications][:consumer_version_id]}, { table_alias: table_alias })
end

def join_consumer_version_tags_with_names(consumer_version_tag_names)
join(:tags, {
Sequel[:ct][:version_id] => Sequel[:pact_publications][:consumer_version_id],
Sequel[:ct][:name] => consumer_version_tag_names
}, {
table_alias: :ct
})
end

def join_providers(table_alias = :providers)
join(:pacticipants, { Sequel[:pact_publications][:provider_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
end

def join_consumers(table_alias = :consumers)
join(:pacticipants, { Sequel[:pact_publications][:consumer_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
end

def join_pact_versions
join(:pact_versions, { Sequel[:pact_publications][:pact_version_id] => Sequel[:pact_versions][:id] })
end

def eager_load_pact_versions
eager(:pact_versions)
end

def tag tag_name
filter = name_like(Sequel.qualify(:tags, :name), tag_name)
join(:tags, {version_id: :consumer_version_id}).where(filter)
end

def provider_name_like(name)
where(name_like(Sequel[:providers][:name], name))
end

def consumer_name_like(name)
where(name_like(Sequel[:consumers][:name], name))
end

def consumer_version_number_like(number)
where(name_like(Sequel[:cv][:number], number))
end

def consumer_version_tag(tag)
where(Sequel[:ct][:name] => tag)
end

def order_by_consumer_name
order_append_ignore_case(Sequel[:consumers][:name])
end

def order_by_consumer_version_order
order_append(Sequel[:cv][:order])
end

def where_consumer_if_set(consumer)
if consumer
where(consumer: consumer)
else
self
end
end

def delete
require 'pact_broker/webhooks/triggered_webhook'
PactBroker::Webhooks::TriggeredWebhook.where(pact_publication: self).delete
super
end
end

def before_create
Expand Down
Loading