potassium 1.3.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +1 -1
  5. data/.ruby_style.yml +6 -2
  6. data/CHANGELOG.md +19 -1
  7. data/README.md +79 -74
  8. data/circle.yml +9 -0
  9. data/docs/CONTRIBUTING.md +132 -0
  10. data/docs/{dsl.md → DSL.md} +146 -18
  11. data/lib/potassium/{templates/application/assets → assets}/.bowerrc +0 -0
  12. data/lib/potassium/assets/.buildpacks +3 -0
  13. data/lib/potassium/{templates/application/assets → assets}/.editorconfig +0 -0
  14. data/lib/potassium/assets/.env.example.erb +8 -0
  15. data/lib/potassium/assets/.hound.yml +2 -0
  16. data/lib/potassium/{templates/application/assets → assets}/.pryrc +0 -0
  17. data/lib/potassium/assets/.rubocop.yml +3 -0
  18. data/lib/potassium/assets/.ruby_style.yml +0 -0
  19. data/lib/potassium/assets/Dockerfile.ci +4 -0
  20. data/lib/potassium/assets/Procfile +1 -0
  21. data/lib/potassium/assets/README.md.erb +2 -0
  22. data/lib/potassium/assets/README.yml +83 -0
  23. data/lib/potassium/{templates/application/assets → assets}/active_admin/active_admin.js.coffee +0 -0
  24. data/lib/potassium/{templates/application/assets → assets}/active_admin/admin_user_policy.rb +0 -0
  25. data/lib/potassium/{templates/application/assets → assets}/active_admin/comment_policy.rb +0 -0
  26. data/lib/potassium/{templates/application/assets → assets}/active_admin/init_activeadmin_angular.rb +0 -0
  27. data/lib/potassium/{templates/application/assets → assets}/active_admin/pundit_page_policy.rb +0 -0
  28. data/lib/potassium/{templates/application/assets → assets}/api/api_error_concern.rb +0 -0
  29. data/lib/potassium/{templates/application/assets → assets}/api/base_controller.rb +0 -0
  30. data/lib/potassium/{templates/application/assets → assets}/api/responder.rb +0 -0
  31. data/lib/potassium/assets/bin/cibuild.erb +27 -0
  32. data/lib/potassium/assets/bin/setup.erb +22 -0
  33. data/lib/potassium/assets/bin/setup_heroku.erb +21 -0
  34. data/lib/potassium/{templates/application/assets → assets}/bower.json +0 -0
  35. data/lib/potassium/assets/circle.yml +16 -0
  36. data/lib/potassium/assets/config/database_mysql.yml.erb +25 -0
  37. data/lib/potassium/assets/config/database_postgresql.yml.erb +25 -0
  38. data/lib/potassium/assets/config/environments/staging.rb +5 -0
  39. data/lib/potassium/assets/config/puma.rb +29 -0
  40. data/lib/potassium/assets/config/secrets.yml.erb +14 -0
  41. data/lib/potassium/assets/docker-compose.ci.yml +6 -0
  42. data/lib/potassium/{templates/application/assets → assets}/es.yml +0 -0
  43. data/lib/potassium/{templates/application/assets → assets}/testing/.rspec +0 -0
  44. data/lib/potassium/{templates/application/assets → assets}/testing/rails_helper.rb +0 -0
  45. data/lib/potassium/cli/commands/create.rb +55 -4
  46. data/lib/potassium/cli/commands/install.rb +27 -13
  47. data/lib/potassium/{templates/application/generator.rb → generators/application.rb} +7 -2
  48. data/lib/potassium/{templates/application/recipe_generator.rb → generators/recipe.rb} +11 -2
  49. data/lib/potassium/helpers/answer-helpers.rb +21 -0
  50. data/lib/potassium/{templates/application/helpers → helpers}/callback-helpers.rb +0 -0
  51. data/lib/potassium/helpers/docker-helpers.rb +37 -0
  52. data/lib/potassium/{templates/application/helpers → helpers}/environment-helpers.rb +0 -0
  53. data/lib/potassium/{templates/application/helpers → helpers}/gem-helpers.rb +6 -2
  54. data/lib/potassium/helpers/info-helpers.rb +16 -0
  55. data/lib/potassium/helpers/readme-helpers.rb +85 -0
  56. data/lib/potassium/{templates/application/helpers → helpers}/template-dsl.rb +8 -0
  57. data/lib/potassium/helpers/template-helpers.rb +97 -0
  58. data/lib/potassium/{templates/application/helpers → helpers}/variable-helpers.rb +0 -0
  59. data/lib/potassium/recipe.rb +2 -0
  60. data/lib/potassium/{templates/application/recipes → recipes}/admin.rb +36 -6
  61. data/lib/potassium/recipes/angular_admin.rb +56 -0
  62. data/lib/potassium/recipes/api.rb +43 -0
  63. data/lib/potassium/recipes/aws_sdk.rb +5 -0
  64. data/lib/potassium/recipes/bower.rb +13 -0
  65. data/lib/potassium/recipes/ci.rb +42 -0
  66. data/lib/potassium/recipes/cleanup.rb +10 -0
  67. data/lib/potassium/recipes/database.rb +42 -0
  68. data/lib/potassium/recipes/delayed_job.rb +41 -0
  69. data/lib/potassium/recipes/devise.rb +64 -0
  70. data/lib/potassium/recipes/editorconfig.rb +5 -0
  71. data/lib/potassium/recipes/env.rb +10 -0
  72. data/lib/potassium/recipes/git.rb +13 -0
  73. data/lib/potassium/recipes/github.rb +27 -0
  74. data/lib/potassium/recipes/heroku.rb +138 -0
  75. data/lib/potassium/recipes/i18n.rb +26 -0
  76. data/lib/potassium/recipes/paperclip.rb +37 -0
  77. data/lib/potassium/recipes/production.rb +7 -0
  78. data/lib/potassium/recipes/pry.rb +10 -0
  79. data/lib/potassium/recipes/puma.rb +19 -0
  80. data/lib/potassium/recipes/pundit.rb +61 -0
  81. data/lib/potassium/recipes/rack_cors.rb +21 -0
  82. data/lib/potassium/recipes/readme.rb +7 -0
  83. data/lib/potassium/recipes/ruby.rb +23 -0
  84. data/lib/potassium/recipes/script.rb +16 -0
  85. data/lib/potassium/recipes/secrets.rb +5 -0
  86. data/lib/potassium/recipes/staging.rb +5 -0
  87. data/lib/potassium/recipes/style.rb +13 -0
  88. data/lib/potassium/recipes/testing.rb +37 -0
  89. data/lib/potassium/templates/application.rb +67 -0
  90. data/lib/potassium/templates/recipe.rb +12 -0
  91. data/lib/potassium/text_spinner.rb +0 -5
  92. data/lib/potassium/version.rb +2 -1
  93. data/potassium.gemspec +3 -0
  94. data/spec/fakes/bin/heroku +5 -0
  95. data/spec/fakes/bin/hub +5 -0
  96. data/spec/features/ci_spec.rb +14 -0
  97. data/spec/features/github_spec.rb +22 -0
  98. data/spec/features/heroku_spec.rb +61 -0
  99. data/spec/features/new_project_spec.rb +38 -0
  100. data/spec/spec_helper.rb +33 -0
  101. data/spec/support/fake_github.rb +25 -0
  102. data/spec/support/fake_heroku.rb +77 -0
  103. data/spec/support/potassium_test_helpers.rb +98 -0
  104. metadata +149 -62
  105. data/lib/potassium/templates/application/assets/.rbenv-vars.example +0 -8
  106. data/lib/potassium/templates/application/assets/config/database_mysql.yml +0 -40
  107. data/lib/potassium/templates/application/assets/config/database_postgresql.yml +0 -26
  108. data/lib/potassium/templates/application/helpers/recipe-helpers.rb +0 -5
  109. data/lib/potassium/templates/application/helpers/template-helpers.rb +0 -35
  110. data/lib/potassium/templates/application/recipe_template.rb +0 -23
  111. data/lib/potassium/templates/application/recipes/angular_admin.rb +0 -26
  112. data/lib/potassium/templates/application/recipes/api.rb +0 -22
  113. data/lib/potassium/templates/application/recipes/asks/admin.rb +0 -9
  114. data/lib/potassium/templates/application/recipes/asks/api.rb +0 -2
  115. data/lib/potassium/templates/application/recipes/asks/database.rb +0 -9
  116. data/lib/potassium/templates/application/recipes/asks/devise.rb +0 -10
  117. data/lib/potassium/templates/application/recipes/asks/i18n.rb +0 -8
  118. data/lib/potassium/templates/application/recipes/asks/paperclip.rb +0 -2
  119. data/lib/potassium/templates/application/recipes/asks/pundit.rb +0 -4
  120. data/lib/potassium/templates/application/recipes/aws_sdk.rb +0 -1
  121. data/lib/potassium/templates/application/recipes/bower.rb +0 -3
  122. data/lib/potassium/templates/application/recipes/checks/devise.rb +0 -1
  123. data/lib/potassium/templates/application/recipes/database.rb +0 -22
  124. data/lib/potassium/templates/application/recipes/dependencies/admin.rb +0 -3
  125. data/lib/potassium/templates/application/recipes/devise.rb +0 -28
  126. data/lib/potassium/templates/application/recipes/editorconfig.rb +0 -1
  127. data/lib/potassium/templates/application/recipes/git.rb +0 -9
  128. data/lib/potassium/templates/application/recipes/i18n.rb +0 -9
  129. data/lib/potassium/templates/application/recipes/paperclip.rb +0 -20
  130. data/lib/potassium/templates/application/recipes/production.rb +0 -3
  131. data/lib/potassium/templates/application/recipes/pry.rb +0 -6
  132. data/lib/potassium/templates/application/recipes/pundit.rb +0 -33
  133. data/lib/potassium/templates/application/recipes/rack-cors.rb +0 -15
  134. data/lib/potassium/templates/application/recipes/rbenv.rb +0 -23
  135. data/lib/potassium/templates/application/recipes/readme.rb +0 -2
  136. data/lib/potassium/templates/application/recipes/testing.rb +0 -32
  137. data/lib/potassium/templates/application/recipes/unicorn.rb +0 -5
  138. data/lib/potassium/templates/application/template.rb +0 -58
@@ -0,0 +1,56 @@
1
+ class Recipes::AngularAdmin < Rails::AppBuilder
2
+ def ask
3
+ if selected?(:admin_mode)
4
+ angular_admin = answer(:"angular-admin") do
5
+ Ask.confirm "Do you want Angular support for ActiveAdmin?"
6
+ end
7
+ set(:angular_admin, angular_admin)
8
+ end
9
+ end
10
+
11
+ def create
12
+ recipe = self
13
+ if selected?(:angular_admin)
14
+ after(:admin_install) do
15
+ recipe.add_angular_admin
16
+ end
17
+ end
18
+ end
19
+
20
+ def install
21
+ active_admin = load_recipe(:admin)
22
+ if active_admin.installed?
23
+ add_angular_admin
24
+ else
25
+ info "ActiveAdmin can't be installed because Active Admin isn't installed."
26
+ end
27
+ end
28
+
29
+ def installed?
30
+ dir_exist?("app/assets/javascripts/admin")
31
+ end
32
+
33
+ def add_angular_admin
34
+ copy_file '../assets/active_admin/init_activeadmin_angular.rb',
35
+ 'config/initializers/init_activeadmin_angular.rb'
36
+
37
+ create_file 'app/assets/javascripts/admin_app.js', "angular.module('ActiveAdmin', []);"
38
+
39
+ copy_file '../assets/active_admin/active_admin.js.coffee',
40
+ 'app/assets/javascripts/active_admin.js.coffee',
41
+ force: true
42
+
43
+ empty_directory 'app/assets/javascripts/admin'
44
+ empty_directory 'app/assets/javascripts/admin/controllers'
45
+ empty_directory 'app/assets/javascripts/admin/services'
46
+ empty_directory 'app/assets/javascripts/admin/directives'
47
+
48
+ create_file 'app/assets/javascripts/admin/controllers/.keep'
49
+ create_file 'app/assets/javascripts/admin/services/.keep'
50
+ create_file 'app/assets/javascripts/admin/directives/.keep'
51
+
52
+ inside('.') do
53
+ run('bower install angular --save')
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,43 @@
1
+ class Recipes::Api < Rails::AppBuilder
2
+ def ask
3
+ api_support = answer(:api) { Ask.confirm("Do you want to enable API support?") }
4
+ set(:api_support, api_support)
5
+ end
6
+
7
+ def create
8
+ add_api if get(:api_support)
9
+ end
10
+
11
+ def install
12
+ add_api
13
+ end
14
+
15
+ def installed?
16
+ gem_exists?(/versionist/)
17
+ end
18
+
19
+ private
20
+
21
+ def add_api
22
+ gather_gem 'versionist'
23
+ gather_gem 'responders'
24
+ gather_gem 'active_model_serializers', '~> 0.9.3'
25
+ gather_gem 'simple_token_authentication', '~> 1.0'
26
+
27
+ after(:gem_install) do
28
+ line = "Rails.application.routes.draw do\n"
29
+ insert_into_file "config/routes.rb", after: line do
30
+ <<-HERE.gsub(/^ {8}/, '')
31
+ scope path: '/api' do
32
+ api_version(module: "Api::V1", path: { value: "v1" }) do
33
+ end
34
+ end
35
+ HERE
36
+ end
37
+
38
+ copy_file '../assets/api/base_controller.rb', 'app/controllers/api/v1/base_controller.rb'
39
+ copy_file '../assets/api/api_error_concern.rb', 'app/controllers/concerns/api_error_concern.rb'
40
+ copy_file '../assets/api/responder.rb', 'app/responders/api_responder.rb'
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ class Recipes::AwsSdk < Rails::AppBuilder
2
+ def create
3
+ gather_gem('aws-sdk', '< 2')
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Recipes::Bower < Rails::AppBuilder
2
+ def create
3
+ copy_file '../assets/.bowerrc', '.bowerrc'
4
+ template '../assets/bower.json', 'bower.json'
5
+ application "config.assets.paths << Rails.root.join('vendor', 'assets', 'bower_components')"
6
+
7
+ if get(:heroku)
8
+ bower_buildpack_url = 'https://github.com/platanus/heroku-buildpack-bower.git'
9
+ insert_point = 'https://github.com/platanus/heroku-buildpack-ruby-version.git'
10
+ inject_into_file '.buildpacks', "#{bower_buildpack_url}\n", before: insert_point
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,42 @@
1
+ class Recipes::Ci < Rails::AppBuilder
2
+ def create
3
+ if get(:heroku)
4
+ copy_file '../assets/Dockerfile.ci', 'Dockerfile.ci'
5
+ copy_file '../assets/circle.yml', 'circle.yml'
6
+
7
+ template '../assets/bin/cibuild.erb', 'bin/cibuild'
8
+ run "chmod a+x bin/cibuild"
9
+
10
+ copy_file '../assets/docker-compose.ci.yml', 'docker-compose.ci.yml'
11
+
12
+ compose = DockerHelpers.new('docker-compose.ci.yml')
13
+
14
+ if selected?(:database, :mysql)
15
+ service = <<-YAML
16
+ image: "mysql:5.6.23"
17
+ environment:
18
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
19
+ YAML
20
+ compose.add_service("mysql", service)
21
+ compose.add_link('test', 'mysql')
22
+ compose.add_env('test', 'MYSQL_HOST', 'mysql')
23
+ compose.add_env('test', 'MYSQL_PORT', '3306')
24
+
25
+ elsif selected?(:database, :postgresql)
26
+ service = <<-YAML
27
+ image: "postgres:9.4.5"
28
+ environment:
29
+ POSTGRES_USER: postgres
30
+ POSTGRES_PASSWORD: ''
31
+ YAML
32
+ compose.add_service("postgresql", service)
33
+ compose.add_link('test', 'postgresql')
34
+ compose.add_env('test', 'POSTGRESQL_USER', 'postgres')
35
+ compose.add_env('test', 'POSTGRESQL_HOST', 'postgresql')
36
+ compose.add_env('test', 'POSTGRESQL_PORT', '5432')
37
+ end
38
+
39
+ add_readme_header :ci
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ class Recipes::Cleanup < Rails::AppBuilder
2
+ def create
3
+ erase_comments "config/application.rb"
4
+ erase_comments "config/environments/production.rb"
5
+ erase_comments "config/environments/staging.rb"
6
+ erase_comments "config/environments/test.rb"
7
+ erase_comments "config/environments/development.rb"
8
+ cut_comments "config/initializers/backtrace_silencers.rb", limit: 100
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ class Recipes::Database < Rails::AppBuilder
2
+ def ask
3
+ databases = {
4
+ mysql: "MySQL",
5
+ postgresql: "PostgreSQL",
6
+ none: "None, thanks"
7
+ }
8
+
9
+ database = answer(:db) do
10
+ databases.keys[Ask.list("Which database are you using?", databases.values)]
11
+ end
12
+
13
+ set :database, database.to_sym
14
+ end
15
+
16
+ def create
17
+ databases = {
18
+ mysql: { name: 'mysql', gem_name: 'mysql2', version: '~> 0.3.18', relational: true },
19
+ postgresql: { name: 'postgresql', gem_name: 'pg', relational: true }
20
+ }
21
+
22
+ if db = databases[get(:database)]
23
+ if db[:relational]
24
+ activate_for_active_record(db)
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def activate_for_active_record(db)
32
+ remove_file 'config/database.yml'
33
+ template "../assets/config/database_#{db[:name]}.yml.erb", 'config/database.yml'
34
+
35
+ discard_gem 'sqlite3'
36
+ if db[:version]
37
+ gather_gem db[:gem_name], db[:version]
38
+ else
39
+ gather_gem db[:gem_name]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ class Recipes::DelayedJob < Rails::AppBuilder
2
+ def ask
3
+ use_delayed_job = answer(:"delayed-job") { Ask.confirm("Do you want to use delayed jobs?") }
4
+ set(:delayed_job, use_delayed_job)
5
+ end
6
+
7
+ def create
8
+ add_delayed_job if selected?(:delayed_job)
9
+ end
10
+
11
+ def install
12
+ heroku = load_recipe(:heroku)
13
+ set(:heroku, heroku.installed?)
14
+ add_delayed_job
15
+ end
16
+
17
+ def installed?
18
+ gem_exists?(/delayed_job_active_record/)
19
+ end
20
+
21
+ private
22
+
23
+ def add_delayed_job
24
+ gather_gem "delayed_job_active_record"
25
+
26
+ delayed_job_config = "config.active_job.queue_adapter = :delayed_job"
27
+ application(delayed_job_config)
28
+
29
+ after(:gem_install) do
30
+ generate "delayed_job:active_record"
31
+ run "bundle binstubs delayed_job"
32
+ add_readme_section :internal_dependencies, :delayed_job
33
+
34
+ if selected?(:heroku)
35
+ gsub_file "Procfile", /^.*$/m do |match|
36
+ "#{match}worker: bundle exec rake jobs:work"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ class Recipes::Devise < Rails::AppBuilder
2
+ def ask
3
+ use_devise = answer(:devise) do
4
+ Ask.confirm "Do you want to use Devise for authentication? (required for ActiveAdmin)"
5
+ end
6
+
7
+ if use_devise
8
+ set(:authentication, use_devise)
9
+ ask_for_devise_model
10
+ end
11
+ end
12
+
13
+ def create
14
+ add_devise if selected?(:authentication)
15
+ end
16
+
17
+ def install
18
+ ask_for_devise_model
19
+ add_devise
20
+ end
21
+
22
+ def installed?
23
+ gem_exists?(/devise/)
24
+ end
25
+
26
+ private
27
+
28
+ def ask_for_devise_model
29
+ create_user_model = answer(:"devise-user-model") do
30
+ Ask.confirm "Do you want to create a user model for Devise?"
31
+ end
32
+
33
+ set(:authentication_model, :user) if create_user_model
34
+ end
35
+
36
+ def add_devise
37
+ gather_gem 'devise'
38
+ gather_gem 'devise-i18n'
39
+
40
+ after(:gem_install) do
41
+ generate "devise:install"
42
+
43
+ if auth_model = get(:authentication_model)
44
+ generate "devise #{auth_model}"
45
+ end
46
+
47
+ gsub_file "config/initializers/devise.rb", /(\# config.secret_key.+)/i do |_match|
48
+ "config.secret_key = ENV['DEVISE_SECRET_KEY']"
49
+ end
50
+
51
+ gsub_file "config/initializers/devise.rb", /(config.mailer_sender.+)/i do |_match|
52
+ "config.mailer_sender = ENV['DEFAULT_EMAIL_ADDRESS']"
53
+ end
54
+
55
+ gsub_file "config/initializers/devise.rb", /(\# config.pepper.+)/i do |_match|
56
+ "# config.pepper = 'onhcylrat7x8bjyr5o15sxaix3vbu0sl'"
57
+ end
58
+
59
+ append_to_file '.env.example', 'DEVISE_SECRET_KEY='
60
+ append_to_file '.env', 'DEVISE_SECRET_KEY='
61
+ add_readme_section :internal_dependencies, :devise
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ class Recipes::Editorconfig < Rails::AppBuilder
2
+ def create
3
+ copy_file '../assets/.editorconfig', '.editorconfig'
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class Recipes::Env < Rails::AppBuilder
2
+ def create
3
+ gather_gems(:development, :test) do
4
+ gather_gem('dotenv-rails')
5
+ end
6
+
7
+ template '../assets/.env.example.erb', '.env.example'
8
+ run "cp .env.example .env"
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class Recipes::Git < Rails::AppBuilder
2
+ def create
3
+ git :init
4
+ after(:database_creation) do
5
+ append_to_file '.gitignore', ".env\n"
6
+ append_to_file '.gitignore', ".powder\n"
7
+ append_to_file '.gitignore', "vendor/assets/bower_components\n"
8
+
9
+ git add: "."
10
+ git commit: %{ -m 'Initial commit' }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ class Recipes::Github < Rails::AppBuilder
2
+ def ask
3
+ repo_name = "platanus/#{get(:dasherized_app_name)}"
4
+ github_repo_create = answer(:github) do
5
+ Ask.confirm("Do you want to use create the github repository? (#{repo_name})")
6
+ end
7
+ if github_repo_create
8
+ github_repo_private = answer(:"github-private") do
9
+ Ask.confirm("Should the repository be private?")
10
+ end
11
+ end
12
+ set(:github_repo_name, repo_name)
13
+ set(:github_repo_create, github_repo_create)
14
+ set(:github_repo_private, github_repo_private)
15
+ end
16
+
17
+ def create
18
+ github_repo_create(get(:github_repo_name), get(:github_repo_private))
19
+ end
20
+
21
+ private
22
+
23
+ def github_repo_create(repo_name, private_repo = false)
24
+ flag = private_repo ? "-p" : ""
25
+ run "hub create #{flag} #{repo_name}"
26
+ end
27
+ end
@@ -0,0 +1,138 @@
1
+ class Recipes::Heroku < Rails::AppBuilder
2
+ NAME_PREFIX = 'pl'
3
+
4
+ attr_accessor :app_name_staging
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
11
+
12
+ def ask
13
+ heroku = answer(:heroku) do
14
+ Ask.confirm("Are you going to deploy to heroku? (#{who_am_i})")
15
+ end
16
+
17
+ if heroku
18
+ set(:heroku, heroku)
19
+ end
20
+ end
21
+
22
+ def create
23
+ add_heroku if get(:heroku)
24
+ end
25
+
26
+ def install
27
+ add_heroku
28
+ end
29
+
30
+ def installed?
31
+ gem_exists?(/rails_stdout_logging/)
32
+ end
33
+
34
+ private
35
+
36
+ def add_heroku
37
+ gather_gems(:production, :staging) do
38
+ gather_gem('rails_stdout_logging')
39
+ end
40
+
41
+ copy_file '../assets/Procfile', 'Procfile'
42
+ copy_file '../assets/.buildpacks', '.buildpacks'
43
+
44
+ template "../assets/bin/setup_heroku.erb", "bin/setup_heroku", force: true
45
+ run "chmod a+x bin/setup_heroku"
46
+
47
+ if logged_in?
48
+ %w(staging production).each do |environment|
49
+ create_app_on_heroku(environment)
50
+ end
51
+ puts "Remember to connect the github repository to the new pipeline"
52
+ open_pipeline_command = "\e[33mheroku pipelines:open #{heroku_pipeline_name}\e[0m"
53
+ puts "run #{open_pipeline_command} to open the dashboard"
54
+ else
55
+ puts "You are not logged in into heroku"
56
+ login_command = "\e[33mheroku login\e[0m"
57
+ puts "Run #{login_command} and enter your credentials"
58
+ puts "You can install the heroku recipe again create the app in heroku"
59
+ install_command = "\e[33mpostassium install heroku --force\e[0m"
60
+ puts "Just run #{install_command}"
61
+ end
62
+
63
+ add_readme_header :deployment
64
+ end
65
+
66
+ def heroku_pipeline_name
67
+ app_name.dasherize
68
+ end
69
+
70
+ def app_name_for(environment)
71
+ "#{NAME_PREFIX}-#{app_name.dasherize}-#{environment}"
72
+ end
73
+
74
+ def logged_in?
75
+ !who_am_i.include? "not logged in"
76
+ end
77
+
78
+ def who_am_i
79
+ `heroku auth:whoami`.strip
80
+ end
81
+
82
+ def create_app_on_heroku(environment)
83
+ rack_env = "RACK_ENV=#{environment} RAILS_ENV=#{environment}"
84
+ staged_app_name = app_name_for(environment)
85
+
86
+ run_toolbelt_command "create #{staged_app_name} --remote #{environment}"
87
+ run_toolbelt_command "config:add #{rack_env}", staged_app_name
88
+ run_toolbelt_command "config:add DEPLOY_TASKS=db:migrate", staged_app_name
89
+
90
+ set_rails_secrets(environment)
91
+ set_app_multi_buildpack(environment)
92
+ add_app_to_pipeline(staged_app_name, environment)
93
+ end
94
+
95
+ def set_rails_secrets(environment)
96
+ run_toolbelt_command(
97
+ "config:add SECRET_KEY_BASE=#{generate_secret}",
98
+ app_name_for(environment)
99
+ )
100
+ end
101
+
102
+ def set_app_multi_buildpack(environment)
103
+ run_toolbelt_command(
104
+ "buildpacks:set https://github.com/ddollar/heroku-buildpack-multi.git",
105
+ app_name_for(environment)
106
+ )
107
+ end
108
+
109
+ def add_app_to_pipeline(app_env_name, environment)
110
+ pipelines_plugin = `heroku plugins | grep pipelines`
111
+ if pipelines_plugin.empty?
112
+ puts "You need heroku pipelines plugin. Run: heroku plugins:install heroku-pipelines"
113
+ exit 1
114
+ end
115
+
116
+ pipeline = `heroku pipelines:info \
117
+ #{heroku_pipeline_name} 2>/dev/null | grep #{heroku_pipeline_name}`
118
+ pipeline_command = pipeline.empty? ? "create" : "add"
119
+
120
+ run_toolbelt_command(
121
+ "pipelines:#{pipeline_command} #{heroku_pipeline_name} \
122
+ --stage #{environment}",
123
+ app_env_name
124
+ )
125
+ end
126
+
127
+ def generate_secret
128
+ SecureRandom.hex(64)
129
+ end
130
+
131
+ def run_toolbelt_command(command, app_env_name = nil)
132
+ if app_env_name.nil?
133
+ `heroku #{command}`
134
+ else
135
+ `heroku #{command} --app #{app_env_name}`
136
+ end
137
+ end
138
+ end