duffel_api 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.gitignore +1 -0
  4. data/Appraisals +11 -0
  5. data/CHANGELOG.md +6 -0
  6. data/Gemfile +3 -2
  7. data/README.md +34 -1
  8. data/duffel_api.gemspec +6 -4
  9. data/examples/book_with_extra_baggage.rb +83 -0
  10. data/examples/book_with_seat.rb +1 -2
  11. data/lib/duffel_api/api_response.rb +35 -5
  12. data/lib/duffel_api/api_service.rb +18 -4
  13. data/lib/duffel_api/client.rb +24 -1
  14. data/lib/duffel_api/errors/error.rb +44 -1
  15. data/lib/duffel_api/list_response.rb +17 -0
  16. data/lib/duffel_api/middlewares/raise_duffel_errors.rb +18 -2
  17. data/lib/duffel_api/paginator.rb +11 -3
  18. data/lib/duffel_api/request.rb +32 -16
  19. data/lib/duffel_api/resources/aircraft.rb +7 -6
  20. data/lib/duffel_api/resources/airline.rb +7 -6
  21. data/lib/duffel_api/resources/airport.rb +21 -6
  22. data/lib/duffel_api/resources/base_resource.rb +3 -0
  23. data/lib/duffel_api/resources/offer_passenger.rb +11 -0
  24. data/lib/duffel_api/resources/offer_request.rb +15 -6
  25. data/lib/duffel_api/response.rb +24 -5
  26. data/lib/duffel_api/services/aircraft_service.rb +18 -0
  27. data/lib/duffel_api/services/airlines_service.rb +17 -0
  28. data/lib/duffel_api/services/airports_service.rb +18 -0
  29. data/lib/duffel_api/services/base_service.rb +17 -4
  30. data/lib/duffel_api/services/offer_passengers_service.rb +7 -0
  31. data/lib/duffel_api/services/offer_requests_service.rb +24 -0
  32. data/lib/duffel_api/services/offers_service.rb +18 -0
  33. data/lib/duffel_api/services/order_cancellations_service.rb +28 -0
  34. data/lib/duffel_api/services/order_change_offers_service.rb +18 -0
  35. data/lib/duffel_api/services/order_change_requests_service.rb +11 -0
  36. data/lib/duffel_api/services/order_changes_service.rb +17 -0
  37. data/lib/duffel_api/services/orders_service.rb +28 -0
  38. data/lib/duffel_api/services/payment_intents_service.rb +15 -0
  39. data/lib/duffel_api/services/payments_service.rb +5 -0
  40. data/lib/duffel_api/services/refunds_service.rb +10 -0
  41. data/lib/duffel_api/services/seat_maps_service.rb +6 -0
  42. data/lib/duffel_api/services/webhooks_service.rb +23 -2
  43. data/lib/duffel_api/version.rb +1 -1
  44. data/lib/duffel_api/webhook_event.rb +119 -0
  45. data/lib/duffel_api.rb +1 -0
  46. metadata +36 -6
  47. data/.circleci/config.yml +0 -82
  48. data/.github/dependabot.yml +0 -6
@@ -3,6 +3,12 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class OrderChangeOffersService < BaseService
6
+ # Lists order change offers, returning a single page of results.
7
+ #
8
+ # @option [Hash] :params Parameters to include in the HTTP querystring, including
9
+ # any filters
10
+ # @return [ListResponse]
11
+ # @raise [Errors::Error] when the Duffel API returns an error
6
12
  def list(options = {})
7
13
  path = "/air/order_change_offers"
8
14
 
@@ -15,6 +21,13 @@ module DuffelAPI
15
21
  )
16
22
  end
17
23
 
24
+ # Returns an `Enumerator` which can automatically cycle through multiple
25
+ # pages of `Resources;:OrderChangeOffer`s
26
+ #
27
+ # @param options [Hash] options passed to `#list`, for example `:params` to
28
+ # send an HTTP querystring with filters
29
+ # @return [Enumerator]
30
+ # @raise [Errors::Error] when the Duffel API returns an error
18
31
  def all(options = {})
19
32
  Paginator.new(
20
33
  service: self,
@@ -22,6 +35,11 @@ module DuffelAPI
22
35
  ).enumerator
23
36
  end
24
37
 
38
+ # Retrieves a single order change offer by ID
39
+ #
40
+ # @param id [String]
41
+ # @return [Resources::OrderChangeOffer]
42
+ # @raise [Errors::Error] when the Duffel API returns an error
25
43
  def get(id, options = {})
26
44
  path = substitute_url_pattern("/air/order_change_offers/:id", "id" => id)
27
45
 
@@ -3,6 +3,12 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class OrderChangeRequestsService < BaseService
6
+ # Creates an order change request
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the order change
9
+ # request
10
+ # @return [Resources::OrderChangeRequest]
11
+ # @raise [Errors::Error] when the Duffel API returns an error
6
12
  def create(options = {})
7
13
  path = "/air/order_change_requests"
8
14
 
@@ -23,6 +29,11 @@ module DuffelAPI
23
29
  Resources::OrderChangeRequest.new(unenvelope_body(response.parsed_body), response)
24
30
  end
25
31
 
32
+ # Retrieves a single order change request by ID
33
+ #
34
+ # @param id [String]
35
+ # @return [Resources::OrderChangeRequest]
36
+ # @raise [Errors::Error] when the Duffel API returns an error
26
37
  def get(id, options = {})
27
38
  path = substitute_url_pattern("/air/order_change_requests/:id", "id" => id)
28
39
 
@@ -3,6 +3,11 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class OrderChangesService < BaseService
6
+ # Creates an order chnage
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the order change
9
+ # @return [Resources::OrderChange]
10
+ # @raise [Errors::Error] when the Duffel API returns an error
6
11
  def create(options = {})
7
12
  path = "/air/order_changes"
8
13
 
@@ -22,6 +27,13 @@ module DuffelAPI
22
27
  Resources::OrderChange.new(unenvelope_body(response.parsed_body), response)
23
28
  end
24
29
 
30
+ # Confirms an order change by ID, passing across extra data required for
31
+ # confirmation
32
+ #
33
+ # @param id [String]
34
+ # @option [required, Hash] :params
35
+ # @return [Resources::OrderChange] the payload for confirming the order change
36
+ # @raise [Errors::Error] when the Duffel API returns an error
25
37
  def confirm(id, options = {})
26
38
  path = substitute_url_pattern("/air/order_changes/:id/actions/confirm",
27
39
  "id" => id)
@@ -42,6 +54,11 @@ module DuffelAPI
42
54
  Resources::OrderChange.new(unenvelope_body(response.parsed_body), response)
43
55
  end
44
56
 
57
+ # Retrieves a single order change by ID
58
+ #
59
+ # @param id [String]
60
+ # @return [Resources::OrderChange]
61
+ # @raise [Errors::Error] when the Duffel API returns an error
45
62
  def get(id, options = {})
46
63
  path = substitute_url_pattern("/air/order_changes/:id", "id" => id)
47
64
 
@@ -3,6 +3,11 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class OrdersService < BaseService
6
+ # Creates an order
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the order
9
+ # @return [Resources::Order]
10
+ # @raise [Errors::Error] when the Duffel API returns an error
6
11
  def create(options = {})
7
12
  path = "/air/orders"
8
13
 
@@ -22,6 +27,11 @@ module DuffelAPI
22
27
  Resources::Order.new(unenvelope_body(response.parsed_body), response)
23
28
  end
24
29
 
30
+ # Updates an order
31
+ #
32
+ # @option [required, Hash] :params the payload for updating the order
33
+ # @return [Resources::Order]
34
+ # @raise [Errors::Error] when the Duffel API returns an error
25
35
  def update(id, options = {})
26
36
  path = substitute_url_pattern("/air/orders/:id", "id" => id)
27
37
 
@@ -41,6 +51,12 @@ module DuffelAPI
41
51
  Resources::Order.new(unenvelope_body(response.parsed_body), response)
42
52
  end
43
53
 
54
+ # Lists orders, returning a single page of results.
55
+ #
56
+ # @option [Hash] :params Parameters to include in the HTTP querystring, including
57
+ # any filters
58
+ # @return [ListResponse]
59
+ # @raise [Errors::Error] when the Duffel API returns an error
44
60
  def list(options = {})
45
61
  path = "/air/orders"
46
62
 
@@ -53,6 +69,13 @@ module DuffelAPI
53
69
  )
54
70
  end
55
71
 
72
+ # Returns an `Enumerator` which can automatically cycle through multiple
73
+ # pages of `Resources;:Order`s
74
+ #
75
+ # @param options [Hash] options passed to `#list`, for example `:params` to
76
+ # send an HTTP querystring with filters
77
+ # @return [Enumerator]
78
+ # @raise [Errors::Error] when the Duffel API returns an error
56
79
  def all(options = {})
57
80
  Paginator.new(
58
81
  service: self,
@@ -60,6 +83,11 @@ module DuffelAPI
60
83
  ).enumerator
61
84
  end
62
85
 
86
+ # Retrieves a single order by ID
87
+ #
88
+ # @param id [String]
89
+ # @return [Resources::Order]
90
+ # @raise [Errors::Error] when the Duffel API returns an error
63
91
  def get(id, options = {})
64
92
  path = substitute_url_pattern("/air/orders/:id", "id" => id)
65
93
 
@@ -3,6 +3,11 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class PaymentIntentsService < BaseService
6
+ # Creates an payment intent
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the payment intent
9
+ # @return [Resources::PaymentIntent]
10
+ # @raise [Errors::Error] when the Duffel API returns an error
6
11
  def create(options = {})
7
12
  path = "/payments/payment_intents"
8
13
 
@@ -22,6 +27,11 @@ module DuffelAPI
22
27
  Resources::PaymentIntent.new(unenvelope_body(response.parsed_body), response)
23
28
  end
24
29
 
30
+ # Confirms a payment intent by ID
31
+ #
32
+ # @param id [String]
33
+ # @return [Resources::PaymentIntent]
34
+ # @raise [Errors::Error] when the Duffel API returns an error
25
35
  def confirm(id, options = {})
26
36
  path = substitute_url_pattern("/payments/payment_intents/:id/actions/confirm",
27
37
  "id" => id)
@@ -42,6 +52,11 @@ module DuffelAPI
42
52
  Resources::PaymentIntent.new(unenvelope_body(response.parsed_body), response)
43
53
  end
44
54
 
55
+ # Retrieves a single payment intent by ID
56
+ #
57
+ # @param id [String]
58
+ # @return [Resources::PaymentIntent]
59
+ # @raise [Errors::Error] when the Duffel API returns an error
45
60
  def get(id, options = {})
46
61
  path = substitute_url_pattern("/payments/payment_intents/:id", "id" => id)
47
62
 
@@ -3,6 +3,11 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class PaymentsService < BaseService
6
+ # Creates an payment
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the payment
9
+ # @return [Resources::Payment]
10
+ # @raise [Errors::Error] when the Duffel API returns an error
6
11
  def create(options = {})
7
12
  path = "/air/payments"
8
13
 
@@ -3,6 +3,11 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class RefundsService < BaseService
6
+ # Creates a refund
7
+ #
8
+ # @option [required, Hash] :params the payload for creating the refund
9
+ # @return [Resources::Refund]
10
+ # @raise [Errors::Error] when the Duffel API returns an error
6
11
  def create(options = {})
7
12
  path = "/payments/refunds"
8
13
 
@@ -22,6 +27,11 @@ module DuffelAPI
22
27
  Resources::Refund.new(unenvelope_body(response.parsed_body), response)
23
28
  end
24
29
 
30
+ # Retrieves a single refund by ID
31
+ #
32
+ # @param id [String]
33
+ # @return [Resources::Refund]
34
+ # @raise [Errors::Error] when the Duffel API returns an error
25
35
  def get(id, options = {})
26
36
  path = substitute_url_pattern("/payments/refunds/:id", "id" => id)
27
37
 
@@ -3,6 +3,12 @@
3
3
  module DuffelAPI
4
4
  module Services
5
5
  class SeatMapsService < BaseService
6
+ # Lists all seat maps for an offer. This data is __not__ paginated.
7
+ #
8
+ # @option [Hash] :params Parameters to include in the HTTP querystring, including
9
+ # any filters
10
+ # @return [ListResponse]
11
+ # @raise [Errors::Error] when the Duffel API returns an error
6
12
  def list(options = {})
7
13
  path = "/air/seat_maps"
8
14
 
@@ -4,19 +4,29 @@ module DuffelAPI
4
4
  module Services
5
5
  class WebhooksService < BaseService
6
6
  class PingResult
7
+ # Returns the raw API response this resource originated from
8
+ #
9
+ # @return [APIResponse]
7
10
  attr_reader :api_response
8
11
 
9
12
  def initialize(api_response)
10
13
  @api_response = api_response
11
14
  end
12
15
 
13
- # If we return a `PingResult` rather than an error, then that means that the
14
- # action was successful.
16
+ # Returns whether the ping was successful. This is always true, because if the
17
+ # ping fails, we raise an error.
18
+ #
19
+ # @return [Boolean]
15
20
  def succeeded
16
21
  true
17
22
  end
18
23
  end
19
24
 
25
+ # Creates an webhook
26
+ #
27
+ # @option [required, Hash] :params the payload for creating the webhook
28
+ # @return [Resources::Webhook]
29
+ # @raise [Errors::Error] when the Duffel API returns an error
20
30
  def create(options = {})
21
31
  path = "/air/webhooks"
22
32
 
@@ -36,6 +46,12 @@ module DuffelAPI
36
46
  Resources::Webhook.new(unenvelope_body(response.parsed_body), response)
37
47
  end
38
48
 
49
+ # Updates a webhook by ID
50
+ #
51
+ # @param id [String]
52
+ # @option [required, Hash] :params the payload for updating the webhook
53
+ # @return [Resources::Webhook]
54
+ # @raise [Errors::Error] when the Duffel API returns an error
39
55
  def update(id, options = {})
40
56
  path = substitute_url_pattern("/air/webhooks/:id", "id" => id)
41
57
 
@@ -55,6 +71,11 @@ module DuffelAPI
55
71
  Resources::Webhook.new(unenvelope_body(response.parsed_body), response)
56
72
  end
57
73
 
74
+ # Pings a webhook by ID
75
+ #
76
+ # @param id [String]
77
+ # @return [PingResult]
78
+ # @raise [Errors::Error] when the Duffel API returns an error
58
79
  def ping(id, options = {})
59
80
  path = substitute_url_pattern("/air/webhooks/:id/actions/ping", "id" => id)
60
81
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DuffelAPI
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base16"
4
+ require "openssl"
5
+
6
+ module DuffelAPI
7
+ module WebhookEvent
8
+ # An exception raised internally within the library - but not exposed - if the
9
+ # webhook signature provided does not match the format of a valid signature
10
+ class InvalidRequestSignatureError < StandardError; end
11
+
12
+ SIGNATURE_REGEXP = /\At=(.+),v1=(.+)\z/.freeze
13
+
14
+ SHA_256 = OpenSSL::Digest.new("sha256")
15
+
16
+ class << self
17
+ # Checks if a webhook event you received was a genuine webhook event from Duffel by
18
+ # checking that it was signed with your shared secret.
19
+ #
20
+ # Assuming that you've kept that secret secure and only shared it with Duffel,
21
+ # this can give you confidence that a webhook event was genuinely sent by Duffel.
22
+ #
23
+ # @param request_body [String] The raw body of the received request
24
+ # @param request_signature [String] The signature provided with the received
25
+ # request, found in the `X-Duffel-Signature` request header
26
+ # @param webhook_secret [String] The secret of the webhook, registered with Duffel
27
+ # @return [Boolean] whether the webhook signature matches
28
+ def genuine?(request_body:, request_signature:, webhook_secret:)
29
+ parsed_signature = parse_signature!(request_signature)
30
+
31
+ calculated_hmac = calculate_hmac(
32
+ payload: request_body,
33
+ secret: webhook_secret,
34
+ timestamp: parsed_signature[:timestamp],
35
+ )
36
+
37
+ secure_compare(calculated_hmac, parsed_signature[:v1])
38
+ rescue InvalidRequestSignatureError
39
+ # If the signature doesn't even look like a valid one, then the webhook
40
+ # event can't be genuine
41
+ false
42
+ end
43
+
44
+ private
45
+
46
+ # Calculates the signature for a request body in the same way that the Duffel API
47
+ # does it
48
+ #
49
+ # @param secret [String]
50
+ # @param payload [String]
51
+ # @param timestamp [String]
52
+ # @return [String]
53
+ def calculate_hmac(secret:, payload:, timestamp:)
54
+ signed_payload = %(#{timestamp}.#{payload})
55
+ Base16.encode16(OpenSSL::HMAC.digest(SHA_256, secret,
56
+ signed_payload)).strip.downcase
57
+ end
58
+
59
+ # Parses a webhook signature and extracts the `v1` and `timestamp` values, if
60
+ # available.
61
+ #
62
+ # @param signature [String] A webhook event signature received in a request
63
+ # @return [Hash]
64
+ # @raise InvalidRequestSignatureError when the signature isn't valid
65
+ def parse_signature!(signature)
66
+ matches = signature.match(SIGNATURE_REGEXP)
67
+
68
+ if matches
69
+ {
70
+ v1: matches[2],
71
+ timestamp: matches[1],
72
+ }
73
+ else
74
+ raise InvalidRequestSignatureError
75
+ end
76
+ end
77
+
78
+ # Taken from `Rack::Utils`
79
+ # (<https://github.com/rack/rack/blob/03b4b9708f375db46ee214b219f709d08ed6eeb0/lib/rack/utils.rb#L371-L393>).
80
+ #
81
+ # Licensed under the MIT License
82
+ # (<https://github.com/rack/rack/blob/master/MIT-LICENSE>).
83
+ if defined?(OpenSSL.fixed_length_secure_compare)
84
+ # Checks if two strings are equal, performing a constant time string comparison
85
+ # resistant to timing attacks.
86
+ #
87
+ # @param a [String]
88
+ # @param b [String]
89
+ # @return [Boolean] whether the two strings are equal
90
+ # rubocop:disable Naming/MethodParameterName
91
+ def secure_compare(a, b)
92
+ # rubocop:enable Naming/MethodParameterName
93
+ return false unless a.bytesize == b.bytesize
94
+
95
+ OpenSSL.fixed_length_secure_compare(a, b)
96
+ end
97
+ else
98
+ # Checks if two strings are equal, performing a constant time string comparison
99
+ # resistant to timing attacks.
100
+ #
101
+ # @param [String] a
102
+ # @param [String] b
103
+ # @return [Boolean] whether the two strings are equal
104
+ # rubocop:disable Naming/MethodParameterName
105
+ def secure_compare(a, b)
106
+ # rubocop:enable Naming/MethodParameterName
107
+ return false unless a.bytesize == b.bytesize
108
+
109
+ l = a.unpack("C*")
110
+
111
+ r = 0
112
+ i = -1
113
+ b.each_byte { |v| r |= v ^ l[i += 1] }
114
+ r.zero?
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
data/lib/duffel_api.rb CHANGED
@@ -51,5 +51,6 @@ require_relative "duffel_api/client"
51
51
  require_relative "duffel_api/list_response"
52
52
  require_relative "duffel_api/request"
53
53
  require_relative "duffel_api/response"
54
+ require_relative "duffel_api/webhook_event"
54
55
 
55
56
  module DuffelAPI; end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duffel_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Duffel team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-31 00:00:00.000000000 Z
11
+ date: 2022-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base16
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: faraday
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -19,7 +33,7 @@ dependencies:
19
33
  version: 0.9.2
20
34
  - - "<"
21
35
  - !ruby/object:Gem::Version
22
- version: '2'
36
+ version: '3'
23
37
  type: :runtime
24
38
  prerelease: false
25
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +43,21 @@ dependencies:
29
43
  version: 0.9.2
30
44
  - - "<"
31
45
  - !ruby/object:Gem::Version
32
- version: '2'
46
+ version: '3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: appraisal
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.4'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.4'
33
61
  description:
34
62
  email:
35
63
  - help@duffel.com
@@ -37,11 +65,11 @@ executables: []
37
65
  extensions: []
38
66
  extra_rdoc_files: []
39
67
  files:
40
- - ".circleci/config.yml"
41
- - ".github/dependabot.yml"
68
+ - ".DS_Store"
42
69
  - ".gitignore"
43
70
  - ".rspec"
44
71
  - ".rubocop.yml"
72
+ - Appraisals
45
73
  - CHANGELOG.md
46
74
  - CODE_OF_CONDUCT.md
47
75
  - Gemfile
@@ -52,6 +80,7 @@ files:
52
80
  - bin/setup
53
81
  - duffel_api.gemspec
54
82
  - examples/book_and_change.rb
83
+ - examples/book_with_extra_baggage.rb
55
84
  - examples/book_with_seat.rb
56
85
  - examples/exploring_data.rb
57
86
  - examples/hold_and_pay_later.rb
@@ -108,6 +137,7 @@ files:
108
137
  - lib/duffel_api/services/seat_maps_service.rb
109
138
  - lib/duffel_api/services/webhooks_service.rb
110
139
  - lib/duffel_api/version.rb
140
+ - lib/duffel_api/webhook_event.rb
111
141
  homepage: https://github.com/duffelhq/duffel-api-ruby
112
142
  licenses:
113
143
  - MIT
data/.circleci/config.yml DELETED
@@ -1,82 +0,0 @@
1
- version: 2.1
2
-
3
- commands:
4
- setup_ruby:
5
- steps:
6
- - run:
7
- name: Install bundler gem
8
- command: gem install bundler --version '~> 2.2'
9
- - run:
10
- name: Install Ruby dependencies
11
- command: bundle check || bundle install
12
-
13
- executors:
14
- ruby:
15
- parameters:
16
- image:
17
- default: "cimg/ruby:3.0"
18
- type: string
19
- docker:
20
- - image: << parameters.image >>
21
- resource_class: small
22
-
23
- orbs:
24
- ruby: circleci/ruby@1.2
25
-
26
- jobs:
27
- test:
28
- parameters:
29
- ruby-image:
30
- type: string
31
- executor:
32
- name: ruby
33
- image: << parameters.ruby-image >>
34
- steps:
35
- - checkout
36
- - setup_ruby
37
- - ruby/rubocop-check
38
- - ruby/rspec-test
39
- coverage:
40
- executor: ruby
41
- environment:
42
- COVERAGE: true
43
- steps:
44
- - checkout
45
- - setup_ruby
46
- - run:
47
- name: Run tests with Simplecov enabled
48
- command: bundle exec rspec spec
49
- - store_artifacts:
50
- path: coverage
51
- code_examples:
52
- executor: ruby
53
- steps:
54
- - checkout
55
- - setup_ruby
56
- - run:
57
- name: Run "search and book" example
58
- command: bundle exec ruby examples/search_and_book.rb
59
- - run:
60
- name: Run "hold and pay later" example
61
- command: bundle exec ruby examples/hold_and_pay_later.rb
62
- - run:
63
- name: Run "exploring data" example
64
- command: bundle exec ruby examples/exploring_data.rb
65
- - run:
66
- name: Run "book with seat" example
67
- command: bundle exec ruby examples/book_with_seat.rb
68
- - run:
69
- name: Run "book and change" example
70
- command: bundle exec ruby examples/book_and_change.rb
71
- workflows:
72
- version: 2
73
- build_and_test:
74
- jobs:
75
- - test:
76
- matrix:
77
- parameters:
78
- ruby-image: ["cimg/ruby:2.6", "cimg/ruby:2.7", "cimg/ruby:3.0", "cimg/ruby:3.1"]
79
- - coverage
80
- - code_examples:
81
- requires:
82
- - test
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "bundler"
4
- directory: "/"
5
- schedule:
6
- interval: "daily"