hoboken 0.0.1 → 0.9.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.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +7 -0
- data/.github/workflows/ruby.yml +28 -0
- data/.rubocop.yml +33 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/IDEAS.md +57 -0
- data/LICENSE.txt +1 -1
- data/README.md +21 -10
- data/Rakefile +14 -6
- data/bin/hoboken +2 -1
- data/hoboken.gemspec +53 -16
- data/lib/hoboken.rb +110 -23
- data/lib/hoboken/actions.rb +10 -6
- data/lib/hoboken/add_ons/github_action.rb +14 -0
- data/lib/hoboken/add_ons/heroku.rb +8 -23
- data/lib/hoboken/add_ons/internationalization.rb +10 -6
- data/lib/hoboken/add_ons/metrics.rb +39 -14
- data/lib/hoboken/add_ons/omniauth.rb +114 -47
- data/lib/hoboken/add_ons/rubocop.rb +40 -0
- data/lib/hoboken/add_ons/sequel.rb +76 -47
- data/lib/hoboken/add_ons/sprockets.rb +67 -65
- data/lib/hoboken/add_ons/travis.rb +6 -2
- data/lib/hoboken/add_ons/twbs.rb +80 -0
- data/lib/hoboken/generate.rb +112 -38
- data/lib/hoboken/templates/Gemfile.erb.tt +33 -10
- data/lib/hoboken/templates/README.md.tt +105 -35
- data/lib/hoboken/templates/Rakefile.tt +10 -22
- data/lib/hoboken/templates/classic.rb.tt +35 -8
- data/lib/hoboken/templates/config.ru.tt +5 -3
- data/lib/hoboken/templates/console.sh +5 -0
- data/lib/hoboken/templates/db.rb.tt +24 -0
- data/lib/hoboken/templates/github_action.tt +28 -0
- data/lib/hoboken/templates/gitignore +8 -1
- data/lib/hoboken/templates/metrics.rake.tt +10 -9
- data/lib/hoboken/templates/modular.rb.tt +40 -11
- data/lib/hoboken/templates/puma.rb.tt +21 -0
- data/lib/hoboken/templates/rspec.rake.tt +5 -0
- data/lib/hoboken/templates/rubocop.yml.tt +31 -0
- data/lib/hoboken/templates/sequel.rake +6 -4
- data/lib/hoboken/templates/server.sh +12 -0
- data/lib/hoboken/templates/setup.sh +7 -0
- data/lib/hoboken/templates/spec/app_spec.rb.tt +15 -0
- data/lib/hoboken/templates/spec/rack_matchers.rb.tt +56 -0
- data/lib/hoboken/templates/spec/spec_helper.rb.tt +41 -0
- data/lib/hoboken/templates/sprockets.rake +13 -7
- data/lib/hoboken/templates/sprockets_chain.rb +7 -3
- data/lib/hoboken/templates/sprockets_helper.rb +14 -10
- data/lib/hoboken/templates/support/rack_helpers.rb.tt +55 -0
- data/lib/hoboken/templates/support/rack_test_assertions.rb.tt +111 -0
- data/lib/hoboken/templates/test/test_helper.rb.tt +38 -27
- data/lib/hoboken/templates/test/unit/app_test.rb.tt +11 -3
- data/lib/hoboken/templates/test_unit.rake.tt +18 -0
- data/lib/hoboken/templates/views/index.erb.tt +10 -3
- data/lib/hoboken/templates/views/layout.erb.tt +4 -1
- data/lib/hoboken/version.rb +3 -1
- data/test/fixtures/Gemfile +3 -3
- data/test/fixtures/Gemfile.pristine +3 -2
- data/test/integration/add_on_test.rb +399 -136
- data/test/integration/generate_test.rb +170 -38
- data/test/test_helper.rb +54 -23
- data/test/unit/hoboken_actions_test.rb +70 -61
- metadata +441 -16
- data/.travis.yml +0 -5
- data/lib/hoboken/templates/test/support/rack_test_assertions.rb.tt +0 -92
data/lib/hoboken/actions.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hoboken
|
4
|
+
# Custom actions.
|
5
|
+
#
|
2
6
|
module Actions
|
3
7
|
def gem(name, opts={})
|
4
|
-
verbose = opts.
|
5
|
-
version = opts.
|
8
|
+
verbose = opts.key?(:verbose) ? opts.delete(:verbose) : true
|
9
|
+
version = opts.key?(:version) ? opts.delete(:version) : nil
|
6
10
|
|
7
|
-
parts = [name
|
8
|
-
parts << "~> #{version}"
|
11
|
+
parts = ["'#{name}'"]
|
12
|
+
parts << "'~> #{version}'" unless version.nil? || version.empty?
|
9
13
|
opts.each { |k, v| parts << "#{k}: #{v.inspect}" }
|
10
|
-
append_file(
|
14
|
+
append_file('Gemfile', "gem #{parts.join(', ')}\n", verbose: verbose)
|
11
15
|
end
|
12
16
|
|
13
17
|
def indent(text, num_spaces)
|
14
|
-
text.gsub(/^/, 1.upto(num_spaces).map { |
|
18
|
+
text.gsub(/^/, 1.upto(num_spaces).map { |_| ' ' }.join)
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hoboken
|
4
|
+
module AddOns
|
5
|
+
# Github action that runs CI task.
|
6
|
+
#
|
7
|
+
class GithubAction < ::Hoboken::Group
|
8
|
+
def add_action_yml_file
|
9
|
+
empty_directory('.github/workflows')
|
10
|
+
template('hoboken/templates/github_action.tt', '.github/workflows/ruby.yml')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,34 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hoboken
|
2
4
|
module AddOns
|
5
|
+
# Heroku deployment support.
|
6
|
+
#
|
3
7
|
class Heroku < ::Hoboken::Group
|
4
|
-
def add_gem
|
5
|
-
gem "foreman", version: "0.63.0", group: :development
|
6
|
-
end
|
7
|
-
|
8
|
-
def procfile
|
9
|
-
create_file("Procfile") do
|
10
|
-
"web: bundle exec thin start -p $PORT -e $RACK_ENV"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
8
|
def slugignore
|
15
|
-
create_file(
|
16
|
-
"
|
9
|
+
create_file('.slugignore') do
|
10
|
+
"spec\ntags\n/test\n/tmp"
|
17
11
|
end
|
18
12
|
end
|
19
13
|
|
20
14
|
def fix_stdout_for_logging
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def replace_server_rake_task
|
25
|
-
gsub_file("Rakefile", /desc.*server.*{rack_env}"\)\nend$/m) do
|
26
|
-
<<TASK
|
27
|
-
desc "Start the development server with Foreman"
|
28
|
-
task :server do
|
29
|
-
exec("foreman start")
|
30
|
-
end
|
31
|
-
TASK
|
15
|
+
insert_into_file('config.ru', after: /# frozen_string_literal: true/) do
|
16
|
+
"\n\n$stdout.sync = true"
|
32
17
|
end
|
33
18
|
end
|
34
19
|
|
@@ -1,19 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hoboken
|
2
4
|
module AddOns
|
5
|
+
# Internationalization support using sinatra-r18n.
|
6
|
+
#
|
3
7
|
class Internationalization < ::Hoboken::Group
|
4
8
|
def add_gem
|
5
|
-
gem
|
6
|
-
insert_into_file(
|
7
|
-
"\nrequire
|
9
|
+
gem 'sinatra-r18n', version: '5.0'
|
10
|
+
insert_into_file('app.rb', after: %r{require 'sinatra('|/base')}) do
|
11
|
+
"\nrequire 'sinatra/r18n'"
|
8
12
|
end
|
9
|
-
insert_into_file(
|
13
|
+
insert_into_file('app.rb', after: /Sinatra::Base/) do
|
10
14
|
"\n register Sinatra::R18n"
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def translations
|
15
|
-
empty_directory(
|
16
|
-
template(
|
19
|
+
empty_directory('i18n')
|
20
|
+
template('hoboken/templates/en.yml.tt', 'i18n/en.yml')
|
17
21
|
end
|
18
22
|
|
19
23
|
def reminders
|
@@ -1,34 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hoboken
|
2
4
|
module AddOns
|
5
|
+
# Add metrics (flog, flay, simplecov).
|
6
|
+
#
|
3
7
|
class Metrics < ::Hoboken::Group
|
4
8
|
def add_gems
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
9
|
+
gem 'flog', version: '4.6', group: :test
|
10
|
+
gem 'flay', version: '2.12', group: :test
|
11
|
+
gem 'simplecov', version: '0.21', require: false, group: :test
|
8
12
|
end
|
9
13
|
|
10
14
|
def copy_task_templates
|
11
|
-
empty_directory(
|
12
|
-
template(
|
15
|
+
empty_directory('tasks')
|
16
|
+
template('hoboken/templates/metrics.rake.tt', 'tasks/metrics.rake')
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
16
|
-
|
17
|
-
<<CODE
|
19
|
+
def simplecov_test_unit
|
20
|
+
return if rspec?
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
insert_into_file 'test/test_helper.rb', before: snippet_location do
|
23
|
+
snippet('test')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def simplecov_rspec
|
28
|
+
return unless rspec?
|
24
29
|
|
25
|
-
|
30
|
+
insert_into_file 'spec/spec_helper.rb', before: snippet_location do
|
31
|
+
snippet('rspec')
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
29
35
|
def reminders
|
30
36
|
say "\nGemfile updated... don't forget to 'bundle install'"
|
31
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def snippet(framework_folder)
|
42
|
+
<<~CODE
|
43
|
+
require 'simplecov'
|
44
|
+
SimpleCov.start do
|
45
|
+
add_filter '/bin/'
|
46
|
+
add_filter '/config/'
|
47
|
+
add_filter '/#{framework_folder}/'
|
48
|
+
coverage_dir 'tmp/coverage'
|
49
|
+
end
|
50
|
+
|
51
|
+
CODE
|
52
|
+
end
|
53
|
+
|
54
|
+
def snippet_location
|
55
|
+
%r{require 'bundler/setup'}
|
56
|
+
end
|
32
57
|
end
|
33
58
|
end
|
34
59
|
end
|
@@ -1,92 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hoboken
|
2
4
|
module AddOns
|
5
|
+
# OmniAuth authentication (allows you to select a provider).
|
6
|
+
#
|
3
7
|
class OmniAuth < ::Hoboken::Group
|
4
8
|
attr_reader :provider
|
5
9
|
|
6
10
|
def add_gem
|
7
|
-
@provider = ask(
|
8
|
-
provider_version = ask(
|
11
|
+
@provider = ask('Specify a provider (i.e. twitter, facebook. etc.): ').downcase
|
12
|
+
provider_version = ask('Specify provider version: ')
|
9
13
|
gem gem_name, version: provider_version
|
10
14
|
end
|
11
15
|
|
12
16
|
def setup_middleware
|
13
|
-
insert_into_file(
|
14
|
-
"\nrequire
|
17
|
+
insert_into_file('app.rb', after: %r{require 'sinatra('|/base')}) do
|
18
|
+
"\nrequire '#{gem_name}'\nrequire 'sinatra/json'\n"
|
15
19
|
end
|
16
20
|
|
17
|
-
snippet =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
CODE
|
21
|
+
snippet = <<~CODE
|
22
|
+
use OmniAuth::Builder do
|
23
|
+
provider :#{provider}, ENV['#{provider.upcase}_KEY'], ENV['#{provider.upcase}_SECRET']
|
24
|
+
end
|
25
|
+
CODE
|
24
26
|
|
25
|
-
|
26
|
-
insert_into_file(
|
27
|
+
indentation = classic? ? 2 : 4
|
28
|
+
insert_into_file('app.rb', after: /use Rack::Session::Cookie.+\n/) do
|
29
|
+
"\n#{indent(snippet, indentation)}\n"
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
29
34
|
def add_routes
|
30
|
-
routes =
|
31
|
-
|
35
|
+
routes = <<~CODE
|
32
36
|
|
33
|
-
get
|
34
|
-
|
35
|
-
end
|
37
|
+
get '/login' do
|
38
|
+
'<a href="/auth/#{provider}">Login</a>'
|
39
|
+
end
|
36
40
|
|
37
|
-
get
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
+
get '/auth/:provider/callback' do
|
42
|
+
# TODO: Insert real authentication logic...
|
43
|
+
json request.env['omniauth.auth']
|
44
|
+
end
|
41
45
|
|
42
|
-
get
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
CODE
|
46
|
+
get '/auth/failure' do
|
47
|
+
# TODO: Insert real error handling logic...
|
48
|
+
halt 401, params[:message]
|
49
|
+
end
|
50
|
+
CODE
|
47
51
|
|
48
|
-
if
|
49
|
-
|
52
|
+
if classic?
|
53
|
+
append_file('app.rb', routes)
|
50
54
|
else
|
51
|
-
|
55
|
+
inject_into_class('app.rb', 'App') { indent(routes, 4) }
|
52
56
|
end
|
53
57
|
end
|
58
|
+
# rubocop:enable Metrics/MethodLength
|
54
59
|
|
60
|
+
# rubocop:disable Metrics/MethodLength
|
55
61
|
def add_tests
|
56
|
-
|
57
|
-
|
62
|
+
return if rspec?
|
63
|
+
|
64
|
+
inject_into_class('test/unit/app_test.rb', 'AppTest') do
|
65
|
+
<<-CODE
|
58
66
|
setup do
|
59
67
|
OmniAuth.config.test_mode = true
|
60
68
|
end
|
61
69
|
|
62
|
-
test
|
63
|
-
get
|
70
|
+
test 'GET /login' do
|
71
|
+
get '/login'
|
64
72
|
assert_equal('<a href="/auth/#{provider}">Login</a>', last_response.body)
|
65
73
|
end
|
66
74
|
|
67
|
-
test
|
75
|
+
test 'GET /auth/#{provider}/callback' do
|
68
76
|
auth_hash = {
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
provider: '#{provider}',
|
78
|
+
uid: '123545',
|
79
|
+
info: {
|
80
|
+
name: 'John Doe'
|
73
81
|
}
|
74
82
|
}
|
75
83
|
|
76
84
|
OmniAuth.config.mock_auth[:#{provider}] = auth_hash
|
77
|
-
get
|
85
|
+
get '/auth/#{provider}/callback'
|
78
86
|
assert_equal(MultiJson.encode(auth_hash), last_response.body)
|
79
87
|
end
|
80
88
|
|
81
|
-
test
|
89
|
+
test 'GET /auth/failure' do
|
82
90
|
OmniAuth.config.mock_auth[:#{provider}] = :invalid_credentials
|
83
|
-
get
|
91
|
+
get '/auth/failure'
|
84
92
|
assert_response :not_authorized
|
85
93
|
end
|
86
94
|
|
87
|
-
|
95
|
+
CODE
|
88
96
|
end
|
89
97
|
end
|
98
|
+
# rubocop:enable Metrics/MethodLength
|
99
|
+
|
100
|
+
# rubocop:disable Metrics/MethodLength
|
101
|
+
def add_specs
|
102
|
+
return unless rspec?
|
103
|
+
|
104
|
+
append_file('spec/app_spec.rb') do
|
105
|
+
<<~CODE
|
106
|
+
|
107
|
+
# rubocop:disable RSpec/DescribeClass
|
108
|
+
RSpec.describe 'omniauth', rack: true do
|
109
|
+
before(:each) { OmniAuth.config.test_mode = true }
|
110
|
+
|
111
|
+
describe 'GET /login' do
|
112
|
+
before(:each) { get '/login' }
|
113
|
+
|
114
|
+
it { expect(last_response).to have_http_status(:ok) }
|
115
|
+
it { expect(last_response).to have_content_type(:html) }
|
116
|
+
|
117
|
+
it 'renders a template with a login link' do
|
118
|
+
#{provider}_link = '<a href="/auth/#{provider}">Login</a>'
|
119
|
+
expect(last_response.body).to include(#{provider}_link)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'GET /auth/#{provider}/callback' do
|
124
|
+
let(:auth_hash) do
|
125
|
+
{
|
126
|
+
provider: '#{provider}',
|
127
|
+
uid: '123545',
|
128
|
+
info: {
|
129
|
+
name: 'John Doe'
|
130
|
+
}
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
before(:each) do
|
135
|
+
OmniAuth.config.mock_auth[:#{provider}] = auth_hash
|
136
|
+
get '/auth/#{provider}/callback'
|
137
|
+
end
|
138
|
+
|
139
|
+
it { expect(last_response).to have_http_status(:ok) }
|
140
|
+
it { expect(last_response).to have_content_type(:json) }
|
141
|
+
|
142
|
+
it 'renders the auth hash result' do
|
143
|
+
expect(last_response.body).to eq(JSON.generate(auth_hash))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'GET /auth/failure' do
|
148
|
+
before(:each) do
|
149
|
+
OmniAuth.config.mock_auth[:#{provider}] = :invalid_credentials
|
150
|
+
get '/auth/failure'
|
151
|
+
end
|
152
|
+
|
153
|
+
it { expect(last_response).to have_http_status(:not_authorized) }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
# rubocop:enable RSpec/DescribeClass
|
157
|
+
CODE
|
158
|
+
end
|
159
|
+
end
|
160
|
+
# rubocop:enable Metrics/MethodLength
|
90
161
|
|
91
162
|
def reminders
|
92
163
|
say "\nGemfile updated... don't forget to 'bundle install'"
|
@@ -97,10 +168,6 @@ CODE
|
|
97
168
|
def gem_name
|
98
169
|
"omniauth-#{provider}"
|
99
170
|
end
|
100
|
-
|
101
|
-
def modular?
|
102
|
-
@modular ||= File.readlines("app.rb").grep(/Sinatra::Base/).any?
|
103
|
-
end
|
104
171
|
end
|
105
172
|
end
|
106
173
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hoboken
|
4
|
+
module AddOns
|
5
|
+
# Basic Rubocop YAML config.
|
6
|
+
#
|
7
|
+
class Rubocop < ::Hoboken::Group
|
8
|
+
def add_gems
|
9
|
+
gem 'rubocop', version: '1.12', group: %i[development test]
|
10
|
+
gem 'rubocop-rake', version: '0.5', group: %i[development test]
|
11
|
+
gem 'rubocop-rspec', version: '2.2', group: %i[development test] if rspec?
|
12
|
+
end
|
13
|
+
|
14
|
+
def rubocop_yml
|
15
|
+
template('hoboken/templates/rubocop.yml.tt', '.rubocop.yml')
|
16
|
+
end
|
17
|
+
|
18
|
+
def rake_task
|
19
|
+
create_file('tasks/rubocop.rake') do
|
20
|
+
<<~TEXT
|
21
|
+
# frozen_string_literal: true
|
22
|
+
|
23
|
+
require 'rubocop/rake_task'
|
24
|
+
|
25
|
+
RuboCop::RakeTask.new
|
26
|
+
TEXT
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ci_task
|
31
|
+
task_list = if rspec?
|
32
|
+
'%w[rspec rubocop]'
|
33
|
+
else
|
34
|
+
"['test:all', 'rubocop']"
|
35
|
+
end
|
36
|
+
gsub_file('Rakefile', /task ci:.*/, "task ci: #{task_list}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|