code42template 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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +3 -0
  6. data/NEWS.md +56 -0
  7. data/README.md +280 -0
  8. data/Rakefile +8 -0
  9. data/bin/code42template +24 -0
  10. data/bin/rake +16 -0
  11. data/bin/rspec +16 -0
  12. data/bin/setup +13 -0
  13. data/code42template.gemspec +30 -0
  14. data/lib/code42template/actions.rb +28 -0
  15. data/lib/code42template/adapters/heroku.rb +174 -0
  16. data/lib/code42template/app_builder.rb +251 -0
  17. data/lib/code42template/generators/app_generator.rb +208 -0
  18. data/lib/code42template/version.rb +9 -0
  19. data/lib/code42template.rb +5 -0
  20. data/spec/adapters/heroku_spec.rb +56 -0
  21. data/spec/code42template.rb +58 -0
  22. data/spec/fakes/bin/heroku +5 -0
  23. data/spec/fakes/bin/hub +5 -0
  24. data/spec/features/heroku_spec.rb +83 -0
  25. data/spec/features/new_project_spec.rb +186 -0
  26. data/spec/fixtures/feature_smoke_test.rb +15 -0
  27. data/spec/fixtures/home_controller.rb +4 -0
  28. data/spec/fixtures/index.html.erb +1 -0
  29. data/spec/fixtures/routes.rb +3 -0
  30. data/spec/fixtures/smoke_test.rb +10 -0
  31. data/spec/spec_helper.rb +14 -0
  32. data/spec/support/code42template.rb +83 -0
  33. data/spec/support/fake_heroku.rb +83 -0
  34. data/templates/Gemfile.erb +42 -0
  35. data/templates/Procfile +3 -0
  36. data/templates/README.md.erb +10 -0
  37. data/templates/active_job.rb +1 -0
  38. data/templates/application.js +1 -0
  39. data/templates/bin_deploy +12 -0
  40. data/templates/bin_setup +21 -0
  41. data/templates/bin_setup_review_app.erb +19 -0
  42. data/templates/code42_gitignore +16 -0
  43. data/templates/config_locales_pt-BR.yml.erb +17 -0
  44. data/templates/dotfiles/.babelrc +5 -0
  45. data/templates/dotfiles/.codeclimate.yml +3 -0
  46. data/templates/dotfiles/.env +8 -0
  47. data/templates/dotfiles/.rspec +2 -0
  48. data/templates/dotfiles/.rubocop.yml +20 -0
  49. data/templates/feature_helper.rb.erb +5 -0
  50. data/templates/health.rake +22 -0
  51. data/templates/karma.conf.js +48 -0
  52. data/templates/mocha-webpack.opts +4 -0
  53. data/templates/package.json +39 -0
  54. data/templates/postgresql_database.yml.erb +22 -0
  55. data/templates/puma.rb +28 -0
  56. data/templates/rails_helper.rb +59 -0
  57. data/templates/secrets.yml +14 -0
  58. data/templates/setup +32 -0
  59. data/templates/sidekiq.yml +7 -0
  60. data/templates/spec/javascripts/.gitkeep +0 -0
  61. data/templates/spec/javascripts/index.browser.js +5 -0
  62. data/templates/spec/javascripts/index.integration.js +5 -0
  63. data/templates/spec/javascripts/integration/smoke.spec.js +7 -0
  64. data/templates/spec/javascripts/unit/smoke.spec.js +7 -0
  65. data/templates/spec_helper.rb +15 -0
  66. data/templates/travis.yml.erb +12 -0
  67. data/templates/webpack.config.js +68 -0
  68. data/templates/webpack.config.test.browser.js +17 -0
  69. data/templates/webpack.config.test.js +5 -0
  70. data/templates/webpack.rake +26 -0
  71. metadata +158 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25f9b6b6283c1adf734c7de322de2cad8a852a2b
4
+ data.tar.gz: 542e7cfd66f20c16858cab5a6fb45a1360326d7c
5
+ SHA512:
6
+ metadata.gz: 4d469c1365c42a9e90dad4acd623984f85f1ee14d406c9f8ad596b713b0011cb33847a82ba34039571824a6520b83f1c60d6a635735be9725e6fcec7ed6b1010
7
+ data.tar.gz: 98b2e35b070cdadbbf7f7976df6b2e8a8b3dfa5723cc2eca0b1aae609419af9d39ce1efddc31bc68a4596de2f9caaa00c7e0d4303ff3150f89d82f857e9536bd
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ *.swp
3
+ Gemfile.lock
4
+ /.bundle
5
+ /tmp
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm: 2.3.0
3
+ cache: bundler
4
+ sudo: false
5
+ before_install:
6
+ - "echo '--colour' > ~/.rspec"
7
+ - git config --global user.name 'Travis CI'
8
+ - git config --global user.email 'travis-ci@example.com'
9
+ install: bundle install
10
+ notifications:
11
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/NEWS.md ADDED
@@ -0,0 +1,56 @@
1
+ 0.0.1 (January 28 2016)
2
+
3
+ * Initial setup
4
+ * Ruby 2.3.0
5
+ * Rails 4.2.5
6
+ * App layout and flashes
7
+ * Customize error pages
8
+ * Git init and .gitignore
9
+ * Postgresql as database
10
+ * pt-BR locale
11
+ * Readme
12
+ * Remove config and routes comment lines
13
+ * Setup script
14
+ * Setup secret token
15
+
16
+ 1.0.0 (April 06 2016)
17
+
18
+ * Add `quiet_assets` as development dependency
19
+ * Generate rake, rails and rspec binstubs with Spring
20
+ * Make Shoulda Matchers work with Spring
21
+ * Add `binding_of_caller` gem
22
+ * Add `better_errors` gem
23
+ * Add `pry-byebug` and `pry-rails` gems
24
+ * Add `bullet` as development dependency
25
+ * Add Bundler Audit to scan Gemfile for insecure dependencies per CVEs.
26
+ * Add Dotenv to development and test environments to load environment variables from the `.env` file.
27
+ * Add `brakeman`
28
+ * Add `letter_opener`
29
+ * Add `rubocop`
30
+
31
+ 1.0.1 (July 02 2016)
32
+
33
+ * Fix bug: remove missing jquery from generated application.js
34
+
35
+ 2.0.0 (July 27 2016)
36
+
37
+ * Setup rspec with reasonable default settings out of the box
38
+ * Setup capybara and database\_cleaner out of the box
39
+ * Include optional config for phantomjs / poltergeist
40
+ * Include webpack (webpack-rails) and NPM to replace sprockets' JS
41
+ * use foreman to manage processes: rails server, webpack dev server and sidekiq
42
+ * Include JS test runners: karma and mocha
43
+ * Upgrade Ruby to 2.3.1
44
+ * Upgrade Rails to 5.0
45
+ * Drop quiet\_assets in favor of Rails 5' native similar feature
46
+ * Add Heroku support upon app creation
47
+ * Tune up deploy with Heroku
48
+ * Add Puma as the default application server
49
+ * Add codeclimate configuration
50
+ * Add sidekiq / ActiveJob as background job runner
51
+ * Add rubocop configuration
52
+ * Add rake health command and make CI use it
53
+ * Cleanup unnecessary gems
54
+ * Improve bin/setup script
55
+ * Do not remove comments from generated files anymore
56
+ * Improve README
data/README.md ADDED
@@ -0,0 +1,280 @@
1
+ # Code42Template
2
+
3
+ This is the base application used at [Codeminer
4
+ 42](http://www.codeminer42.com/). It uses **Rails 5** to manage the backend and
5
+ **Node.js / Webpack** to manage the frontend. The purpose of this project is
6
+ to:
7
+
8
+ - Provide a minimal and well-configured application generator.
9
+ - Improve some Rails defaults.
10
+ - Unleash the full power of the JavaScript ecosystem within Rails by making it
11
+ a **first class citizen**. We replace JS sprockets with **Webpack**.
12
+ - Enforce **code style guidelines**.
13
+ - Provide _basic_ **security**.
14
+ - Have Ruby and JS test frameworks configured out of the box with a few
15
+ hand-picked tools.
16
+ - Provide opinionated defaults on infrastructure: **Travis** for CI and
17
+ **Heroku** deploys working out of the box. We want apps to leverage the best
18
+ Heroku has to offer, such as decreased devops maintenance burden, pipelines,
19
+ review apps, etc.
20
+
21
+ This template does **NOT** aim to:
22
+
23
+ - Encourage having too many dependencies. Dependencies are not cheap, and each
24
+ bundled tool must have a _good_ reason to be included.
25
+ - Make you use JavaScript for everything, but rather to provide better
26
+ tools to work with the language. Just because we use Webpack it does not
27
+ mean you have to turn your app into an SPA.
28
+ - Provide "pattern" gems (e.g. decorator). Patterns are usually
29
+ project-specific and most of them can be achieved **without** any gems or
30
+ libraries.
31
+ - Be a silver bullet. This is tailored for the majority of Rails applications
32
+ you may want to build, but we know it won't work sometimes.
33
+
34
+ ## Pre-requisites
35
+
36
+ - [Ruby](https://www.ruby-lang.org) >= 2.3.1
37
+ - [Bundler](http://bundler.io/)
38
+ - Either [rbenv](https://github.com/rbenv/rbenv) /
39
+ [ruby-build](https://github.com/rbenv/ruby-build) or
40
+ [rvm](https://github.com/rvm/rvm)
41
+ - [Node.js](https://nodejs.org) >= 6.2.0
42
+ - [NPM](https://www.npmjs.com/)
43
+ - [nvm](https://github.com/creationix/nvm)
44
+ - [Git](https://git-scm.com/)
45
+ - [PostgreSQL](https://www.postgresql.org/)
46
+ - [Heroku Toolbelt](https://toolbelt.heroku.com/)
47
+ - [Redis](http://redis.io/) - primarily for use with [Sidekiq](http://sidekiq.org/)
48
+ - [PhantomJS](http://phantomjs.org/)
49
+
50
+
51
+ ## Installation
52
+
53
+ Install the gem:
54
+
55
+ ```sh
56
+ gem install code42template
57
+ ```
58
+
59
+ This will make the `code42template` command accessible throughout your `PATH`.
60
+
61
+ ## Configuring your environment
62
+
63
+ ### PostgreSQL
64
+
65
+ **development** and **test** databases are automatically setup for you.
66
+ While running the generator it's assumed that:
67
+
68
+ - The PostgreSQL server is running.
69
+ - You have a PostgreSQL user named after your UNIX login.
70
+ - Your PostgreSQL user has a _blank_ password.
71
+
72
+ It's OK if your PG settings happen to be different from this; DB creation will
73
+ fail, but you can do it manually thereafter.
74
+
75
+ At a basic level, here's how to setup PostgreSQL on Linux:
76
+
77
+ ```sh
78
+ # Creates a user
79
+ sudo -u postgres createuser -s my_user_name
80
+
81
+ # Runs psql
82
+ sudo -u postgres psql
83
+
84
+ # Change your use password within psql. Leave it blank.
85
+ [local] thiago@thiago=# \password my_user_name
86
+ ```
87
+
88
+ ### Heroku
89
+
90
+ Automatic Heroku setup is optional, but if you want to use it we assume you've
91
+ already logged in with your Heroku credentials. If you haven't, you'll need to
92
+ run `heroku login`. Also remember to set the correct account if you happen to
93
+ use the [multiple accounts](https://github.com/heroku/heroku-accounts) plugin.
94
+
95
+ ## Generating your app
96
+
97
+ You can generate a new app with the following command:
98
+
99
+ ```sh
100
+ code42template myapp
101
+ ```
102
+
103
+ To generate and configure your new app with Heroku:
104
+
105
+ ```sh
106
+ code42template myapp --heroku true
107
+ ```
108
+
109
+ ## Starting up your app
110
+
111
+ ```sh
112
+ $ cd my_app_folder
113
+ $ foreman start
114
+ ```
115
+
116
+ This command runs Webpack dev server, Rails server and Sidekiq all at once.
117
+ Note that Your redis server has to be up and running because of Sidekiq. To
118
+ customize these processes you can edit `Procfile`.
119
+
120
+ Now you can work as you'd usually work in any Rails application, with automatic
121
+ Ruby and JS file reloads out of the box.
122
+
123
+ ## Basic hands-on guide
124
+
125
+ ### App setup
126
+
127
+ Your team can use the following command after cloning the git repository:
128
+
129
+ ```sh
130
+ bin/setup
131
+ ```
132
+ ### Deploy
133
+
134
+ Deploy your app with the following command:
135
+
136
+ ```sh
137
+ # Replace `MY_ENV` with `production` or `staging`.
138
+ bin/deploy MY_ENV
139
+ ```
140
+
141
+ This command pushes your code to Heroku, migrates your database and restarts
142
+ your dynos. It will work out of the box if you've generated your app with
143
+ `--heroku true`. If not, please create `staging` and `production` git remotes
144
+ pointing to the respective Heroku remotes.
145
+
146
+ ### Health check
147
+
148
+ Check your app's health with the `rake health` command. It runs the following
149
+ tasks:
150
+
151
+ - `rspec` runs your Ruby and Rails specs.
152
+ - If you app happens to be below 90% test coverage the `rspec` command will fail.
153
+ - `npm run test`: runs JS unit and integration tests
154
+ - `bundle-audit` and `brakeman` check if your app does not have basic
155
+ security holes.
156
+ - `rubocop` makes sure your code adheres to style guidelines.
157
+
158
+ ### Continuous integration
159
+
160
+ A `travis.yml` file is also included: it runs the `rake health` command, among
161
+ other setup tasks. You must still manually configure your remote repo with
162
+ Travis integration, though.
163
+
164
+ ### Improved JavaScript
165
+
166
+ JS files must live at the `app/assets/javascripts` folder. JS packages can be
167
+ managed with NPM and the `package.json` file.
168
+
169
+ You can write your JS code in **ES2015** because of
170
+ [babel](https://babeljs.io/). ES2015 Import statements will automatically work
171
+ without having to specify the full path.
172
+
173
+ ### CSS
174
+
175
+ We still use the asset pipeline for CSS.
176
+
177
+ ### Testing
178
+
179
+ #### Ruby tests
180
+
181
+ Use the following command to run all your specs:
182
+
183
+ ```sh
184
+ rspec
185
+ ```
186
+
187
+ We use the following tools:
188
+
189
+ - [rspec](https://github.com/rspec/rspec)
190
+ - [capybara](https://github.com/jnicklas/capybara) and
191
+ [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner)
192
+ - [factory_girl](https://github.com/thoughtbot/factory_girl)
193
+ - [poltergeist](https://github.com/teampoltergeist/poltergeist) (for JS feature
194
+ tests)
195
+ - [simplecov](https://github.com/colszowka/simplecov) for helping out with test
196
+ coverage
197
+
198
+
199
+ Refer to the [rspec-rails](https://github.com/rspec/rspec-rails) to learn which
200
+ kinds of specs are available.
201
+
202
+ Note that you can require the following files to setup your tests:
203
+
204
+ - For light unit tests you can require `spec_helper.rb`. It won't boot up
205
+ the Rails environment.
206
+ - For tests needing Rails you can require `rails_helper.rb`.
207
+ - For feature tests require `feature_helper.rb`. It will compile your assets
208
+ and make feature tests run correctly.
209
+
210
+ Regarding feature tests, they are configured to run seamlessly with Webpack.
211
+
212
+ #### JavaScript tests
213
+
214
+ JavaScript tests must live at the `spec/javascripts` folder. Some smoke
215
+ tests are included in every app.
216
+
217
+ - `mocha` is used for unit tests. Unit tests **must not depend** on global JS
218
+ objects such as `window`. They must live at `spec/javascripts/unit` and can be
219
+ run with:
220
+
221
+ npm test:unit
222
+ npm test:unit:watch # runs tests automatically in every change
223
+
224
+ - `karma` and `phantomjs` are used for integration tests. That means you _can_
225
+ use browser-only global JS objects such as `window`. They must live at
226
+ `spec/javascript/integration` and can be run with:
227
+
228
+ npm test:integration
229
+ npm test:integration:watch
230
+
231
+ - Run _all_ the tests (unit + integration) with the following command:
232
+
233
+ npm test
234
+
235
+ - Debug your tests in the browser with webpack-dev-server. This command will
236
+ output a URL where you can run all tests:
237
+
238
+ npm test:browser
239
+
240
+ ### Application server
241
+
242
+ We use [puma](https://github.com/puma/puma) as our application server, which
243
+ happens to be [Heroku's default
244
+ recommendation](https://devcenter.heroku.com/changelog-items/594).
245
+
246
+ ### Background jobs
247
+
248
+ Our tool of choice is Sidekiq, which is configured as ActiveJob's backend. We
249
+ include a `sidekiq.yml` configuration file with default settings, but you are
250
+ encouraged to tune it to your application needs.
251
+
252
+ ### Debugging
253
+
254
+ - [pry-rails](https://github.com/rweng/pry-rails)
255
+ - [pry-byebug](https://github.com/deivid-rodriguez/pry-byebug)
256
+ - [better-errors](https://github.com/charliesome/better_errors) instead of Web
257
+ Console.
258
+
259
+ ### Performance and Profiling
260
+
261
+ * [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler) for
262
+ helping out with performance issues
263
+ * [spring](https://github.com/rails/spring) for fast Rails actions via
264
+ pre-loading
265
+ * [bullet](https://github.com/flyerhzm/bullet) yeah, it's very easy to miss out
266
+ N+1 queries, that's why we include this gem by default
267
+
268
+ Spring binstubs are automatically generated within the `bin` folder.
269
+
270
+ ### Environment variables
271
+
272
+ * [Dotenv](https://github.com/bkeepers/dotenv) for loading environment variables
273
+
274
+ ## Credits
275
+
276
+ The template uses the [Suspenders](https://github.com/thoughtbot/suspenders)
277
+ gem from Thoughtbot as starting point.
278
+
279
+ [![codeminer42](http://s3.amazonaws.com/cm42_prod/assets/logo-codeminer-horizontal-c0516b1b78a8713270da02c3a0645560.png)](http://codeminer42.com)
280
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:rspec)
6
+
7
+ desc 'Run the test suite'
8
+ task :default => :rspec
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path
5
+ $LOAD_PATH << source_path
6
+
7
+ require 'code42template/version'
8
+
9
+ if Code42Template::RUBY_VERSION != ::RUBY_VERSION
10
+ abort "ERROR: You must use this tool with Ruby version #{Code42Template::RUBY_VERSION}"
11
+ end
12
+
13
+ require 'code42template'
14
+
15
+ if ['-v', '--version'].include? ARGV[0]
16
+ puts Code42Template::VERSION
17
+ exit 0
18
+ end
19
+
20
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
21
+ Code42Template::AppGenerator.source_root templates_root
22
+ Code42Template::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
23
+
24
+ Code42Template::AppGenerator.start
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/setup ADDED
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+
3
+ # Run this script immediately after cloning the codebase.
4
+
5
+ # Exit if any subcommand fails
6
+ set -e
7
+
8
+ # Set up Ruby dependencies via Bundler
9
+ bundle install
10
+
11
+ # Add binstubs to PATH in ~/.zshenv like this:
12
+ # export PATH=".git/safe/../../bin:$PATH"
13
+ mkdir -p .git/safe
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'code42template/version'
4
+ require 'date'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.required_ruby_version = ">= #{Code42Template::RUBY_VERSION}"
8
+ s.authors = ['codeminer42']
9
+ s.date = Date.today.strftime('%Y-%m-%d')
10
+
11
+ s.description = <<-HERE
12
+ code42template is the base Rails project used at Codeminer 42.
13
+ HERE
14
+
15
+ s.email = 'suporte@codeminer42.com'
16
+ s.executables = ['code42template']
17
+ s.extra_rdoc_files = %w[README.md]
18
+ s.files = `git ls-files`.split("\n")
19
+ s.homepage = 'https://github.com/Codeminer42/code42template'
20
+ s.name = 'code42template'
21
+ s.rdoc_options = ['--charset=UTF-8']
22
+ s.require_paths = ['lib']
23
+ s.summary = "Generate a minimal Rails / Webpack app."
24
+ s.version = Code42Template::VERSION
25
+
26
+ s.add_dependency 'bundler'
27
+ s.add_dependency 'rails', Code42Template::RAILS_VERSION
28
+
29
+ s.add_development_dependency 'rspec'
30
+ end
@@ -0,0 +1,28 @@
1
+ module Code42Template
2
+ module Actions
3
+ def replace_in_file(relative_path, find, replace)
4
+ path = File.join(destination_root, relative_path)
5
+ contents = IO.read(path)
6
+ unless contents.gsub!(find, replace)
7
+ raise "#{find.inspect} not found in #{relative_path}"
8
+ end
9
+ File.open(path, "w") { |file| file.write(contents) }
10
+ end
11
+
12
+ def configure_application_file(config)
13
+ inject_into_file(
14
+ "config/application.rb",
15
+ "\n\n #{config}",
16
+ before: "\n end"
17
+ )
18
+ end
19
+
20
+ def configure_environment(rails_env, config)
21
+ inject_into_file(
22
+ "config/environments/#{rails_env}.rb",
23
+ "\n\n #{config}",
24
+ before: "\nend"
25
+ )
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,174 @@
1
+ module Code42Template
2
+ module Adapters
3
+ class Heroku
4
+ HEROKU_BUILDPACK_URLS = %w(
5
+ heroku/nodejs
6
+ heroku/ruby
7
+ https://github.com/febeling/webpack-rails-buildpack.git
8
+ )
9
+
10
+ def initialize(app_builder)
11
+ @app_builder = app_builder
12
+ end
13
+
14
+ def create_heroku_apps(flags)
15
+ create_staging_heroku_app(flags)
16
+ create_production_heroku_app(flags)
17
+ end
18
+
19
+ def create_deploy_script
20
+ @app_builder.copy_file "bin_deploy", "bin/deploy"
21
+ @app_builder.run "chmod a+x bin/deploy"
22
+ end
23
+
24
+ def update_readme_with_deploy
25
+ instructions = <<~MARKDOWN
26
+ ## Deploying
27
+
28
+ If you have previously run the `./bin/setup` script,
29
+ you can deploy to staging and production with:
30
+
31
+ $ ./bin/deploy staging
32
+ $ ./bin/deploy production
33
+
34
+ We currently use the following buildpacks:
35
+
36
+ - heroku/nodejs
37
+ - heroku/ruby
38
+ - https://github.com/febeling/webpack-rails-buildpack.git
39
+
40
+ Please be sure to configure these buildpacks in the same sequence
41
+ presented here in both staging and production, or else the deploy will
42
+ not work.
43
+ MARKDOWN
44
+
45
+ @app_builder.append_file "README.md", instructions
46
+ end
47
+
48
+ def set_heroku_remotes
49
+ remotes = <<~SHELL
50
+ #{command_to_join_heroku_app('staging')}
51
+ #{command_to_join_heroku_app('production')}
52
+
53
+ git config heroku.remote staging
54
+ SHELL
55
+
56
+ @app_builder.append_file 'bin/setup', remotes
57
+ end
58
+
59
+ def create_staging_heroku_app(flags)
60
+ app_name = heroku_app_name_for('staging')
61
+
62
+ run_toolbelt_command "create #{app_name} #{flags}", "staging"
63
+ end
64
+
65
+ def create_production_heroku_app(flags)
66
+ app_name = heroku_app_name_for('production')
67
+
68
+ run_toolbelt_command "create #{app_name} #{flags}", "production"
69
+ end
70
+
71
+ def set_heroku_rails_secrets
72
+ %w(staging production).each do |environment|
73
+ run_toolbelt_command(
74
+ "config:add SECRET_KEY_BASE=#{generate_secret}",
75
+ environment,
76
+ )
77
+ end
78
+ end
79
+
80
+ def set_heroku_rails_environment
81
+ %w(staging production).each do |environment|
82
+ run_toolbelt_command("config:add RAILS_ENV=production", environment)
83
+ end
84
+ end
85
+
86
+ def create_review_apps_setup_script
87
+ @app_builder.template(
88
+ 'bin_setup_review_app.erb',
89
+ 'bin/setup_review_app',
90
+ force: true,
91
+ )
92
+ @app_builder.run 'chmod a+x bin/setup_review_app'
93
+ end
94
+
95
+ def create_heroku_pipeline
96
+ run_toolbelt_command(
97
+ "pipelines:create #{heroku_app_name} \
98
+ -a #{heroku_app_name}-staging --stage staging",
99
+ 'staging',
100
+ )
101
+
102
+ run_toolbelt_command(
103
+ "pipelines:add #{heroku_app_name} \
104
+ -a #{heroku_app_name}-production --stage production",
105
+ 'production',
106
+ )
107
+ end
108
+
109
+ def configure_heroku_buildpacks
110
+ %w(staging production).each do |environment|
111
+ app_name = heroku_app_name_for(environment)
112
+
113
+ run_toolbelt_command("buildpacks:clear -a #{app_name}", environment)
114
+
115
+ HEROKU_BUILDPACK_URLS.each do |buildpack_url|
116
+ run_toolbelt_command(
117
+ "buildpacks:add #{buildpack_url} -a #{app_name}",
118
+ environment
119
+ )
120
+ end
121
+ end
122
+ end
123
+
124
+ def set_heroku_serve_static_files
125
+ %w(staging production).each do |environment|
126
+ run_toolbelt_command(
127
+ 'config:add RAILS_SERVE_STATIC_FILES=true',
128
+ environment,
129
+ )
130
+ end
131
+ end
132
+
133
+ def set_heroku_application_host
134
+ %w(staging production).each do |environment|
135
+ run_toolbelt_command(
136
+ "config:add APPLICATION_HOST=#{heroku_app_name}-#{environment}.herokuapp.com",
137
+ environment,
138
+ )
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def command_to_join_heroku_app(environment)
145
+ heroku_app_name = heroku_app_name_for(environment)
146
+
147
+ <<~SHELL
148
+ if heroku join --app #{heroku_app_name} &> /dev/null; then
149
+ git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true
150
+ printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n'
151
+ else
152
+ printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n'
153
+ fi
154
+ SHELL
155
+ end
156
+
157
+ def heroku_app_name
158
+ @app_builder.app_name.dasherize
159
+ end
160
+
161
+ def heroku_app_name_for(environment)
162
+ "#{heroku_app_name}-#{environment}"
163
+ end
164
+
165
+ def generate_secret
166
+ SecureRandom.hex(64)
167
+ end
168
+
169
+ def run_toolbelt_command(command, environment)
170
+ @app_builder.run("heroku #{command} --remote #{environment}")
171
+ end
172
+ end
173
+ end
174
+ end