hoboken 0.0.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|