potassium 1.3.5 → 2.0.0

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