suspenders-ocs 0.0.1

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 (75) 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/CONTRIBUTING.md +51 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +21 -0
  8. data/NEWS.md +486 -0
  9. data/README.md +233 -0
  10. data/RELEASING.md +19 -0
  11. data/Rakefile +8 -0
  12. data/bin/rake +16 -0
  13. data/bin/rspec +16 -0
  14. data/bin/setup +13 -0
  15. data/bin/suspenders +23 -0
  16. data/lib/suspenders.rb +5 -0
  17. data/lib/suspenders/actions.rb +33 -0
  18. data/lib/suspenders/adapters/heroku.rb +125 -0
  19. data/lib/suspenders/app_builder.rb +523 -0
  20. data/lib/suspenders/generators/app_generator.rb +269 -0
  21. data/lib/suspenders/version.rb +5 -0
  22. data/spec/adapters/heroku_spec.rb +52 -0
  23. data/spec/fakes/bin/heroku +5 -0
  24. data/spec/fakes/bin/hub +5 -0
  25. data/spec/features/github_spec.rb +15 -0
  26. data/spec/features/heroku_spec.rb +93 -0
  27. data/spec/features/new_project_spec.rb +234 -0
  28. data/spec/spec_helper.rb +20 -0
  29. data/spec/support/fake_github.rb +21 -0
  30. data/spec/support/fake_heroku.rb +53 -0
  31. data/spec/support/suspenders.rb +58 -0
  32. data/suspenders.gemspec +34 -0
  33. data/templates/Gemfile.erb +63 -0
  34. data/templates/Procfile +2 -0
  35. data/templates/README.md.erb +28 -0
  36. data/templates/_analytics.html.erb +7 -0
  37. data/templates/_css_overrides.html.erb +8 -0
  38. data/templates/_flashes.html.erb +7 -0
  39. data/templates/_javascript.html.erb +12 -0
  40. data/templates/action_mailer.rb +5 -0
  41. data/templates/app.json.erb +42 -0
  42. data/templates/application.scss +9 -0
  43. data/templates/bin_deploy +12 -0
  44. data/templates/bin_setup +21 -0
  45. data/templates/bin_setup_review_app.erb +19 -0
  46. data/templates/browserslist +3 -0
  47. data/templates/bundler_audit.rake +12 -0
  48. data/templates/capybara_webkit.rb +5 -0
  49. data/templates/circle.yml.erb +6 -0
  50. data/templates/config_locales_en.yml.erb +19 -0
  51. data/templates/database_cleaner_rspec.rb +21 -0
  52. data/templates/dev.rake +12 -0
  53. data/templates/disable_xml_params.rb +1 -0
  54. data/templates/dotfiles/.ctags +2 -0
  55. data/templates/dotfiles/.env +13 -0
  56. data/templates/errors.rb +34 -0
  57. data/templates/factories.rb +2 -0
  58. data/templates/factory_girl_rspec.rb +3 -0
  59. data/templates/flashes_helper.rb +5 -0
  60. data/templates/hound.yml +14 -0
  61. data/templates/i18n.rb +3 -0
  62. data/templates/json_encoding.rb +1 -0
  63. data/templates/newrelic.yml.erb +34 -0
  64. data/templates/postgresql_database.yml.erb +21 -0
  65. data/templates/puma.rb +28 -0
  66. data/templates/rack_mini_profiler.rb +5 -0
  67. data/templates/rails_helper.rb +22 -0
  68. data/templates/secrets.yml +14 -0
  69. data/templates/shoulda_matchers_config_rspec.rb +6 -0
  70. data/templates/smtp.rb +9 -0
  71. data/templates/spec_helper.rb +29 -0
  72. data/templates/staging.rb +5 -0
  73. data/templates/suspenders_gitignore +13 -0
  74. data/templates/suspenders_layout.html.erb.erb +22 -0
  75. metadata +204 -0
data/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # Suspenders [![Build Status](https://secure.travis-ci.org/thoughtbot/suspenders.svg?branch=master)](http://travis-ci.org/thoughtbot/suspenders)
2
+
3
+ Suspenders is the base Rails application used at
4
+ [thoughtbot](https://thoughtbot.com/).
5
+
6
+ ![Suspenders boy](http://media.tumblr.com/1TEAMALpseh5xzf0Jt6bcwSMo1_400.png)
7
+
8
+ ## Installation
9
+
10
+ First install the suspenders gem:
11
+
12
+ gem install suspenders
13
+
14
+ Then run:
15
+
16
+ suspenders projectname
17
+
18
+ This will create a Rails app in `projectname` using the latest version of Rails.
19
+
20
+ ### Associated services
21
+
22
+ * Enable [Circle CI](https://circleci.com/) Continuous Integration
23
+ * Enable [GitHub auto deploys to Heroku staging and review
24
+ apps](https://dashboard.heroku.com/apps/app-name-staging/deploy/github).
25
+
26
+ ## Gemfile
27
+
28
+ To see the latest and greatest gems, look at Suspenders'
29
+ [Gemfile](templates/Gemfile.erb), which will be appended to the default
30
+ generated projectname/Gemfile.
31
+
32
+ It includes application gems like:
33
+
34
+ * [Autoprefixer Rails](https://github.com/ai/autoprefixer-rails) for CSS vendor prefixes
35
+ * [Bourbon](https://github.com/thoughtbot/bourbon) for Sass mixins
36
+ * [Bitters](https://github.com/thoughtbot/bitters) for scaffold application styles
37
+ * [Delayed Job](https://github.com/collectiveidea/delayed_job) for background
38
+ processing
39
+ * [Flutie](https://github.com/thoughtbot/flutie) for `page_title` and `body_class` view
40
+ helpers
41
+ * [High Voltage](https://github.com/thoughtbot/high_voltage) for static pages
42
+ * [Honeybadger](https://honeybadger.io) for exception notification
43
+ * [jQuery Rails](https://github.com/rails/jquery-rails) for jQuery
44
+ * [Neat](https://github.com/thoughtbot/neat) for semantic grids
45
+ * [New Relic RPM](https://github.com/newrelic/rpm) for monitoring performance
46
+ * [Normalize](https://necolas.github.io/normalize.css/) for resetting browser styles
47
+ * [Postgres](https://github.com/ged/ruby-pg) for access to the Postgres database
48
+ * [Rack Canonical Host](https://github.com/tylerhunt/rack-canonical-host) to
49
+ ensure all requests are served from the same domain
50
+ * [Rack Timeout](https://github.com/heroku/rack-timeout) to abort requests that are
51
+ taking too long
52
+ * [Recipient Interceptor](https://github.com/croaky/recipient_interceptor) to
53
+ avoid accidentally sending emails to real people from staging
54
+ * [Refills](https://github.com/thoughtbot/refills) for “copy-paste” components
55
+ and patterns based on Bourbon, Neat and Bitters
56
+ * [Simple Form](https://github.com/plataformatec/simple_form) for form markup
57
+ and style
58
+ * [Title](https://github.com/calebthompson/title) for storing titles in
59
+ translations
60
+ * [Puma](https://github.com/puma/puma) to serve HTTP requests
61
+
62
+ And development gems like:
63
+
64
+ * [Dotenv](https://github.com/bkeepers/dotenv) for loading environment variables
65
+ * [Pry Rails](https://github.com/rweng/pry-rails) for interactively exploring
66
+ objects
67
+ * [ByeBug](https://github.com/deivid-rodriguez/byebug) for interactively
68
+ debugging behavior
69
+ * [Bullet](https://github.com/flyerhzm/bullet) for help to kill N+1 queries and
70
+ unused eager loading
71
+ * [Bundler Audit](https://github.com/rubysec/bundler-audit) for scanning the
72
+ Gemfile for insecure dependencies based on published CVEs
73
+ * [Spring](https://github.com/rails/spring) for fast Rails actions via
74
+ pre-loading
75
+ * [Web Console](https://github.com/rails/web-console) for better debugging via
76
+ in-browser IRB consoles.
77
+ * [Quiet Assets](https://github.com/evrone/quiet_assets) for muting assets
78
+ pipeline log messages
79
+
80
+ And testing gems like:
81
+
82
+ * [Capybara](https://github.com/jnicklas/capybara) and
83
+ [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
84
+ integration testing
85
+ * [Factory Girl](https://github.com/thoughtbot/factory_girl) for test data
86
+ * [Formulaic](https://github.com/thoughtbot/formulaic) for integration testing
87
+ HTML forms
88
+ * [RSpec](https://github.com/rspec/rspec) for unit testing
89
+ * [RSpec Mocks](https://github.com/rspec/rspec-mocks) for stubbing and spying
90
+ * [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for common
91
+ RSpec matchers
92
+ * [Timecop](https://github.com/ferndopolis/timecop-console) for testing time
93
+
94
+ ## Other goodies
95
+
96
+ Suspenders also comes with:
97
+
98
+ * The [`./bin/setup`][setup] convention for new developer setup
99
+ * The `./bin/deploy` convention for deploying to Heroku
100
+ * Rails' flashes set up and in application layout
101
+ * A few nice time formats set up for localization
102
+ * `Rack::Deflater` to [compress responses with Gzip][compress]
103
+ * A [low database connection pool limit][pool]
104
+ * [Safe binstubs][binstub]
105
+ * [t() and l() in specs without prefixing with I18n][i18n]
106
+ * An automatically-created `SECRET_KEY_BASE` environment variable in all
107
+ environments
108
+ * Configuration for [CircleCI][circle] Continuous Integration (tests)
109
+ * Configuration for [Hound][hound] Continuous Integration (style)
110
+ * The analytics adapter [Segment][segment] (and therefore config for Google
111
+ Analytics, Intercom, Facebook Ads, Twitter Ads, etc.)
112
+
113
+ [setup]: https://robots.thoughtbot.com/bin-setup
114
+ [compress]: https://robots.thoughtbot.com/content-compression-with-rack-deflater
115
+ [pool]: https://devcenter.heroku.com/articles/concurrency-and-database-connections
116
+ [binstub]: https://github.com/thoughtbot/suspenders/pull/282
117
+ [i18n]: https://github.com/thoughtbot/suspenders/pull/304
118
+ [circle]: https://circleci.com/docs
119
+ [hound]: https://houndci.com
120
+ [segment]: https://segment.com
121
+
122
+ ## Heroku
123
+
124
+ You can optionally create Heroku staging and production apps:
125
+
126
+ suspenders app --heroku true
127
+
128
+ This:
129
+
130
+ * Creates a staging and production Heroku app
131
+ * Sets them as `staging` and `production` Git remotes
132
+ * Configures staging with `RACK_ENV` environment variable set
133
+ to `staging`
134
+ * Adds the [Rails Stdout Logging][logging-gem] gem
135
+ to configure the app to log to standard out,
136
+ which is how [Heroku's logging][heroku-logging] works.
137
+ * Creates a [Heroku Pipeline] for review apps
138
+
139
+ [logging-gem]: https://github.com/heroku/rails_stdout_logging
140
+ [heroku-logging]: https://devcenter.heroku.com/articles/logging#writing-to-your-log
141
+ [Heroku Pipeline]: https://devcenter.heroku.com/articles/pipelines
142
+
143
+ You can optionally specify alternate Heroku flags:
144
+
145
+ suspenders app \
146
+ --heroku true \
147
+ --heroku-flags "--region eu --addons newrelic,sendgrid,ssl"
148
+
149
+ See all possible Heroku flags:
150
+
151
+ heroku help create
152
+
153
+ ## Git
154
+
155
+ This will initialize a new git repository for your Rails app. You can
156
+ bypass this with the `--skip-git` option:
157
+
158
+ suspenders app --skip-git true
159
+
160
+ ## GitHub
161
+
162
+ You can optionally create a GitHub repository for the suspended Rails app. It
163
+ requires that you have [Hub](https://github.com/github/hub) on your system:
164
+
165
+ curl http://hub.github.com/standalone -sLo ~/bin/hub && chmod +x ~/bin/hub
166
+ suspenders app --github organization/project
167
+
168
+ This has the same effect as running:
169
+
170
+ hub create organization/project
171
+
172
+ ## Spring
173
+
174
+ Suspenders uses [spring](https://github.com/rails/spring) by default.
175
+ It makes Rails applications load faster, but it might introduce confusing issues
176
+ around stale code not being refreshed.
177
+ If you think your application is running old code, run `spring stop`.
178
+ And if you'd rather not use spring, add `DISABLE_SPRING=1` to your login file.
179
+
180
+ ## Dependencies
181
+
182
+ Suspenders requires the latest version of Ruby.
183
+
184
+ Some gems included in Suspenders have native extensions. You should have GCC
185
+ installed on your machine before generating an app with Suspenders.
186
+
187
+ Use [OS X GCC Installer](https://github.com/kennethreitz/osx-gcc-installer/) for
188
+ Snow Leopard (OS X 10.6).
189
+
190
+ Use [Command Line Tools for XCode](https://developer.apple.com/downloads/index.action)
191
+ for Lion (OS X 10.7) or Mountain Lion (OS X 10.8).
192
+
193
+ We use [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
194
+ full-stack JavaScript integration testing. It requires QT. Instructions for
195
+ installing QT are
196
+ [here](https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit).
197
+
198
+ PostgreSQL needs to be installed and running for the `db:create` rake task.
199
+
200
+ ## Issues
201
+
202
+ If you have problems, please create a
203
+ [GitHub Issue](https://github.com/thoughtbot/suspenders/issues).
204
+
205
+ ## Contributing
206
+
207
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
208
+
209
+ Thank you, [contributors]!
210
+
211
+ [contributors]: https://github.com/thoughtbot/suspenders/graphs/contributors
212
+
213
+ ## License
214
+
215
+ Suspenders is Copyright © 2008-2016 thoughtbot.
216
+ It is free software,
217
+ and may be redistributed under the terms specified in the [LICENSE] file.
218
+
219
+ [LICENSE]: LICENSE
220
+
221
+ ## About thoughtbot
222
+
223
+ ![thoughtbot](https://thoughtbot.com/logo.png)
224
+
225
+ Suspenders is maintained and funded by thoughtbot, inc.
226
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
227
+
228
+ We love open source software!
229
+ See [our other projects][community].
230
+ We are [available for hire][hire].
231
+
232
+ [community]: https://thoughtbot.com/community?utm_source=github
233
+ [hire]: https://thoughtbot.com?utm_source=github
data/RELEASING.md ADDED
@@ -0,0 +1,19 @@
1
+ # Releasing
2
+
3
+ 1. Update `lib/suspenders/version.rb` file accordingly.
4
+ 2. Update `NEWS.md` to reflect the changes since last release.
5
+ 3. Commit changes. There shouldn't be code changes, and thus CI doesn't need to
6
+ run, you can then add `[ci skip]` to the commit message.
7
+ 4. Tag the release: `git tag vVERSION -a`. The tag message should contain the
8
+ appropriate `NEWS.md` subsection.
9
+ 5. Push changes: `git push --tags`
10
+ 6. Build and publish to rubygems:
11
+ ```bash
12
+ gem build suspenders.gemspec
13
+ gem push suspenders-*.gem
14
+ ```
15
+
16
+ 7. Add a new GitHub release:
17
+ https://github.com/thoughtbot/suspenders/releases/new?tag=vVERSION
18
+ 8. Announce the new release, making sure to say "thank you" to the contributors
19
+ who helped shape this version!
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
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
data/bin/suspenders ADDED
@@ -0,0 +1,23 @@
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 'suspenders'
8
+
9
+ if ARGV.empty?
10
+ puts "Please provide a path for the new application"
11
+ puts
12
+ puts "See --help for more info"
13
+ exit 0
14
+ elsif ['-v', '--version'].include? ARGV[0]
15
+ puts Suspenders::VERSION
16
+ exit 0
17
+ end
18
+
19
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
20
+ Suspenders::AppGenerator.source_root templates_root
21
+ Suspenders::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
22
+
23
+ Suspenders::AppGenerator.start
data/lib/suspenders.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'suspenders/version'
2
+ require 'suspenders/generators/app_generator'
3
+ require 'suspenders/actions'
4
+ require "suspenders/adapters/heroku"
5
+ require 'suspenders/app_builder'
@@ -0,0 +1,33 @@
1
+ module Suspenders
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 action_mailer_host(rails_env, host)
13
+ config = "config.action_mailer.default_url_options = { host: #{host} }"
14
+ configure_environment(rails_env, config)
15
+ end
16
+
17
+ def configure_application_file(config)
18
+ inject_into_file(
19
+ "config/application.rb",
20
+ "\n\n #{config}",
21
+ before: "\n end"
22
+ )
23
+ end
24
+
25
+ def configure_environment(rails_env, config)
26
+ inject_into_file(
27
+ "config/environments/#{rails_env}.rb",
28
+ "\n\n #{config}",
29
+ before: "\nend"
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,125 @@
1
+ module Suspenders
2
+ module Adapters
3
+ class Heroku
4
+ def initialize(app_builder)
5
+ @app_builder = app_builder
6
+ end
7
+
8
+ def set_heroku_remotes
9
+ remotes = <<-SHELL.strip_heredoc
10
+ #{command_to_join_heroku_app('staging')}
11
+ #{command_to_join_heroku_app('production')}
12
+
13
+ git config heroku.remote staging
14
+ SHELL
15
+
16
+ app_builder.append_file "bin/setup", remotes
17
+ end
18
+
19
+ def set_up_heroku_specific_gems
20
+ app_builder.inject_into_file(
21
+ "Gemfile",
22
+ %{\n\s\sgem "rails_stdout_logging"},
23
+ after: /group :staging, :production do/,
24
+ )
25
+ end
26
+
27
+ def create_staging_heroku_app(flags)
28
+ rack_env = "RACK_ENV=staging"
29
+ app_name = heroku_app_name_for("staging")
30
+
31
+ run_toolbelt_command "create #{app_name} #{flags}", "staging"
32
+ run_toolbelt_command "config:add #{rack_env}", "staging"
33
+ end
34
+
35
+ def create_production_heroku_app(flags)
36
+ app_name = heroku_app_name_for("production")
37
+
38
+ run_toolbelt_command "create #{app_name} #{flags}", "production"
39
+ end
40
+
41
+ def set_heroku_rails_secrets
42
+ %w(staging production).each do |environment|
43
+ run_toolbelt_command(
44
+ "config:add SECRET_KEY_BASE=#{generate_secret}",
45
+ environment,
46
+ )
47
+ end
48
+ end
49
+
50
+ def provide_review_apps_setup_script
51
+ app_builder.template(
52
+ "bin_setup_review_app.erb",
53
+ "bin/setup_review_app",
54
+ force: true,
55
+ )
56
+ app_builder.run "chmod a+x bin/setup_review_app"
57
+ end
58
+
59
+ def create_heroku_pipelines_config_file
60
+ app_builder.template "app.json.erb", "app.json"
61
+ end
62
+
63
+ def create_heroku_pipeline
64
+ pipelines_plugin = `heroku plugins | grep pipelines`
65
+ if pipelines_plugin.empty?
66
+ puts "You need heroku pipelines plugin. Run: heroku plugins:install heroku-pipelines"
67
+ exit 1
68
+ end
69
+
70
+ heroku_app_name = app_builder.app_name.dasherize
71
+ run_toolbelt_command(
72
+ "pipelines:create #{heroku_app_name} \
73
+ -a #{heroku_app_name}-staging --stage staging",
74
+ "staging",
75
+ )
76
+
77
+ run_toolbelt_command(
78
+ "pipelines:add #{heroku_app_name} \
79
+ -a #{heroku_app_name}-production --stage production",
80
+ "production",
81
+ )
82
+ end
83
+
84
+ def set_heroku_serve_static_files
85
+ %w(staging production).each do |environment|
86
+ run_toolbelt_command(
87
+ "config:add RAILS_SERVE_STATIC_FILES=true",
88
+ environment,
89
+ )
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ attr_reader :app_builder
96
+
97
+ def command_to_join_heroku_app(environment)
98
+ heroku_app_name = heroku_app_name_for(environment)
99
+ <<-SHELL
100
+
101
+ if heroku join --app #{heroku_app_name} &> /dev/null; then
102
+ git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true
103
+ printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n'
104
+ else
105
+ printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n'
106
+ fi
107
+ SHELL
108
+ end
109
+
110
+ def heroku_app_name_for(environment)
111
+ "#{app_builder.app_name.dasherize}-#{environment}"
112
+ end
113
+
114
+ def generate_secret
115
+ SecureRandom.hex(64)
116
+ end
117
+
118
+ def run_toolbelt_command(command, environment)
119
+ app_builder.run(
120
+ "heroku #{command} --remote #{environment}",
121
+ )
122
+ end
123
+ end
124
+ end
125
+ end