stitches 3.5.0 → 3.6.0.RC1
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.
- checksums.yaml +5 -5
- data/.circleci/config.yml +102 -0
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/Gemfile.rails-4.2 +8 -0
- data/Gemfile.rails-5.0 +8 -0
- data/Gemfile.rails-5.1 +8 -0
- data/Gemfile.rails-5.2 +8 -0
- data/README.md +21 -1
- data/build-matrix.json +4 -0
- data/lib/stitches.rb +2 -1
- data/lib/stitches/add_deprecation_generator.rb +15 -0
- data/lib/stitches/api_generator.rb +3 -7
- data/lib/stitches/deprecation.rb +26 -0
- data/lib/stitches/generator_files/app/controllers/api/api_controller.rb +1 -0
- data/lib/stitches/spec.rb +2 -0
- data/lib/stitches/spec/be_gone.rb +19 -0
- data/lib/stitches/spec/show_deprecation.rb +46 -0
- data/lib/stitches/version.rb +1 -1
- data/lib/stitches_norailtie.rb +2 -0
- data/owners.json +7 -0
- data/spec/deprecation_spec.rb +49 -0
- data/spec/integration/add_to_rails_app_spec.rb +200 -0
- data/spec/spec/be_gone_spec.rb +18 -0
- data/spec/spec/show_deprecation_spec.rb +54 -0
- data/stitches.gemspec +4 -1
- metadata +52 -20
- data/Gemfile.lock +0 -154
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9af000ef971218e036d2b46e0bc508749ed8e834f216e857a57c6fb194928fe5
|
|
4
|
+
data.tar.gz: b39481868efbe1c8e373c265d9561d09989e1be3230b4716adf14176d5de63af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6eb58de02836b34c9ddda0170c4d0b53f64d4b95e01ca4726213af7ae701978fe772e50d038c46cceb6c78b47de46029f04a9043b08fb4d77e3abe8eb9ba79a
|
|
7
|
+
data.tar.gz: 553079dcb2c338bff86d978db574634802db678344c30655d1db3c67b0625b576034b2f410dae975e04accd7514681df7aee6c0b5c58be2e1a48cb6a3b877a7c
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# DO NOT MODIFY - this is managed by Git Reduce in goro
|
|
2
|
+
#
|
|
3
|
+
---
|
|
4
|
+
version: 2
|
|
5
|
+
jobs:
|
|
6
|
+
ruby-2.5.1-rails-5.2:
|
|
7
|
+
docker:
|
|
8
|
+
- image: circleci/ruby:2.5.1
|
|
9
|
+
environment:
|
|
10
|
+
BUNDLE_GEMFILE: Gemfile.rails-5.2
|
|
11
|
+
working_directory: "~/stitches"
|
|
12
|
+
steps:
|
|
13
|
+
- checkout
|
|
14
|
+
- run: bundle install --full-index
|
|
15
|
+
- run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
|
|
16
|
+
--format=doc
|
|
17
|
+
- run:
|
|
18
|
+
name: Notify Pager Duty
|
|
19
|
+
command: bundle exec y-notify eng-platform
|
|
20
|
+
when: on_fail
|
|
21
|
+
- store_test_results:
|
|
22
|
+
path: "/tmp/test-results"
|
|
23
|
+
ruby-2.4.4-rails-5.2:
|
|
24
|
+
docker:
|
|
25
|
+
- image: circleci/ruby:2.4.4
|
|
26
|
+
environment:
|
|
27
|
+
BUNDLE_GEMFILE: Gemfile.rails-5.2
|
|
28
|
+
working_directory: "~/stitches"
|
|
29
|
+
steps:
|
|
30
|
+
- checkout
|
|
31
|
+
- run: bundle install --full-index
|
|
32
|
+
- run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
|
|
33
|
+
--format=doc
|
|
34
|
+
- run:
|
|
35
|
+
name: Notify Pager Duty
|
|
36
|
+
command: bundle exec y-notify eng-platform
|
|
37
|
+
when: on_fail
|
|
38
|
+
- store_test_results:
|
|
39
|
+
path: "/tmp/test-results"
|
|
40
|
+
ruby-2.5.1-rails-5.1:
|
|
41
|
+
docker:
|
|
42
|
+
- image: circleci/ruby:2.5.1
|
|
43
|
+
environment:
|
|
44
|
+
BUNDLE_GEMFILE: Gemfile.rails-5.1
|
|
45
|
+
working_directory: "~/stitches"
|
|
46
|
+
steps:
|
|
47
|
+
- checkout
|
|
48
|
+
- run: bundle install --full-index
|
|
49
|
+
- run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
|
|
50
|
+
--format=doc
|
|
51
|
+
- run:
|
|
52
|
+
name: Notify Pager Duty
|
|
53
|
+
command: bundle exec y-notify eng-platform
|
|
54
|
+
when: on_fail
|
|
55
|
+
- store_test_results:
|
|
56
|
+
path: "/tmp/test-results"
|
|
57
|
+
ruby-2.4.4-rails-5.1:
|
|
58
|
+
docker:
|
|
59
|
+
- image: circleci/ruby:2.4.4
|
|
60
|
+
environment:
|
|
61
|
+
BUNDLE_GEMFILE: Gemfile.rails-5.1
|
|
62
|
+
working_directory: "~/stitches"
|
|
63
|
+
steps:
|
|
64
|
+
- checkout
|
|
65
|
+
- run: bundle install --full-index
|
|
66
|
+
- run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
|
|
67
|
+
--format=doc
|
|
68
|
+
- run:
|
|
69
|
+
name: Notify Pager Duty
|
|
70
|
+
command: bundle exec y-notify eng-platform
|
|
71
|
+
when: on_fail
|
|
72
|
+
- store_test_results:
|
|
73
|
+
path: "/tmp/test-results"
|
|
74
|
+
workflows:
|
|
75
|
+
version: 2
|
|
76
|
+
on-commit:
|
|
77
|
+
jobs:
|
|
78
|
+
- ruby-2.5.1-rails-5.2:
|
|
79
|
+
context: org-global
|
|
80
|
+
- ruby-2.4.4-rails-5.2:
|
|
81
|
+
context: org-global
|
|
82
|
+
- ruby-2.5.1-rails-5.1:
|
|
83
|
+
context: org-global
|
|
84
|
+
- ruby-2.4.4-rails-5.1:
|
|
85
|
+
context: org-global
|
|
86
|
+
scheduled:
|
|
87
|
+
triggers:
|
|
88
|
+
- schedule:
|
|
89
|
+
cron: 53 20 * * 1,2,3,4,5
|
|
90
|
+
filters:
|
|
91
|
+
branches:
|
|
92
|
+
only:
|
|
93
|
+
- master
|
|
94
|
+
jobs:
|
|
95
|
+
- ruby-2.5.1-rails-5.2:
|
|
96
|
+
context: org-global
|
|
97
|
+
- ruby-2.4.4-rails-5.2:
|
|
98
|
+
context: org-global
|
|
99
|
+
- ruby-2.5.1-rails-5.1:
|
|
100
|
+
context: org-global
|
|
101
|
+
- ruby-2.4.4-rails-5.1:
|
|
102
|
+
context: org-global
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.5.1
|
data/Gemfile.rails-4.2
ADDED
data/Gemfile.rails-5.0
ADDED
data/Gemfile.rails-5.1
ADDED
data/Gemfile.rails-5.2
ADDED
data/README.md
CHANGED
|
@@ -35,6 +35,21 @@ Then, set it up:
|
|
|
35
35
|
> bundle exec rake db:migrate
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### Upgrading from an older version
|
|
39
|
+
|
|
40
|
+
* If you have a version lower than 3.3.0, you need to run two generators, one of which creates a new database migration on your
|
|
41
|
+
`api_clients` table:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
> bin/rails generate stitches:add_enabled_to_api_clients
|
|
45
|
+
> bin/rails generate stitches:add_deprecation
|
|
46
|
+
```
|
|
47
|
+
* If you have a version lower than 3.6.0, you need to run one generator:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
> bin/rails generate stitches:add_deprecation
|
|
51
|
+
```
|
|
52
|
+
|
|
38
53
|
## Example Microservice Endpoint
|
|
39
54
|
|
|
40
55
|
Suppose we wish to allow our consumers to create Widgets
|
|
@@ -47,7 +62,7 @@ class Api::V1::WidgetsController < ApiController
|
|
|
47
62
|
head 201
|
|
48
63
|
else
|
|
49
64
|
render json: {
|
|
50
|
-
errors: Stitches::Errors.
|
|
65
|
+
errors: Stitches::Errors.from_active_record_object(widget)
|
|
51
66
|
}, status: 422
|
|
52
67
|
end
|
|
53
68
|
end
|
|
@@ -82,6 +97,7 @@ See [the wiki](https://github.com/stitchfix/stitches/wiki/Setup) for how to setu
|
|
|
82
97
|
- Versioned requests via HTTP content types
|
|
83
98
|
- Structured Errors
|
|
84
99
|
- ISO 8601-formatted dates
|
|
100
|
+
- Deprecation using the `Sunset` header
|
|
85
101
|
* The [Generator](https://github.com/stitchfix/stitches/wiki/Generator) sets up some code in your app, so you can start writing
|
|
86
102
|
APIs using vanilla Rails idioms:
|
|
87
103
|
- a "ping" controller that can vaidate your app is working
|
|
@@ -95,6 +111,10 @@ APIs using vanilla Rails idioms:
|
|
|
95
111
|
|
|
96
112
|
Although `Stitches.configuration` is global, do not depend directly on that in your logic. Instead, allow all classes to receive a configuration object in their constructor. This makes the classes easier to deal with and change, without incurring much of a real cost to development. Global symbols suck, but are convienient. This is how you make the most of it.
|
|
97
113
|
|
|
114
|
+
Also, the integration test does a lot of "testing the implementation", but since Rails generators are notorious for silently
|
|
115
|
+
failing with a successful result, we have to make sure that the various `inject_into_file` calls are actually working. Do not do
|
|
116
|
+
any fancy refactors here, just keep it up to date.
|
|
117
|
+
|
|
98
118
|
---
|
|
99
119
|
|
|
100
120
|
Provided with love by your friends at [Stitch Fix Engineering](http://technology.stitchfix.com)
|
data/build-matrix.json
ADDED
data/lib/stitches.rb
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module Stitches
|
|
4
|
+
class AddDeprecationGenerator < Rails::Generators::Base
|
|
5
|
+
source_root(File.expand_path(File.join(File.dirname(__FILE__),"generator_files")))
|
|
6
|
+
|
|
7
|
+
desc "Adds deprecation support to an app creates with an older version of stitches"
|
|
8
|
+
def add_deprecation
|
|
9
|
+
inject_into_file "app/controllers/api/api_controller.rb", after: /^class.*$/ do<<-CODE
|
|
10
|
+
include Stitches::Deprecation
|
|
11
|
+
CODE
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -12,10 +12,12 @@ module Stitches
|
|
|
12
12
|
|
|
13
13
|
desc "Bootstraps your API service with a basic ping controller and spec to ensure everything is setup properly"
|
|
14
14
|
def bootstrap_api
|
|
15
|
-
inject_into_file "Gemfile", after: /^gem ["
|
|
15
|
+
inject_into_file "Gemfile", after: /^gem ['"]rails['"].*$/ do<<-GEM
|
|
16
16
|
|
|
17
17
|
gem "apitome"
|
|
18
18
|
gem "responders"
|
|
19
|
+
gem "rspec_api_documentation", group: [ :development, :test ]
|
|
20
|
+
gem "capybara", group: [ :development, :test ]
|
|
19
21
|
GEM
|
|
20
22
|
end
|
|
21
23
|
inject_into_file "config/routes.rb", before: /^end/ do<<-ROUTES
|
|
@@ -51,12 +53,6 @@ mount api_docs, at: "docs"
|
|
|
51
53
|
template "spec/features/api_spec.rb.erb", "spec/features/api_spec.rb"
|
|
52
54
|
copy_file "spec/acceptance/ping_v1_spec.rb", "spec/acceptance/ping_v1_spec.rb"
|
|
53
55
|
|
|
54
|
-
inject_into_file "Gemfile", after: /^group :test, :development do.*$/ do<<-GEM
|
|
55
|
-
|
|
56
|
-
gem "rspec_api_documentation"
|
|
57
|
-
gem "capybara"
|
|
58
|
-
GEM
|
|
59
|
-
end
|
|
60
56
|
run 'bundle install'
|
|
61
57
|
|
|
62
58
|
migration_template "db/migrate/enable_uuid_ossp_extension.rb", "db/migrate/enable_uuid_ossp_extension.rb"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Stitches
|
|
2
|
+
module Deprecation
|
|
3
|
+
# Indicate that a previously-deprecated endpoint is now gone
|
|
4
|
+
def gone!
|
|
5
|
+
head 410
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Indicate that this endpoint is deprecated and will go away on the given date.
|
|
9
|
+
#
|
|
10
|
+
# gon_on: - date, as a string, when this endpoint will go away
|
|
11
|
+
# block - the contents of the endpoint
|
|
12
|
+
#
|
|
13
|
+
# Example:
|
|
14
|
+
#
|
|
15
|
+
# def show
|
|
16
|
+
# deprecated gone_on: "2019-04-09" do
|
|
17
|
+
# render widgets: { Widget.find(params[:id]) }
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
def deprecated(gone_on:,&block)
|
|
21
|
+
response.set_header("Sunset",Date.parse(gone_on).in_time_zone("GMT").midnight.strftime("%a, %e %b %Y %H:%M:%S %Z"))
|
|
22
|
+
Rails.logger.info("Deprecated endpoint #{request.method} #{request.fullpath} requested by #{current_user.id}")
|
|
23
|
+
block.()
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
class Api::ApiController < ActionController::Base
|
|
2
|
+
include Stitches::Deprecation
|
|
2
3
|
rescue_from ActiveRecord::RecordNotFound do |exception|
|
|
3
4
|
respond_to do |type|
|
|
4
5
|
type.json { render json: { errors: Stitches::Errors.new([ Stitches::Error.new(code: "not_found", message: exception.message) ]) }, status: 404 }
|
data/lib/stitches/spec.rb
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Use this to test that an HTTP response is properly "410/Gone"
|
|
2
|
+
#
|
|
3
|
+
# The object you expect on is generally `self`, because this is the object on which
|
|
4
|
+
# rspec_api_documentation allows you to call `status`
|
|
5
|
+
#
|
|
6
|
+
# get "/api/widgets" do
|
|
7
|
+
# it "has been removed" do
|
|
8
|
+
# expect(self).to be_gone
|
|
9
|
+
# end
|
|
10
|
+
# end
|
|
11
|
+
RSpec::Matchers.define :be_gone do
|
|
12
|
+
match do |rspec_api_documentation_context|
|
|
13
|
+
rspec_api_documentation_context.status == 410
|
|
14
|
+
end
|
|
15
|
+
failure_message do |rspec_api_documentation_context|
|
|
16
|
+
"Expected HTTP status to be 410/Gone, but it was #{rspec_api_documentation_context.status}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class DeprecationAnalysis
|
|
2
|
+
attr_reader :expected_sunset_value, :status, :sunset_value
|
|
3
|
+
def initialize(rspec_api_documentation_context, gone_on)
|
|
4
|
+
gone_on_date = Date.parse(gone_on)
|
|
5
|
+
if gone_on_date > Date.today
|
|
6
|
+
@expecting_sunset = true
|
|
7
|
+
@expected_sunset_value = gone_on_date.in_time_zone("GMT").midnight.strftime("%a, %e %b %Y %H:%M:%S %Z")
|
|
8
|
+
@sunset_header_set = rspec_api_documentation_context.response_headers["Sunset"].present?
|
|
9
|
+
@sunset_value = rspec_api_documentation_context.response_headers["Sunset"]
|
|
10
|
+
@sunset_header_match = @expected_sunset_value == @sunset_value
|
|
11
|
+
else
|
|
12
|
+
@expecting_gone = true
|
|
13
|
+
@status = rspec_api_documentation_context.status
|
|
14
|
+
@gone = @status == 410
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def expecting_sunset?; !!@expecting_sunset; end
|
|
19
|
+
def sunset_header_set?; !!@sunset_header_set; end
|
|
20
|
+
def sunset_header_match?; !!@sunset_header_match; end
|
|
21
|
+
def gone?; !!@gone; end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
RSpec::Matchers.define :show_deprecation do |gone_on:|
|
|
25
|
+
match do |rspec_api_documentation_context|
|
|
26
|
+
analysis = DeprecationAnalysis.new(rspec_api_documentation_context,gone_on)
|
|
27
|
+
if analysis.expecting_sunset?
|
|
28
|
+
analysis.sunset_header_match?
|
|
29
|
+
else
|
|
30
|
+
analysis.gone?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
failure_message do |rspec_api_documentation_context|
|
|
34
|
+
analysis = DeprecationAnalysis.new(rspec_api_documentation_context,gone_on)
|
|
35
|
+
if analysis.expecting_sunset?
|
|
36
|
+
if analysis.sunset_header_set?
|
|
37
|
+
"Expected the Sunset header to be #{analysis.expected_sunset_value}, but was '#{analysis.sunset_value}'"
|
|
38
|
+
else
|
|
39
|
+
"No Sunset header was set. Use the deprecation method from Stitches::Deprecation in the controller method to deprecate this action"
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
"Since the deprecation date has passed, expected HTTP status to be 410/Gone, but it was #{analysis.status}. Re-implement the endpoint using `gone!` and then change the test to expect it to `be_gone`"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
data/lib/stitches/version.rb
CHANGED
data/lib/stitches_norailtie.rb
CHANGED
|
@@ -12,7 +12,9 @@ require 'stitches/render_timestamps_in_iso8601_in_json'
|
|
|
12
12
|
require 'stitches/error'
|
|
13
13
|
require 'stitches/errors'
|
|
14
14
|
require 'stitches/api_generator'
|
|
15
|
+
require 'stitches/add_deprecation_generator'
|
|
15
16
|
require 'stitches/add_enabled_to_api_clients_generator'
|
|
16
17
|
require 'stitches/api_version_constraint'
|
|
17
18
|
require 'stitches/api_key'
|
|
19
|
+
require 'stitches/deprecation'
|
|
18
20
|
require 'stitches/valid_mime_type'
|
data/owners.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
describe Stitches::Deprecation do
|
|
4
|
+
let(:response) {
|
|
5
|
+
double("response").tap { |r|
|
|
6
|
+
allow(r).to receive(:set_header)
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
let(:request) { double("request", method: "PUT", fullpath: "/foo/bar?blah") }
|
|
10
|
+
let(:api_client) { double("ApiClient", id: 99) }
|
|
11
|
+
let(:fake_controller) {
|
|
12
|
+
double("Controller", response: response, request: request, current_user: api_client).extend(described_class).tap { |controller|
|
|
13
|
+
allow(controller).to receive(:head)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
describe "#gone" do
|
|
17
|
+
it "sends an HTTP 410" do
|
|
18
|
+
fake_controller.gone!
|
|
19
|
+
expect(fake_controller).to have_received(:head).with(410)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "#deprecated" do
|
|
24
|
+
let(:logger) { double("logger") }
|
|
25
|
+
before do
|
|
26
|
+
allow(Rails).to receive(:logger).and_return(logger)
|
|
27
|
+
allow(logger).to receive(:info)
|
|
28
|
+
end
|
|
29
|
+
it "sets the Sunset header to the date given in GMT" do
|
|
30
|
+
fake_controller.deprecated(gone_on: "2018-01-01") {}
|
|
31
|
+
expect(response).to have_received(:set_header).with("Sunset","Mon, 1 Jan 2018 00:00:00 GMT")
|
|
32
|
+
end
|
|
33
|
+
it "logs about the request and current API key id" do
|
|
34
|
+
fake_controller.deprecated(gone_on: "2018-01-01") {}
|
|
35
|
+
expect(logger).to have_received(:info).with(/deprecated.*#{Regexp.escape(request.method)}.*#{Regexp.escape(request.fullpath)}.*#{Regexp.escape(api_client.id.to_s)}/i)
|
|
36
|
+
end
|
|
37
|
+
it "executes and returns the block" do
|
|
38
|
+
block_executed = false
|
|
39
|
+
result = fake_controller.deprecated(gone_on: "2018-01-01") do
|
|
40
|
+
block_executed = true
|
|
41
|
+
42
|
|
42
|
+
end
|
|
43
|
+
aggregate_failures do
|
|
44
|
+
expect(result).to eq(42)
|
|
45
|
+
expect(block_executed).to eq(true)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
RSpec.describe "Adding Stitches to a New Rails App" do
|
|
6
|
+
let(:work_dir) { Dir.mktmpdir }
|
|
7
|
+
let(:rails_app_name) { "swamp-thing" }
|
|
8
|
+
|
|
9
|
+
def run(command)
|
|
10
|
+
stdout, stderr, stat = Open3.capture3(command)
|
|
11
|
+
success = stat.success? && stdout !~ /Could not find generator/im
|
|
12
|
+
|
|
13
|
+
if ENV["DEBUG"] == 'true' || !success
|
|
14
|
+
$stdout.puts stdout
|
|
15
|
+
$stderr.puts stderr
|
|
16
|
+
end
|
|
17
|
+
unless success
|
|
18
|
+
raise "'#{command}' failed"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
around(:each) do |example|
|
|
23
|
+
rails_new = [
|
|
24
|
+
"rails new #{rails_app_name}",
|
|
25
|
+
"--skip-yarn",
|
|
26
|
+
"--skip-git",
|
|
27
|
+
"--skip-keeps",
|
|
28
|
+
"--skip-action-mailer",
|
|
29
|
+
"--skip-active-storage",
|
|
30
|
+
"--skip-action-cable",
|
|
31
|
+
"--skip-spring",
|
|
32
|
+
"--skip-listen",
|
|
33
|
+
"--skip-coffee",
|
|
34
|
+
"--skip-javascript",
|
|
35
|
+
"--skip-turbolinks",
|
|
36
|
+
"--skip-bootsnap",
|
|
37
|
+
"--no-rc",
|
|
38
|
+
"--skip-bundle",
|
|
39
|
+
].join(" ")
|
|
40
|
+
FileUtils.chdir work_dir do
|
|
41
|
+
run rails_new
|
|
42
|
+
FileUtils.chdir rails_app_name do
|
|
43
|
+
example.run
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "works as described in the README" do
|
|
49
|
+
run "bin/rails generate rspec:install"
|
|
50
|
+
run "bin/rails generate apitome:install"
|
|
51
|
+
run "bin/rails generate stitches:api"
|
|
52
|
+
|
|
53
|
+
rails_root = Pathname(work_dir) / rails_app_name
|
|
54
|
+
|
|
55
|
+
# Yuck! So much duplication! BUT: Rails app templates have a notoriously silent failure mode, so mostly
|
|
56
|
+
# what this is doing is ensuring that the generator inserted stuff when asked and that the very basics of what happens
|
|
57
|
+
# during generation are there. It's gross, and I'm sorry.
|
|
58
|
+
#
|
|
59
|
+
# It's also in one big block because making a new rails app and running the generator multiple times seems bad.
|
|
60
|
+
aggregate_failures do
|
|
61
|
+
expect(File.exist?(rails_root / "app" / "controllers" / "api" / "api_controller.rb")).to eq(true)
|
|
62
|
+
expect(rails_root / "Gemfile").to contain_gem("apitome")
|
|
63
|
+
expect(rails_root / "Gemfile").to contain_gem("responders")
|
|
64
|
+
expect(rails_root / "Gemfile").to contain_gem("rspec_api_documentation")
|
|
65
|
+
expect(rails_root / "Gemfile").to contain_gem("capybara")
|
|
66
|
+
expect(rails_root / "config" / "routes.rb").to have_route(namespace: :api, module_scope: :v1, resource: 'ping')
|
|
67
|
+
expect(rails_root / "config" / "routes.rb").to have_route(namespace: :api, module_scope: :v2, resource: 'ping')
|
|
68
|
+
expect(rails_root / "config" / "routes.rb").to have_mounted_engine("Apitome::Engine")
|
|
69
|
+
migrations = Dir["#{rails_root}/db/migrate/*.rb"].sort
|
|
70
|
+
expect(migrations.size).to eq(2)
|
|
71
|
+
expect(migrations[0]).to match(/\/\d+_enable_uuid_ossp_extension.rb/)
|
|
72
|
+
expect(migrations[1]).to match(/\/\d+_create_api_clients.rb/)
|
|
73
|
+
expect(File.read(rails_root / "spec" / "rails_helper.rb")).to include("config.include RSpec::Rails::RequestExampleGroup, type: :feature")
|
|
74
|
+
expect(File.read(rails_root / "spec" / "rails_helper.rb")).to include("require 'stitches/spec'")
|
|
75
|
+
expect(File.read(rails_root / "spec" / "rails_helper.rb")).to include("require 'rspec_api_documentation'")
|
|
76
|
+
expect(File.read(rails_root / "config" / "initializers" / "apitome.rb")).to include("config.mount_at = nil")
|
|
77
|
+
expect(File.read(rails_root / "config" / "initializers" / "apitome.rb")).to include("config.title = 'Service Documentation'")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "inserts the deprecation module into ApiController" do
|
|
82
|
+
run "bin/rails generate rspec:install"
|
|
83
|
+
run "bin/rails generate apitome:install"
|
|
84
|
+
run "bin/rails generate stitches:api"
|
|
85
|
+
|
|
86
|
+
rails_root = Pathname(work_dir) / rails_app_name
|
|
87
|
+
api_controller = rails_root / "app" / "controllers" / "api" / "api_controller.rb"
|
|
88
|
+
|
|
89
|
+
api_controller_contents = File.read(api_controller).split(/\n/)
|
|
90
|
+
File.open(api_controller,"w") do |file|
|
|
91
|
+
api_controller_contents.each do |line|
|
|
92
|
+
file.puts line unless line =~ /Stitches::Deprecation/
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
run "bin/rails generate stitches:add_deprecation"
|
|
97
|
+
|
|
98
|
+
aggregate_failures do
|
|
99
|
+
expect(File.read(api_controller)).to include("include Stitches::Deprecation")
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class RoutesFileAnalysis
|
|
104
|
+
attr_reader :routes_file
|
|
105
|
+
def initialize(routes_file, namespace: nil, module_scope: nil, resource: nil, mounted_engine: nil)
|
|
106
|
+
@routes_file = File.read(routes_file).split(/\n/)
|
|
107
|
+
@found_namespace = false
|
|
108
|
+
@found_module = false
|
|
109
|
+
@found_resource = false
|
|
110
|
+
@found_engine = false
|
|
111
|
+
@engine_mounted = false
|
|
112
|
+
|
|
113
|
+
@routes_file.each do |line|
|
|
114
|
+
if line =~ /namespace :#{namespace} do/
|
|
115
|
+
@found_namespace = true
|
|
116
|
+
end
|
|
117
|
+
if @found_namespace && line =~ /^\s*scope module: :#{module_scope}, constraints: Stitches::ApiVersionConstraint/
|
|
118
|
+
@found_module = true
|
|
119
|
+
end
|
|
120
|
+
if @found_module && line =~ /^\s*resource\s+['"]#{resource}["']/
|
|
121
|
+
@found_resource = true
|
|
122
|
+
end
|
|
123
|
+
if line =~ /api_docs = Rack::Auth::Basic.new\(#{mounted_engine}/
|
|
124
|
+
@found_engine = true
|
|
125
|
+
end
|
|
126
|
+
if @found_engine && line =~ /mount api_docs/
|
|
127
|
+
@engine_mounted = true
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def found_namespace?
|
|
133
|
+
@found_namespace
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def found_module?
|
|
137
|
+
@found_module
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def found_resource?
|
|
141
|
+
@found_resource
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def found_engine?
|
|
145
|
+
@found_engine
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def engine_mounted?
|
|
149
|
+
@engine_mounted
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
RSpec::Matchers.define :have_mounted_engine do |engine_name|
|
|
154
|
+
match do |routes_file|
|
|
155
|
+
analysis = RoutesFileAnalysis.new(routes_file, mounted_engine: engine_name)
|
|
156
|
+
analysis.engine_mounted?
|
|
157
|
+
end
|
|
158
|
+
failure_message do |routes_file|
|
|
159
|
+
analysis = RoutesFileAnalysis.new(routes_file, mounted_engine: engine_name)
|
|
160
|
+
error = if analysis.found_engine?
|
|
161
|
+
"Found engine #{engine_name}, but it's not mounted"
|
|
162
|
+
else
|
|
163
|
+
"Didn't find engine #{engine_name}"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
error + "\n#{File.read(analysis.routes_file.join("\n"))}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
RSpec::Matchers.define :have_route do |namespace:, module_scope:, resource:|
|
|
171
|
+
match do |routes_file|
|
|
172
|
+
analysis = RoutesFileAnalysis.new(routes_file, namespace: namespace, module_scope: module_scope, resource: resource)
|
|
173
|
+
analysis.found_resource? && analysis.found_module? && analysis.found_namespace?
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
failure_message do |routes_file|
|
|
177
|
+
analysis = RoutesFileAnalysis.new(routes_file, namespace: namespace, module_scope: module_scope, resource: resource)
|
|
178
|
+
error = if analysis.found_namespace?
|
|
179
|
+
if analysis.found_module?
|
|
180
|
+
"Could not find resource '#{resource}'"
|
|
181
|
+
else
|
|
182
|
+
"Could not find module '#{scope_module}'"
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
"Could not find namespace '#{namespace}'"
|
|
186
|
+
end
|
|
187
|
+
error + "\n#{File.read(analysis.routes_file.join("\n"))}"
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
RSpec::Matchers.define :contain_gem do |gem_name|
|
|
191
|
+
match do |gemfile|
|
|
192
|
+
File.read(gemfile).split(/\n/).any? { |line|
|
|
193
|
+
line =~ /^\s*gem [\"\']#{gem_name}[\"\']/
|
|
194
|
+
}
|
|
195
|
+
end
|
|
196
|
+
failure_message do |gemfile|
|
|
197
|
+
"#{gem_name} not found in #{gemfile}:\n#{File.read(gemfile)}"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'spec_helper.rb'
|
|
2
|
+
require 'stitches/spec'
|
|
3
|
+
|
|
4
|
+
describe "be_gone" do
|
|
5
|
+
it "passes the test if the http status was 410" do
|
|
6
|
+
rspec_api_documentation_context = double("a test using rspec_api_documentation", status: 410)
|
|
7
|
+
expect(rspec_api_documentation_context).to be_gone
|
|
8
|
+
end
|
|
9
|
+
it "fails the test if the http status was not 401" do
|
|
10
|
+
rspec_api_documentation_context = double("a test using rspec_api_documentation", status: 200)
|
|
11
|
+
begin
|
|
12
|
+
expect(rspec_api_documentation_context).to be_gone
|
|
13
|
+
fail "Expected the matcher to fail"
|
|
14
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
|
15
|
+
expect(e.message).to match(/expected http status.*410.*200/i)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'spec_helper.rb'
|
|
2
|
+
require 'stitches/spec'
|
|
3
|
+
|
|
4
|
+
describe "show_deprecation" do
|
|
5
|
+
context "when the expiration date is in the future" do
|
|
6
|
+
it "passes if the sunset header is set properly" do
|
|
7
|
+
rspec_api_documentation_context = double(
|
|
8
|
+
"a test using rspec_api_documentation",
|
|
9
|
+
status: 200,
|
|
10
|
+
response_headers: { "Sunset" => "Mon, 13 Dec 2038 00:00:00 GMT" }
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
expect(rspec_api_documentation_context).to show_deprecation(gone_on: "2038-12-13")
|
|
14
|
+
end
|
|
15
|
+
it "fails if the sunset header is not set" do
|
|
16
|
+
begin
|
|
17
|
+
rspec_api_documentation_context = double( "a test using rspec_api_documentation", status: 200, response_headers: {})
|
|
18
|
+
expect(rspec_api_documentation_context).to show_deprecation(gone_on: "2038-12-13")
|
|
19
|
+
fail "Expected matcher to fail"
|
|
20
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
|
21
|
+
expect(e.message).to match(/No Sunset header was set/i)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
it "fails if the sunset header is the wrong date" do
|
|
25
|
+
begin
|
|
26
|
+
rspec_api_documentation_context = double(
|
|
27
|
+
"a test using rspec_api_documentation",
|
|
28
|
+
status: 200,
|
|
29
|
+
response_headers: { "Sunset" => "Tuesday, 14 Dec 2038 00:00:00 GMT" }
|
|
30
|
+
)
|
|
31
|
+
expect(rspec_api_documentation_context).to show_deprecation(gone_on: "2038-12-13")
|
|
32
|
+
fail "Expected matcher to fail"
|
|
33
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
|
34
|
+
expect(e.message).to match(/Expected the Sunset header to be Mon, 13 Dec 2038 00:00:00 GMT, but was 'Tuesday, 14 Dec 2038 00:00:00 GMT/i)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
context "when the expiration date is in the past" do
|
|
39
|
+
it "passes if the http status is 410/gone" do
|
|
40
|
+
rspec_api_documentation_context = double("a test using rspec_api_documentation", status: 410)
|
|
41
|
+
expect(rspec_api_documentation_context).to show_deprecation(gone_on: "2011-01-01")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "fails if the status is not 410/gone" do
|
|
45
|
+
rspec_api_documentation_context = double("a test using rspec_api_documentation", status: 200)
|
|
46
|
+
begin
|
|
47
|
+
expect(rspec_api_documentation_context).to show_deprecation(gone_on: "2011-01-01")
|
|
48
|
+
fail "Expected matcher to fail"
|
|
49
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
|
50
|
+
expect(e.message).to match(/deprecation date has passed.*410.*using `gone\!`/i)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/stitches.gemspec
CHANGED
|
@@ -17,10 +17,13 @@ Gem::Specification.new do |s|
|
|
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
18
|
s.executables = `git ls-files -- exe/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
19
|
s.require_paths = ["lib"]
|
|
20
|
+
|
|
20
21
|
s.add_runtime_dependency("rails")
|
|
21
22
|
s.add_runtime_dependency("pg")
|
|
22
|
-
s.add_development_dependency("rake")
|
|
23
23
|
s.add_runtime_dependency("rspec", ">= 3")
|
|
24
24
|
s.add_runtime_dependency("rspec-rails", "~> 3")
|
|
25
25
|
s.add_runtime_dependency("apitome")
|
|
26
|
+
|
|
27
|
+
s.add_development_dependency("rake")
|
|
28
|
+
s.add_development_dependency("rspec_junit_formatter")
|
|
26
29
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stitches
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0.RC1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stitch Fix Engineering
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2018-06-11 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: rails
|
|
@@ -41,20 +41,6 @@ dependencies:
|
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
43
|
version: '0'
|
|
44
|
-
- !ruby/object:Gem::Dependency
|
|
45
|
-
name: rake
|
|
46
|
-
requirement: !ruby/object:Gem::Requirement
|
|
47
|
-
requirements:
|
|
48
|
-
- - ">="
|
|
49
|
-
- !ruby/object:Gem::Version
|
|
50
|
-
version: '0'
|
|
51
|
-
type: :development
|
|
52
|
-
prerelease: false
|
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
54
|
-
requirements:
|
|
55
|
-
- - ">="
|
|
56
|
-
- !ruby/object:Gem::Version
|
|
57
|
-
version: '0'
|
|
58
44
|
- !ruby/object:Gem::Dependency
|
|
59
45
|
name: rspec
|
|
60
46
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -97,6 +83,34 @@ dependencies:
|
|
|
97
83
|
- - ">="
|
|
98
84
|
- !ruby/object:Gem::Version
|
|
99
85
|
version: '0'
|
|
86
|
+
- !ruby/object:Gem::Dependency
|
|
87
|
+
name: rake
|
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '0'
|
|
93
|
+
type: :development
|
|
94
|
+
prerelease: false
|
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
- !ruby/object:Gem::Dependency
|
|
101
|
+
name: rspec_junit_formatter
|
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '0'
|
|
107
|
+
type: :development
|
|
108
|
+
prerelease: false
|
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - ">="
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: '0'
|
|
100
114
|
description: You'll be in stitches at how easy it is to create a service at Stitch
|
|
101
115
|
Fix
|
|
102
116
|
email:
|
|
@@ -108,6 +122,7 @@ executables: []
|
|
|
108
122
|
extensions: []
|
|
109
123
|
extra_rdoc_files: []
|
|
110
124
|
files:
|
|
125
|
+
- ".circleci/config.yml"
|
|
111
126
|
- ".gitignore"
|
|
112
127
|
- ".ruby-gemset"
|
|
113
128
|
- ".ruby-version"
|
|
@@ -115,16 +130,22 @@ files:
|
|
|
115
130
|
- CODE_OF_CONDUCT.md
|
|
116
131
|
- CONTRIBUTING.md
|
|
117
132
|
- Gemfile
|
|
118
|
-
- Gemfile.
|
|
133
|
+
- Gemfile.rails-4.2
|
|
134
|
+
- Gemfile.rails-5.0
|
|
135
|
+
- Gemfile.rails-5.1
|
|
136
|
+
- Gemfile.rails-5.2
|
|
119
137
|
- LICENSE.txt
|
|
120
138
|
- README.md
|
|
121
139
|
- Rakefile
|
|
140
|
+
- build-matrix.json
|
|
122
141
|
- lib/stitches.rb
|
|
142
|
+
- lib/stitches/add_deprecation_generator.rb
|
|
123
143
|
- lib/stitches/add_enabled_to_api_clients_generator.rb
|
|
124
144
|
- lib/stitches/api_generator.rb
|
|
125
145
|
- lib/stitches/api_key.rb
|
|
126
146
|
- lib/stitches/api_version_constraint.rb
|
|
127
147
|
- lib/stitches/configuration.rb
|
|
148
|
+
- lib/stitches/deprecation.rb
|
|
128
149
|
- lib/stitches/error.rb
|
|
129
150
|
- lib/stitches/errors.rb
|
|
130
151
|
- lib/stitches/generator_files/app/controllers/api.rb
|
|
@@ -145,19 +166,26 @@ files:
|
|
|
145
166
|
- lib/stitches/render_timestamps_in_iso8601_in_json.rb
|
|
146
167
|
- lib/stitches/spec.rb
|
|
147
168
|
- lib/stitches/spec/api_clients.rb
|
|
169
|
+
- lib/stitches/spec/be_gone.rb
|
|
148
170
|
- lib/stitches/spec/be_iso_8601_utc_encoded.rb
|
|
149
171
|
- lib/stitches/spec/have_api_error.rb
|
|
172
|
+
- lib/stitches/spec/show_deprecation.rb
|
|
150
173
|
- lib/stitches/spec/test_headers.rb
|
|
151
174
|
- lib/stitches/valid_mime_type.rb
|
|
152
175
|
- lib/stitches/version.rb
|
|
153
176
|
- lib/stitches/whitelisting_middleware.rb
|
|
154
177
|
- lib/stitches_norailtie.rb
|
|
178
|
+
- owners.json
|
|
155
179
|
- spec/api_key_spec.rb
|
|
156
180
|
- spec/api_version_constraint_spec.rb
|
|
157
181
|
- spec/configuration_spec.rb
|
|
182
|
+
- spec/deprecation_spec.rb
|
|
158
183
|
- spec/error_spec.rb
|
|
159
184
|
- spec/errors_spec.rb
|
|
185
|
+
- spec/integration/add_to_rails_app_spec.rb
|
|
186
|
+
- spec/spec/be_gone_spec.rb
|
|
160
187
|
- spec/spec/have_api_error_spec.rb
|
|
188
|
+
- spec/spec/show_deprecation_spec.rb
|
|
161
189
|
- spec/spec_helper.rb
|
|
162
190
|
- spec/valid_mime_type_spec.rb
|
|
163
191
|
- stitches.gemspec
|
|
@@ -176,12 +204,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
176
204
|
version: '0'
|
|
177
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
206
|
requirements:
|
|
179
|
-
- - "
|
|
207
|
+
- - ">"
|
|
180
208
|
- !ruby/object:Gem::Version
|
|
181
|
-
version:
|
|
209
|
+
version: 1.3.1
|
|
182
210
|
requirements: []
|
|
183
211
|
rubyforge_project:
|
|
184
|
-
rubygems_version: 2.
|
|
212
|
+
rubygems_version: 2.7.6
|
|
185
213
|
signing_key:
|
|
186
214
|
specification_version: 4
|
|
187
215
|
summary: You'll be in stitches at how easy it is to create a service at Stitch Fix
|
|
@@ -189,8 +217,12 @@ test_files:
|
|
|
189
217
|
- spec/api_key_spec.rb
|
|
190
218
|
- spec/api_version_constraint_spec.rb
|
|
191
219
|
- spec/configuration_spec.rb
|
|
220
|
+
- spec/deprecation_spec.rb
|
|
192
221
|
- spec/error_spec.rb
|
|
193
222
|
- spec/errors_spec.rb
|
|
223
|
+
- spec/integration/add_to_rails_app_spec.rb
|
|
224
|
+
- spec/spec/be_gone_spec.rb
|
|
194
225
|
- spec/spec/have_api_error_spec.rb
|
|
226
|
+
- spec/spec/show_deprecation_spec.rb
|
|
195
227
|
- spec/spec_helper.rb
|
|
196
228
|
- spec/valid_mime_type_spec.rb
|
data/Gemfile.lock
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
stitches (3.5.0)
|
|
5
|
-
apitome
|
|
6
|
-
pg
|
|
7
|
-
rails
|
|
8
|
-
rspec (>= 3)
|
|
9
|
-
rspec-rails (~> 3)
|
|
10
|
-
|
|
11
|
-
GEM
|
|
12
|
-
remote: https://www.rubygems.org/
|
|
13
|
-
specs:
|
|
14
|
-
actioncable (5.1.3)
|
|
15
|
-
actionpack (= 5.1.3)
|
|
16
|
-
nio4r (~> 2.0)
|
|
17
|
-
websocket-driver (~> 0.6.1)
|
|
18
|
-
actionmailer (5.1.3)
|
|
19
|
-
actionpack (= 5.1.3)
|
|
20
|
-
actionview (= 5.1.3)
|
|
21
|
-
activejob (= 5.1.3)
|
|
22
|
-
mail (~> 2.5, >= 2.5.4)
|
|
23
|
-
rails-dom-testing (~> 2.0)
|
|
24
|
-
actionpack (5.1.3)
|
|
25
|
-
actionview (= 5.1.3)
|
|
26
|
-
activesupport (= 5.1.3)
|
|
27
|
-
rack (~> 2.0)
|
|
28
|
-
rack-test (~> 0.6.3)
|
|
29
|
-
rails-dom-testing (~> 2.0)
|
|
30
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
|
31
|
-
actionview (5.1.3)
|
|
32
|
-
activesupport (= 5.1.3)
|
|
33
|
-
builder (~> 3.1)
|
|
34
|
-
erubi (~> 1.4)
|
|
35
|
-
rails-dom-testing (~> 2.0)
|
|
36
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
|
37
|
-
activejob (5.1.3)
|
|
38
|
-
activesupport (= 5.1.3)
|
|
39
|
-
globalid (>= 0.3.6)
|
|
40
|
-
activemodel (5.1.3)
|
|
41
|
-
activesupport (= 5.1.3)
|
|
42
|
-
activerecord (5.1.3)
|
|
43
|
-
activemodel (= 5.1.3)
|
|
44
|
-
activesupport (= 5.1.3)
|
|
45
|
-
arel (~> 8.0)
|
|
46
|
-
activesupport (5.1.3)
|
|
47
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
48
|
-
i18n (~> 0.7)
|
|
49
|
-
minitest (~> 5.1)
|
|
50
|
-
tzinfo (~> 1.1)
|
|
51
|
-
apitome (0.1.0)
|
|
52
|
-
kramdown
|
|
53
|
-
railties
|
|
54
|
-
rspec_api_documentation
|
|
55
|
-
arel (8.0.0)
|
|
56
|
-
builder (3.2.3)
|
|
57
|
-
concurrent-ruby (1.0.5)
|
|
58
|
-
diff-lcs (1.3)
|
|
59
|
-
erubi (1.6.1)
|
|
60
|
-
globalid (0.4.0)
|
|
61
|
-
activesupport (>= 4.2.0)
|
|
62
|
-
i18n (0.8.6)
|
|
63
|
-
kramdown (1.14.0)
|
|
64
|
-
loofah (2.0.3)
|
|
65
|
-
nokogiri (>= 1.5.9)
|
|
66
|
-
mail (2.6.6)
|
|
67
|
-
mime-types (>= 1.16, < 4)
|
|
68
|
-
method_source (0.8.2)
|
|
69
|
-
mime-types (3.1)
|
|
70
|
-
mime-types-data (~> 3.2015)
|
|
71
|
-
mime-types-data (3.2016.0521)
|
|
72
|
-
mini_portile2 (2.2.0)
|
|
73
|
-
minitest (5.10.3)
|
|
74
|
-
mustache (1.0.5)
|
|
75
|
-
nio4r (2.1.0)
|
|
76
|
-
nokogiri (1.8.0)
|
|
77
|
-
mini_portile2 (~> 2.2.0)
|
|
78
|
-
pg (0.21.0)
|
|
79
|
-
rack (2.0.3)
|
|
80
|
-
rack-test (0.6.3)
|
|
81
|
-
rack (>= 1.0)
|
|
82
|
-
rails (5.1.3)
|
|
83
|
-
actioncable (= 5.1.3)
|
|
84
|
-
actionmailer (= 5.1.3)
|
|
85
|
-
actionpack (= 5.1.3)
|
|
86
|
-
actionview (= 5.1.3)
|
|
87
|
-
activejob (= 5.1.3)
|
|
88
|
-
activemodel (= 5.1.3)
|
|
89
|
-
activerecord (= 5.1.3)
|
|
90
|
-
activesupport (= 5.1.3)
|
|
91
|
-
bundler (>= 1.3.0)
|
|
92
|
-
railties (= 5.1.3)
|
|
93
|
-
sprockets-rails (>= 2.0.0)
|
|
94
|
-
rails-dom-testing (2.0.3)
|
|
95
|
-
activesupport (>= 4.2.0)
|
|
96
|
-
nokogiri (>= 1.6)
|
|
97
|
-
rails-html-sanitizer (1.0.3)
|
|
98
|
-
loofah (~> 2.0)
|
|
99
|
-
railties (5.1.3)
|
|
100
|
-
actionpack (= 5.1.3)
|
|
101
|
-
activesupport (= 5.1.3)
|
|
102
|
-
method_source
|
|
103
|
-
rake (>= 0.8.7)
|
|
104
|
-
thor (>= 0.18.1, < 2.0)
|
|
105
|
-
rake (12.0.0)
|
|
106
|
-
rspec (3.6.0)
|
|
107
|
-
rspec-core (~> 3.6.0)
|
|
108
|
-
rspec-expectations (~> 3.6.0)
|
|
109
|
-
rspec-mocks (~> 3.6.0)
|
|
110
|
-
rspec-core (3.6.0)
|
|
111
|
-
rspec-support (~> 3.6.0)
|
|
112
|
-
rspec-expectations (3.6.0)
|
|
113
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
114
|
-
rspec-support (~> 3.6.0)
|
|
115
|
-
rspec-mocks (3.6.0)
|
|
116
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
117
|
-
rspec-support (~> 3.6.0)
|
|
118
|
-
rspec-rails (3.6.0)
|
|
119
|
-
actionpack (>= 3.0)
|
|
120
|
-
activesupport (>= 3.0)
|
|
121
|
-
railties (>= 3.0)
|
|
122
|
-
rspec-core (~> 3.6.0)
|
|
123
|
-
rspec-expectations (~> 3.6.0)
|
|
124
|
-
rspec-mocks (~> 3.6.0)
|
|
125
|
-
rspec-support (~> 3.6.0)
|
|
126
|
-
rspec-support (3.6.0)
|
|
127
|
-
rspec_api_documentation (5.0.0)
|
|
128
|
-
activesupport (>= 3.0.0)
|
|
129
|
-
mustache (~> 1.0, >= 0.99.4)
|
|
130
|
-
rspec (~> 3.0)
|
|
131
|
-
sprockets (3.7.1)
|
|
132
|
-
concurrent-ruby (~> 1.0)
|
|
133
|
-
rack (> 1, < 3)
|
|
134
|
-
sprockets-rails (3.2.0)
|
|
135
|
-
actionpack (>= 4.0)
|
|
136
|
-
activesupport (>= 4.0)
|
|
137
|
-
sprockets (>= 3.0.0)
|
|
138
|
-
thor (0.20.0)
|
|
139
|
-
thread_safe (0.3.6)
|
|
140
|
-
tzinfo (1.2.3)
|
|
141
|
-
thread_safe (~> 0.1)
|
|
142
|
-
websocket-driver (0.6.5)
|
|
143
|
-
websocket-extensions (>= 0.1.0)
|
|
144
|
-
websocket-extensions (0.1.2)
|
|
145
|
-
|
|
146
|
-
PLATFORMS
|
|
147
|
-
ruby
|
|
148
|
-
|
|
149
|
-
DEPENDENCIES
|
|
150
|
-
rake
|
|
151
|
-
stitches!
|
|
152
|
-
|
|
153
|
-
BUNDLED WITH
|
|
154
|
-
1.15.3
|