potassium 5.2.1 → 6.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +84 -0
- data/.gitignore +2 -1
- data/.node-version +1 -0
- data/.rubocop.yml +530 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +91 -0
- data/README.md +41 -47
- data/docs/DSL.md +5 -5
- data/lib/potassium/assets/.buildpacks +0 -1
- data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
- data/lib/potassium/assets/.eslintrc.json +352 -0
- data/lib/potassium/assets/.github/pull_request_template.md +9 -0
- data/lib/potassium/assets/.pryrc +1 -1
- data/lib/potassium/assets/.rubocop.yml +528 -0
- data/lib/potassium/assets/.stylelintrc.json +46 -0
- data/lib/potassium/assets/Dockerfile.ci +1 -1
- data/lib/potassium/assets/Makefile.erb +21 -32
- data/lib/potassium/assets/Procfile +1 -0
- data/lib/potassium/assets/README.yml +58 -11
- data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
- data/lib/potassium/assets/active_admin/admin_application.js +14 -0
- data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
- data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
- data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
- data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
- data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
- data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
- data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
- data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
- data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
- data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
- data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
- data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
- data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
- data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
- data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
- data/lib/potassium/assets/app/uploaders/base_uploader.rb +11 -0
- data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
- data/lib/potassium/assets/app/views/shared/_gtm_body.html.erb +4 -0
- data/lib/potassium/assets/app/views/shared/_gtm_head.html.erb +7 -0
- data/lib/potassium/assets/bin/cibuild.erb +24 -7
- data/lib/potassium/assets/bin/release +9 -0
- data/lib/potassium/assets/bin/setup.erb +1 -1
- data/lib/potassium/assets/config/database_mysql.yml.erb +2 -2
- data/lib/potassium/assets/config/database_postgresql.yml.erb +2 -2
- data/lib/potassium/assets/config/graphql_playground.rb +20 -0
- data/lib/potassium/assets/config/puma.rb +1 -1
- data/lib/potassium/assets/config/shrine.rb +36 -0
- data/lib/potassium/assets/docker-compose.ci.yml +2 -1
- data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +34 -33
- data/lib/potassium/assets/package.json +4 -1
- data/lib/potassium/assets/redis.yml +1 -2
- data/lib/potassium/assets/testing/rails_helper.rb +4 -2
- data/lib/potassium/cli/commands/create.rb +12 -19
- data/lib/potassium/cli_options.rb +77 -26
- data/lib/potassium/helpers/gem-helpers.rb +1 -1
- data/lib/potassium/helpers/template-helpers.rb +4 -0
- data/lib/potassium/newest_version_ensurer.rb +19 -36
- data/lib/potassium/node_version_ensurer.rb +30 -0
- data/lib/potassium/recipes/admin.rb +3 -3
- data/lib/potassium/recipes/annotate.rb +1 -1
- data/lib/potassium/recipes/api.rb +93 -21
- data/lib/potassium/recipes/background_processor.rb +66 -19
- data/lib/potassium/recipes/ci.rb +6 -4
- data/lib/potassium/recipes/data_migrate.rb +44 -0
- data/lib/potassium/recipes/database.rb +4 -0
- data/lib/potassium/recipes/database_container.rb +7 -5
- data/lib/potassium/recipes/draper.rb +1 -10
- data/lib/potassium/recipes/file_storage.rb +66 -0
- data/lib/potassium/recipes/front_end.rb +219 -9
- data/lib/potassium/recipes/github.rb +93 -15
- data/lib/potassium/recipes/google_tag_manager.rb +90 -0
- data/lib/potassium/recipes/heroku.rb +44 -30
- data/lib/potassium/recipes/mailer.rb +27 -4
- data/lib/potassium/recipes/node.rb +21 -0
- data/lib/potassium/recipes/rack_cors.rb +18 -15
- data/lib/potassium/recipes/schedule.rb +17 -2
- data/lib/potassium/recipes/style.rb +21 -3
- data/lib/potassium/recipes/vue_admin.rb +124 -0
- data/lib/potassium/templates/application.rb +9 -7
- data/lib/potassium/version.rb +6 -4
- data/potassium.gemspec +11 -6
- data/spec/features/api_spec.rb +25 -0
- data/spec/features/background_processor_spec.rb +19 -6
- data/spec/features/data_migrate_spec.rb +14 -0
- data/spec/features/database_container_spec.rb +2 -5
- data/spec/features/draper_spec.rb +1 -6
- data/spec/features/file_storage_spec.rb +75 -0
- data/spec/features/front_end_spec.rb +88 -0
- data/spec/features/github_spec.rb +53 -8
- data/spec/features/google_tag_manager_spec.rb +59 -0
- data/spec/features/graphql_spec.rb +71 -0
- data/spec/features/heroku_spec.rb +8 -5
- data/spec/features/mailer_spec.rb +58 -0
- data/spec/features/new_project_spec.rb +6 -14
- data/spec/features/node_spec.rb +28 -0
- data/spec/features/power_types_spec.rb +5 -16
- data/spec/features/schedule_spec.rb +11 -4
- data/spec/features/vue_admin_spec.rb +47 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/fake_octokit.rb +31 -0
- data/spec/support/potassium_test_helpers.rb +26 -9
- data/tmp/.keep +0 -0
- metadata +157 -48
- data/circle.yml +0 -12
- data/lib/potassium/assets/.circleci/config.yml +0 -20
- data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
- data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
- data/lib/potassium/assets/api/api_error_concern.rb +0 -32
- data/lib/potassium/assets/api/base_controller.rb +0 -9
- data/lib/potassium/assets/api/draper_responder.rb +0 -62
- data/lib/potassium/assets/api/responder.rb +0 -41
- data/lib/potassium/assets/aws.rb +0 -1
- data/lib/potassium/assets/sidekiq_scheduler.yml +0 -9
- data/lib/potassium/assets/testing/paperclip.rb +0 -59
- data/lib/potassium/recipes/active_storage.rb +0 -40
- data/lib/potassium/recipes/angular_admin.rb +0 -56
- data/lib/potassium/recipes/aws_sdk.rb +0 -7
- data/lib/potassium/recipes/paperclip.rb +0 -47
- data/spec/features/active_storage_spec.rb +0 -30
- data/spec/features/front_end.rb +0 -30
|
@@ -1,29 +1,107 @@
|
|
|
1
|
+
require 'octokit'
|
|
2
|
+
|
|
1
3
|
class Recipes::Github < Rails::AppBuilder
|
|
2
4
|
def ask
|
|
3
|
-
repo_name = "platanus/#{get(:dasherized_app_name)}"
|
|
4
5
|
github_repo_create = answer(:github) do
|
|
5
|
-
|
|
6
|
-
"for this project?"
|
|
7
|
-
Ask.confirm(q)
|
|
8
|
-
end
|
|
9
|
-
if github_repo_create
|
|
10
|
-
github_repo_private = answer(:"github-private") do
|
|
11
|
-
Ask.confirm("Should the repository be private?")
|
|
12
|
-
end
|
|
6
|
+
Ask.confirm('Do you want to create a Github repository?')
|
|
13
7
|
end
|
|
14
|
-
set(:github_repo_name, repo_name)
|
|
15
8
|
set(:github_repo, github_repo_create)
|
|
16
|
-
|
|
9
|
+
setup_repo if github_repo_create
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def setup_repo
|
|
13
|
+
setup_repo_private
|
|
14
|
+
setup_repo_org
|
|
15
|
+
setup_repo_name
|
|
16
|
+
set(:github_access_token, get_access_token)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def create
|
|
20
|
-
|
|
20
|
+
return unless selected?(:github_repo)
|
|
21
|
+
|
|
22
|
+
create_github_repo
|
|
23
|
+
copy_file '../assets/.github/pull_request_template.md', '.github/pull_request_template.md'
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
private
|
|
24
27
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
def setup_repo_private
|
|
29
|
+
repo_private = answer(:github_private) do
|
|
30
|
+
Ask.confirm('Should the repository be private?')
|
|
31
|
+
end
|
|
32
|
+
set(:github_repo_private, repo_private)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup_repo_org
|
|
36
|
+
has_organization = answer(:github_has_org) do
|
|
37
|
+
Ask.confirm('Is this repo for a Github organization?')
|
|
38
|
+
end
|
|
39
|
+
set(:github_has_org, has_organization)
|
|
40
|
+
if has_organization
|
|
41
|
+
repo_organization = answer(:github_org) do
|
|
42
|
+
Ask.input('What is the organization for this repository?', default: 'platanus')
|
|
43
|
+
end
|
|
44
|
+
set(:github_org, repo_organization)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def setup_repo_name
|
|
49
|
+
repo_name = answer(:github_name) do
|
|
50
|
+
Ask.input('What is the name for this repository?', default: get(:dasherized_app_name))
|
|
51
|
+
end
|
|
52
|
+
set(:github_repo_name, repo_name)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def create_github_repo
|
|
56
|
+
options = { private: get(:github_repo_private) }
|
|
57
|
+
options[:organization] = get(:github_org) if get(:github_has_org)
|
|
58
|
+
repo_name = get(:github_repo_name)
|
|
59
|
+
|
|
60
|
+
is_retry = false
|
|
61
|
+
begin
|
|
62
|
+
github_client(is_retry).create_repository(repo_name, options)
|
|
63
|
+
rescue Octokit::Unauthorized
|
|
64
|
+
is_retry = true
|
|
65
|
+
retry if retry_create_repo
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def retry_create_repo
|
|
70
|
+
puts "Bad credentials, information on Personal Access Tokens here:"
|
|
71
|
+
puts "https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
|
|
72
|
+
puts "Make sure to give repo access to the personal access token"
|
|
73
|
+
Ask.confirm("Do you want to retry?")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def github_client(is_retry = false)
|
|
77
|
+
access_token = is_retry ? set_access_token : get(:github_access_token)
|
|
78
|
+
octokit_client.new(access_token: access_token)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def octokit_client
|
|
82
|
+
if answer(:test)
|
|
83
|
+
require_relative '../../../spec/support/fake_octokit'
|
|
84
|
+
FakeOctokit
|
|
85
|
+
else
|
|
86
|
+
Octokit::Client
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def get_access_token
|
|
91
|
+
return File.open(config_filename, 'r').read if File.exists?(config_filename)
|
|
92
|
+
|
|
93
|
+
set_access_token
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def set_access_token
|
|
97
|
+
access_token = answer(:github_access_token) do
|
|
98
|
+
Ask.input('Enter a GitHub personal access token', password: true)
|
|
99
|
+
end
|
|
100
|
+
File.open(config_filename, 'w') { |f| f.write(access_token) }
|
|
101
|
+
access_token
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def config_filename
|
|
105
|
+
@config_filename ||= File.expand_path('~/.potassium')
|
|
28
106
|
end
|
|
29
107
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
class Recipes::GoogleTagManager < Rails::AppBuilder
|
|
2
|
+
def ask
|
|
3
|
+
use_google_tag_manager = answer(:google_tag_manager) do
|
|
4
|
+
Ask.confirm 'Do you want to use Google Tag Manager?'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
set(:google_tag_manager, use_google_tag_manager)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def create
|
|
11
|
+
install if selected?(:google_tag_manager)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def install
|
|
15
|
+
add_google_tag_manager
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add_google_tag_manager
|
|
19
|
+
copy_tag_manager_files
|
|
20
|
+
append_to_file '.env.development', "GTM_CONTAINER_ID=\n"
|
|
21
|
+
include_tag_manager
|
|
22
|
+
add_content_security_policy
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_content_security_policy
|
|
26
|
+
inject_into_file(
|
|
27
|
+
'config/initializers/content_security_policy.rb',
|
|
28
|
+
content_security_policy_code
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def copy_tag_manager_files
|
|
33
|
+
copy_file(
|
|
34
|
+
'../assets/app/views/shared/_gtm_head.html.erb',
|
|
35
|
+
'app/views/shared/_gtm_head.html.erb',
|
|
36
|
+
force: true
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
copy_file(
|
|
40
|
+
'../assets/app/views/shared/_gtm_body.html.erb',
|
|
41
|
+
'app/views/shared/_gtm_body.html.erb',
|
|
42
|
+
force: true
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def include_tag_manager
|
|
47
|
+
inject_into_file(
|
|
48
|
+
'app/views/layouts/application.html.erb',
|
|
49
|
+
render_string('shared/gtm_head'),
|
|
50
|
+
before: '</head>'
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
inject_into_file(
|
|
54
|
+
'app/views/layouts/application.html.erb',
|
|
55
|
+
render_string('shared/gtm_body'),
|
|
56
|
+
after: '<body>'
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def render_string(file_path)
|
|
63
|
+
" <%if Rails.env.production? %>
|
|
64
|
+
<%= render \"#{file_path}\" %>
|
|
65
|
+
<% end %>\n "
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def content_security_policy_code
|
|
69
|
+
<<~HERE
|
|
70
|
+
Rails.application.config.content_security_policy do |policy|
|
|
71
|
+
if Rails.env.development?
|
|
72
|
+
policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035'
|
|
73
|
+
policy.script_src :self, :https, :unsafe_eval
|
|
74
|
+
else
|
|
75
|
+
policy.script_src :self, :https
|
|
76
|
+
# google tag manager requires to enable unsafe inline:
|
|
77
|
+
# https://developers.google.com/tag-manager/web/csp
|
|
78
|
+
policy.connect_src :self, :https, 'https://www.google-analytics.com'
|
|
79
|
+
policy.script_src :self,
|
|
80
|
+
:https,
|
|
81
|
+
:unsafe_inline,
|
|
82
|
+
'https://www.googletagmanager.com',
|
|
83
|
+
'https://www.google-analytics.com',
|
|
84
|
+
'https://ssl.google-analytics.com'
|
|
85
|
+
policy.img_src :self, :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
HERE
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
class Recipes::Heroku < Rails::AppBuilder
|
|
2
2
|
NAME_PREFIX = 'pl'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def initialize(args)
|
|
7
|
-
super(args)
|
|
8
|
-
set(:heroku_app_name_staging, app_name_for('staging'))
|
|
9
|
-
set(:heroku_app_name_production, app_name_for('production'))
|
|
10
|
-
end
|
|
3
|
+
ENVIRONMENTS = ['staging', 'production']
|
|
4
|
+
HEROKU_NAMES_MAX_CHARS = 30
|
|
11
5
|
|
|
12
6
|
def ask
|
|
13
7
|
heroku = answer(:heroku) do
|
|
@@ -16,6 +10,8 @@ class Recipes::Heroku < Rails::AppBuilder
|
|
|
16
10
|
|
|
17
11
|
if heroku
|
|
18
12
|
set(:heroku, heroku)
|
|
13
|
+
|
|
14
|
+
ENVIRONMENTS.each { |environment| set_app_name_for(environment) }
|
|
19
15
|
end
|
|
20
16
|
end
|
|
21
17
|
|
|
@@ -41,35 +37,40 @@ class Recipes::Heroku < Rails::AppBuilder
|
|
|
41
37
|
|
|
42
38
|
copy_file '../assets/Procfile', 'Procfile'
|
|
43
39
|
copy_file '../assets/.buildpacks', '.buildpacks'
|
|
40
|
+
copy_file '../assets/bin/release', 'bin/release'
|
|
41
|
+
run 'chmod a+x bin/release'
|
|
44
42
|
|
|
45
43
|
template "../assets/bin/setup_heroku.erb", "bin/setup_heroku", force: true
|
|
46
44
|
run "chmod a+x bin/setup_heroku"
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
%w(staging production).each do |environment|
|
|
50
|
-
create_app_on_heroku(environment)
|
|
51
|
-
end
|
|
52
|
-
puts "Remember to connect the github repository to the new pipeline"
|
|
53
|
-
open_pipeline_command = "\e[33mheroku pipelines:open #{heroku_pipeline_name}\e[0m"
|
|
54
|
-
puts "run #{open_pipeline_command} to open the dashboard"
|
|
55
|
-
else
|
|
56
|
-
puts "You are not logged in into heroku"
|
|
57
|
-
login_command = "\e[33mheroku login\e[0m"
|
|
58
|
-
puts "Run #{login_command} and enter your credentials"
|
|
59
|
-
puts "You can install the heroku recipe again create the app in heroku"
|
|
60
|
-
install_command = "\e[33mpostassium install heroku --force\e[0m"
|
|
61
|
-
puts "Just run #{install_command}"
|
|
62
|
-
end
|
|
46
|
+
logged_in? ? create_apps : puts_not_logged_in_msg
|
|
63
47
|
|
|
64
48
|
add_readme_header :deployment
|
|
65
49
|
end
|
|
66
50
|
|
|
51
|
+
def create_apps
|
|
52
|
+
ENVIRONMENTS.each { |environment| create_app_on_heroku(environment) }
|
|
53
|
+
puts "Remember to connect the github repository to the new pipeline"
|
|
54
|
+
open_pipeline_command = "\e[33mheroku pipelines:open #{heroku_pipeline_name}\e[0m"
|
|
55
|
+
puts "run #{open_pipeline_command} to open the dashboard"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def puts_not_logged_in_msg
|
|
59
|
+
puts "You are not logged in into heroku"
|
|
60
|
+
login_command = "\e[33mheroku login\e[0m"
|
|
61
|
+
puts "Run #{login_command} and enter your credentials"
|
|
62
|
+
puts "You can install the heroku recipe again to create the app in heroku"
|
|
63
|
+
install_command = "\e[33mpostassium install heroku --force\e[0m"
|
|
64
|
+
puts "Just run #{install_command}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
67
|
def heroku_pipeline_name
|
|
68
|
-
app_name.dasherize
|
|
68
|
+
@heroku_pipeline_name ||= valid_heroku_name(app_name.dasherize, 'pipeline', false)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def
|
|
72
|
-
"#{NAME_PREFIX}-#{app_name.dasherize}-#{environment}"
|
|
71
|
+
def set_app_name_for(environment)
|
|
72
|
+
default_name = "#{NAME_PREFIX}-#{app_name.dasherize}-#{environment}"
|
|
73
|
+
set("heroku_app_name_#{environment}".to_sym, valid_heroku_name(default_name, environment))
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
def logged_in?
|
|
@@ -82,13 +83,12 @@ class Recipes::Heroku < Rails::AppBuilder
|
|
|
82
83
|
|
|
83
84
|
def create_app_on_heroku(environment)
|
|
84
85
|
rack_env = "RACK_ENV=production"
|
|
85
|
-
staged_app_name =
|
|
86
|
+
staged_app_name = get("heroku_app_name_#{environment}".to_sym)
|
|
86
87
|
|
|
87
88
|
run_toolbelt_command "create #{staged_app_name} --remote #{environment}"
|
|
88
89
|
run_toolbelt_command "labs:enable runtime-dyno-metadata", staged_app_name
|
|
89
90
|
run_toolbelt_command "config:add HEROKU_APP_NAME=#{staged_app_name}", staged_app_name
|
|
90
91
|
run_toolbelt_command "config:add #{rack_env}", staged_app_name
|
|
91
|
-
run_toolbelt_command "config:add DEPLOY_TASKS=db:migrate", staged_app_name
|
|
92
92
|
|
|
93
93
|
set_rails_secrets(environment)
|
|
94
94
|
set_app_multi_buildpack(environment)
|
|
@@ -98,14 +98,14 @@ class Recipes::Heroku < Rails::AppBuilder
|
|
|
98
98
|
def set_rails_secrets(environment)
|
|
99
99
|
run_toolbelt_command(
|
|
100
100
|
"config:add SECRET_KEY_BASE=#{generate_secret}",
|
|
101
|
-
|
|
101
|
+
get("heroku_app_name_#{environment}".to_sym)
|
|
102
102
|
)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
def set_app_multi_buildpack(environment)
|
|
106
106
|
run_toolbelt_command(
|
|
107
107
|
"buildpacks:set https://github.com/heroku/heroku-buildpack-multi.git",
|
|
108
|
-
|
|
108
|
+
get("heroku_app_name_#{environment}".to_sym)
|
|
109
109
|
)
|
|
110
110
|
end
|
|
111
111
|
|
|
@@ -132,4 +132,18 @@ class Recipes::Heroku < Rails::AppBuilder
|
|
|
132
132
|
`heroku #{command} --app #{app_env_name}`
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
|
+
|
|
136
|
+
def valid_heroku_name(name, element, force_suffix = true)
|
|
137
|
+
suffix = "-#{element}"
|
|
138
|
+
while name.length > HEROKU_NAMES_MAX_CHARS
|
|
139
|
+
puts "Heroku names must be shorter than #{HEROKU_NAMES_MAX_CHARS} chars."
|
|
140
|
+
if force_suffix
|
|
141
|
+
puts "Potassium uses the heroku-stage gem, because of that '#{suffix}' will be "\
|
|
142
|
+
"added to your app name. The suffix, #{suffix}, counts towards the app name length."
|
|
143
|
+
end
|
|
144
|
+
name = Ask.input("Please enter a valid name for #{element}:")
|
|
145
|
+
name += suffix if force_suffix && !name.end_with?(suffix)
|
|
146
|
+
end
|
|
147
|
+
name
|
|
148
|
+
end
|
|
135
149
|
end
|
|
@@ -24,8 +24,7 @@ class Recipes::Mailer < Rails::AppBuilder
|
|
|
24
24
|
dependencies(email_service)
|
|
25
25
|
config(email_service)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
background_processor.add_sidekiq unless background_processor.installed?
|
|
27
|
+
ensure_sidekiq_install_and_add_mailers_queue
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def install
|
|
@@ -33,6 +32,10 @@ class Recipes::Mailer < Rails::AppBuilder
|
|
|
33
32
|
create
|
|
34
33
|
end
|
|
35
34
|
|
|
35
|
+
def add_mailer_queue
|
|
36
|
+
insert_into_file "config/sidekiq.yml", " - mailers", after: "- default\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
36
39
|
private
|
|
37
40
|
|
|
38
41
|
def email_services(service_name)
|
|
@@ -68,7 +71,7 @@ class Recipes::Mailer < Rails::AppBuilder
|
|
|
68
71
|
|
|
69
72
|
mailer_config =
|
|
70
73
|
<<~RUBY
|
|
71
|
-
require Rails.root.join("config
|
|
74
|
+
require Rails.root.join("config", "mailer")
|
|
72
75
|
RUBY
|
|
73
76
|
|
|
74
77
|
prepend_file "config/environments/production.rb", mailer_config
|
|
@@ -81,15 +84,35 @@ class Recipes::Mailer < Rails::AppBuilder
|
|
|
81
84
|
append_to_file '.env.development', "SENDGRID_API_KEY=\n"
|
|
82
85
|
sendgrid_settings = <<~RUBY
|
|
83
86
|
Rails.application.config.action_mailer.sendgrid_settings = {
|
|
84
|
-
api_key: ENV['
|
|
87
|
+
api_key: ENV['SENDGRID_API_KEY']
|
|
85
88
|
}
|
|
86
89
|
RUBY
|
|
87
90
|
inject_into_file 'config/mailer.rb', sendgrid_settings,
|
|
88
91
|
after: "Rails.application.config.action_mailer.delivery_method = :sendgrid\n"
|
|
92
|
+
sendgrid_dev_settings = <<~RUBY
|
|
93
|
+
Rails.application.config.action_mailer.sendgrid_dev_settings = {
|
|
94
|
+
api_key: ENV['SENDGRID_API_KEY']
|
|
95
|
+
}
|
|
96
|
+
RUBY
|
|
97
|
+
application sendgrid_dev_settings, env: "development"
|
|
98
|
+
application "config.action_mailer.delivery_method = :sendgrid_dev", env: "development"
|
|
89
99
|
end
|
|
90
100
|
|
|
91
101
|
def aws_ses
|
|
92
102
|
gather_gems(:development) { gather_gem("letter_opener") }
|
|
93
103
|
application "config.action_mailer.delivery_method = :letter_opener", env: "development"
|
|
94
104
|
end
|
|
105
|
+
|
|
106
|
+
def ensure_sidekiq_install_and_add_mailers_queue
|
|
107
|
+
background_processor_recipe = load_recipe(:background_processor)
|
|
108
|
+
background_processor_answer = get(:background_processor)
|
|
109
|
+
|
|
110
|
+
if background_processor_recipe.installed?
|
|
111
|
+
add_mailer_queue
|
|
112
|
+
else
|
|
113
|
+
recipe = self
|
|
114
|
+
after(:install_sidekiq) { recipe.add_mailer_queue }
|
|
115
|
+
background_processor_recipe.add_sidekiq unless background_processor_answer
|
|
116
|
+
end
|
|
117
|
+
end
|
|
95
118
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'semantic'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
class Recipes::Node < Rails::AppBuilder
|
|
6
|
+
def create
|
|
7
|
+
info "Using node version LTS #{version}"
|
|
8
|
+
create_file '.node-version', version, force: true
|
|
9
|
+
json_file = File.read(Pathname.new("package.json"))
|
|
10
|
+
js_package = JSON.parse(json_file)
|
|
11
|
+
js_package["engines"] = { "node" => "#{version}.x" }
|
|
12
|
+
json_string = JSON.pretty_generate(js_package)
|
|
13
|
+
create_file 'package.json', json_string, force: true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def version
|
|
19
|
+
Potassium::NODE_VERSION
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -4,23 +4,26 @@ class Recipes::RackCors < Rails::AppBuilder
|
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
def create
|
|
7
|
-
gather_gem('rack-cors', '~>
|
|
7
|
+
gather_gem('rack-cors', '~> 1.1')
|
|
8
|
+
recipe = self
|
|
8
9
|
after(:gem_install) do
|
|
9
|
-
rack_cors_config
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
allow do
|
|
13
|
-
origins '*'
|
|
14
|
-
resource '*',
|
|
15
|
-
headers: :any,
|
|
16
|
-
expose: ['X-Page', 'X-PageTotal'],
|
|
17
|
-
methods: [:get, :post, :delete, :put, :options]
|
|
18
|
-
end
|
|
19
|
-
end
|
|
10
|
+
application recipe.rack_cors_config
|
|
11
|
+
end
|
|
12
|
+
end
|
|
20
13
|
|
|
21
|
-
|
|
14
|
+
def rack_cors_config
|
|
15
|
+
<<~RUBY
|
|
16
|
+
config.middleware.insert_before 0, Rack::Cors do
|
|
17
|
+
allow do
|
|
18
|
+
origins '*'
|
|
19
|
+
resource '/public/*', headers: :any, methods: :get
|
|
20
|
+
resource '/api/*',
|
|
21
|
+
headers: :any,
|
|
22
|
+
expose: ['X-Page', 'X-PageTotal'],
|
|
23
|
+
methods: [:get, :post, :patch, :put, :delete, :options]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
end
|
|
27
|
+
RUBY
|
|
25
28
|
end
|
|
26
29
|
end
|