os_suspenders 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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +13 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +133 -0
- data/LICENSE +21 -0
- data/NEWS.md +167 -0
- data/README.md +2 -0
- data/Rakefile +8 -0
- data/bin/rspec +16 -0
- data/bin/suspenders +18 -0
- data/lib/suspenders/actions.rb +35 -0
- data/lib/suspenders/app_builder.rb +352 -0
- data/lib/suspenders/generators/app_generator.rb +207 -0
- data/lib/suspenders/version.rb +3 -0
- data/lib/suspenders.rb +3 -0
- data/spec/fakes/bin/heroku +5 -0
- data/spec/fakes/bin/hub +5 -0
- data/spec/features/github_spec.rb +10 -0
- data/spec/features/heroku_spec.rb +13 -0
- data/spec/features/new_project_spec.rb +38 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/fake_github.rb +21 -0
- data/spec/support/fake_heroku.rb +36 -0
- data/spec/support/suspenders.rb +50 -0
- data/suspenders.gemspec +35 -0
- data/templates/Gemfile_clean +44 -0
- data/templates/Procfile +2 -0
- data/templates/README.md.erb +25 -0
- data/templates/_flashes.html.erb +5 -0
- data/templates/_javascript.html.erb +10 -0
- data/templates/application.css.scss +8 -0
- data/templates/background_jobs_rspec.rb +19 -0
- data/templates/bin_setup +32 -0
- data/templates/config_locales_en.yml +11 -0
- data/templates/database_cleaner_rspec.rb +21 -0
- data/templates/development_seeds.rb +13 -0
- data/templates/disable_xml_params.rb +3 -0
- data/templates/errors.rb +28 -0
- data/templates/factories_spec.rb +13 -0
- data/templates/factories_spec_rake_task.rb +15 -0
- data/templates/factory_girl_syntax_rspec.rb +3 -0
- data/templates/postgresql_database.yml.erb +11 -0
- data/templates/rack_timeout.rb +1 -0
- data/templates/sample.env +3 -0
- data/templates/secret_token.rb +10 -0
- data/templates/smtp.rb +10 -0
- data/templates/spec_helper.rb +29 -0
- data/templates/staging.rb +3 -0
- data/templates/suspenders_gitignore +13 -0
- data/templates/suspenders_layout.html.erb.erb +15 -0
- data/templates/unicorn.rb +29 -0
- metadata +195 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
class FakeHeroku
|
2
|
+
RECORDER = File.expand_path(File.join('..', '..', 'tmp', 'heroku_commands'), File.dirname(__FILE__))
|
3
|
+
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def run!
|
9
|
+
File.open(RECORDER, 'a') do |file|
|
10
|
+
file.puts @args.join(' ')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.clear!
|
15
|
+
FileUtils.rm_rf RECORDER
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.has_gem_included?(project_path, gem_name)
|
19
|
+
gemfile = File.open(File.join(project_path, 'Gemfile'), 'a')
|
20
|
+
|
21
|
+
File.foreach(gemfile).any?{ |line| line.match(/rails_12factor/) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.has_created_app_for?(remote_name)
|
25
|
+
app_name = "#{SuspendersTestHelpers::APP_NAME}-#{remote_name}"
|
26
|
+
expected_line = "create #{app_name} --remote=#{remote_name}\n"
|
27
|
+
|
28
|
+
File.foreach(RECORDER).any? { |line| line == expected_line }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.has_configured_vars?(remote_name, var)
|
32
|
+
File.foreach(RECORDER).any? do |line|
|
33
|
+
line =~ /^config:add #{var}=.+ --remote=#{remote_name}\n$/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module SuspendersTestHelpers
|
2
|
+
APP_NAME = 'dummy'
|
3
|
+
|
4
|
+
def remove_project_directory
|
5
|
+
FileUtils.rm_rf(project_path)
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_tmp_directory
|
9
|
+
FileUtils.mkdir_p(tmp_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run_suspenders(arguments = nil)
|
13
|
+
Dir.chdir(tmp_path) do
|
14
|
+
Bundler.with_clean_env do
|
15
|
+
ENV['TESTING'] = '1'
|
16
|
+
ENV['DISABLE_SPRING'] = '1'
|
17
|
+
|
18
|
+
%x(#{suspenders_bin} #{APP_NAME} #{arguments})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def drop_dummy_database
|
24
|
+
if File.exists?(project_path)
|
25
|
+
Dir.chdir(project_path) do
|
26
|
+
Bundler.with_clean_env do
|
27
|
+
`rake db:drop`
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def project_path
|
34
|
+
@project_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}")
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def tmp_path
|
40
|
+
@tmp_path ||= Pathname.new("#{root_path}/tmp")
|
41
|
+
end
|
42
|
+
|
43
|
+
def suspenders_bin
|
44
|
+
File.join(root_path, 'bin', 'suspenders')
|
45
|
+
end
|
46
|
+
|
47
|
+
def root_path
|
48
|
+
File.expand_path('../../../', __FILE__)
|
49
|
+
end
|
50
|
+
end
|
data/suspenders.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'suspenders/version'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.required_ruby_version = '>= 1.9.2'
|
8
|
+
s.add_dependency 'bundler', '~> 1.3'
|
9
|
+
s.add_dependency 'rails', '4.0.3'
|
10
|
+
s.add_development_dependency 'aruba', '~> 0.5.2'
|
11
|
+
s.add_development_dependency 'cucumber', '~> 1.2'
|
12
|
+
s.authors = ['thoughtbot/os']
|
13
|
+
s.date = Date.today.strftime('%Y-%m-%d')
|
14
|
+
|
15
|
+
s.description = <<-HERE
|
16
|
+
Suspenders is a base Rails project that you can upgrade. It is used by
|
17
|
+
thoughtbot to get a jump start on a working app. Use Suspenders if you're in a
|
18
|
+
rush to build something amazing; don't use it if you like missing deadlines.
|
19
|
+
HERE
|
20
|
+
|
21
|
+
s.email = 'owensims1@gmail.com'
|
22
|
+
s.executables = ['suspenders']
|
23
|
+
s.extra_rdoc_files = %w[README.md LICENSE]
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.homepage = 'http://github.com/owensims1/os_suspenders'
|
26
|
+
s.license = 'MIT'
|
27
|
+
s.name = 'os_suspenders'
|
28
|
+
s.rdoc_options = ['--charset=UTF-8']
|
29
|
+
s.require_paths = ['lib']
|
30
|
+
s.summary = "Generate a Rails app using thoughtbot's best practices."
|
31
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
32
|
+
s.version = Suspenders::VERSION
|
33
|
+
s.add_development_dependency 'rspec'
|
34
|
+
s.add_development_dependency 'capybara'
|
35
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'airbrake'
|
4
|
+
gem 'bourbon'
|
5
|
+
gem 'coffee-rails'
|
6
|
+
gem 'jquery-rails'
|
7
|
+
gem 'neat'
|
8
|
+
gem 'pg'
|
9
|
+
gem 'rack-timeout'
|
10
|
+
gem 'rails', '>= 4.0.3'
|
11
|
+
gem 'sass-rails'
|
12
|
+
gem 'simple_form'
|
13
|
+
gem 'uglifier'
|
14
|
+
gem 'unicorn'
|
15
|
+
gem 'devise'
|
16
|
+
|
17
|
+
group :development do
|
18
|
+
gem 'foreman'
|
19
|
+
gem 'spring'
|
20
|
+
gem 'spring-commands-rspec'
|
21
|
+
end
|
22
|
+
|
23
|
+
group :development, :test do
|
24
|
+
gem 'awesome_print'
|
25
|
+
gem 'dotenv-rails'
|
26
|
+
gem 'factory_girl_rails'
|
27
|
+
gem 'pry-rails'
|
28
|
+
gem 'rspec-rails', '>= 2.14'
|
29
|
+
end
|
30
|
+
|
31
|
+
group :test do
|
32
|
+
gem 'capybara-webkit', '>= 1.0.0'
|
33
|
+
gem 'database_cleaner'
|
34
|
+
gem 'shoulda-matchers'
|
35
|
+
gem 'simplecov', require: false
|
36
|
+
gem 'timecop'
|
37
|
+
gem 'webmock'
|
38
|
+
gem 'vcr'
|
39
|
+
end
|
40
|
+
|
41
|
+
group :staging, :production do
|
42
|
+
gem 'newrelic_rpm', '>= 3.6.7'
|
43
|
+
gem 'rails_12factor'
|
44
|
+
end
|
data/templates/Procfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
<%= app_name.humanize %>
|
2
|
+
<%= '=' * app_name.humanize.length %>
|
3
|
+
|
4
|
+
Getting Started
|
5
|
+
---------------
|
6
|
+
|
7
|
+
This repository comes equipped with a self-setup script:
|
8
|
+
|
9
|
+
% ./bin/setup
|
10
|
+
|
11
|
+
After setting up, you can run the application using [foreman]:
|
12
|
+
|
13
|
+
% foreman start
|
14
|
+
|
15
|
+
[foreman]: http://ddollar.github.io/foreman/
|
16
|
+
|
17
|
+
Guidelines
|
18
|
+
----------
|
19
|
+
|
20
|
+
Use the following guides for getting things done, programming well, and
|
21
|
+
programming in style.
|
22
|
+
|
23
|
+
* [Protocol](http://github.com/thoughtbot/guides/blob/master/protocol)
|
24
|
+
* [Best Practices](http://github.com/thoughtbot/guides/blob/master/best-practices)
|
25
|
+
* [Style](http://github.com/thoughtbot/guides/blob/master/style)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BackgroundJobs
|
2
|
+
def run_background_jobs_immediately
|
3
|
+
delay_jobs = Delayed::Worker.delay_jobs
|
4
|
+
Delayed::Worker.delay_jobs = false
|
5
|
+
yield
|
6
|
+
ensure
|
7
|
+
Delayed::Worker.delay_jobs = delay_jobs
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.around(:each, type: :feature) do |example|
|
13
|
+
run_background_jobs_immediately do
|
14
|
+
example.run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
config.include BackgroundJobs
|
19
|
+
end
|
data/templates/bin_setup
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env sh
|
2
|
+
|
3
|
+
# Set up Rails app. Run this script immediately after cloning the codebase.
|
4
|
+
# https://github.com/thoughtbot/guides/tree/master/protocol
|
5
|
+
|
6
|
+
# Exit if any subcommand fails
|
7
|
+
set -e
|
8
|
+
|
9
|
+
# Set up Ruby dependencies via Bundler
|
10
|
+
bundle install
|
11
|
+
|
12
|
+
# Set up database and add any development seed data
|
13
|
+
bundle exec rake dev:prime
|
14
|
+
|
15
|
+
# Add binstubs to PATH via export PATH=".git/safe/../../bin:$PATH" in ~/.zshenv
|
16
|
+
mkdir -p .git/safe
|
17
|
+
|
18
|
+
# Set up configurable environment variables
|
19
|
+
if [ ! -f .env ]; then
|
20
|
+
cp .sample.env .env
|
21
|
+
fi
|
22
|
+
|
23
|
+
# Pick a port for Foreman
|
24
|
+
echo "port: 7000" > .foreman
|
25
|
+
|
26
|
+
# Set up DNS via Pow
|
27
|
+
if [ -d ~/.pow ]
|
28
|
+
then
|
29
|
+
echo 7000 > ~/.pow/`basename $PWD`
|
30
|
+
else
|
31
|
+
echo "Pow not set up but the team uses it for this project. Setup: http://goo.gl/RaDPO"
|
32
|
+
fi
|
@@ -0,0 +1,21 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.before(:suite) do
|
3
|
+
DatabaseCleaner.clean_with(:deletion)
|
4
|
+
end
|
5
|
+
|
6
|
+
config.before(:each) do
|
7
|
+
DatabaseCleaner.strategy = :transaction
|
8
|
+
end
|
9
|
+
|
10
|
+
config.before(:each, :js => true) do
|
11
|
+
DatabaseCleaner.strategy = :deletion
|
12
|
+
end
|
13
|
+
|
14
|
+
config.before(:each) do
|
15
|
+
DatabaseCleaner.start
|
16
|
+
end
|
17
|
+
|
18
|
+
config.after(:each) do
|
19
|
+
DatabaseCleaner.clean
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
if Rails.env.development?
|
2
|
+
require 'factory_girl'
|
3
|
+
|
4
|
+
namespace :dev do
|
5
|
+
desc 'Seed data for development environment'
|
6
|
+
task prime: 'db:setup' do
|
7
|
+
FactoryGirl.find_definitions
|
8
|
+
include FactoryGirl::Syntax::Methods
|
9
|
+
|
10
|
+
# create(:user, email: 'user@example.com', password: 'password')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/templates/errors.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/smtp'
|
3
|
+
|
4
|
+
# Example:
|
5
|
+
# begin
|
6
|
+
# some http call
|
7
|
+
# rescue *HTTP_ERRORS => error
|
8
|
+
# notify_hoptoad error
|
9
|
+
# end
|
10
|
+
|
11
|
+
HTTP_ERRORS = [Timeout::Error,
|
12
|
+
Errno::EINVAL,
|
13
|
+
Errno::ECONNRESET,
|
14
|
+
EOFError,
|
15
|
+
Net::HTTPBadResponse,
|
16
|
+
Net::HTTPHeaderSyntaxError,
|
17
|
+
Net::ProtocolError]
|
18
|
+
|
19
|
+
SMTP_SERVER_ERRORS = [TimeoutError,
|
20
|
+
IOError,
|
21
|
+
Net::SMTPUnknownError,
|
22
|
+
Net::SMTPServerBusy,
|
23
|
+
Net::SMTPAuthenticationError]
|
24
|
+
|
25
|
+
SMTP_CLIENT_ERRORS = [Net::SMTPFatalError,
|
26
|
+
Net::SMTPSyntaxError]
|
27
|
+
|
28
|
+
SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'factories' do
|
4
|
+
FactoryGirl.factories.map(&:name).each do |factory_name|
|
5
|
+
specify "#{factory_name} factory is valid", :factory do
|
6
|
+
factory = build(factory_name)
|
7
|
+
|
8
|
+
if factory.respond_to?(:valid?)
|
9
|
+
expect(factory).to be_valid, factory.errors.full_messages.join(',')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
if defined?(RSpec)
|
2
|
+
task(:spec).clear
|
3
|
+
|
4
|
+
desc 'Run all specs'
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
6
|
+
t.rspec_opts = '--tag ~factory'
|
7
|
+
end
|
8
|
+
|
9
|
+
desc 'Run factory specs.'
|
10
|
+
RSpec::Core::RakeTask.new(:factory_specs) do |t|
|
11
|
+
t.pattern = './spec/models/factories_spec.rb'
|
12
|
+
end
|
13
|
+
|
14
|
+
task spec: :factory_specs
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Rack::Timeout.timeout = (ENV['TIMEOUT_IN_SECONDS'] || 5).to_i
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
2
|
+
# If you change this key, all old signed cookies will become invalid!
|
3
|
+
|
4
|
+
# Make sure the secret is at least 30 characters and all random,
|
5
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
6
|
+
# You can use `rake secret` to generate a secure secret key.
|
7
|
+
|
8
|
+
# Make sure your secret_key_base is kept private
|
9
|
+
# if you're sharing your code publicly.
|
10
|
+
<%= app_const %>.config.secret_key_base = ENV['SECRET_KEY_BASE']
|
data/templates/smtp.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
if Rails.env.staging? || Rails.env.production?
|
2
|
+
SMTP_SETTINGS = {
|
3
|
+
address: ENV.fetch('SMTP_ADDRESS'), # example: 'smtp.sendgrid.net'
|
4
|
+
authentication: :plain,
|
5
|
+
domain: ENV.fetch('SMTP_DOMAIN'), # example: 'this-app.com'
|
6
|
+
password: ENV.fetch('SMTP_PASSWORD'),
|
7
|
+
port: '587',
|
8
|
+
user_name: ENV.fetch('SMTP_USERNAME')
|
9
|
+
}
|
10
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start 'rails'
|
3
|
+
|
4
|
+
ENV['RAILS_ENV'] = 'test'
|
5
|
+
|
6
|
+
require File.expand_path('../../config/environment', __FILE__)
|
7
|
+
|
8
|
+
require 'rspec/rails'
|
9
|
+
require 'webmock/rspec'
|
10
|
+
|
11
|
+
Dir[Rails.root.join('spec/support/**/*.rb')].each { |file| require file }
|
12
|
+
|
13
|
+
module Features
|
14
|
+
# Extend this module in spec/support/features/*.rb
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.expect_with :rspec do |c|
|
19
|
+
c.syntax = :expect
|
20
|
+
end
|
21
|
+
|
22
|
+
config.include Features, type: :feature
|
23
|
+
config.infer_base_class_for_anonymous_controllers = false
|
24
|
+
config.order = 'random'
|
25
|
+
config.use_transactional_fixtures = false
|
26
|
+
end
|
27
|
+
|
28
|
+
Capybara.javascript_driver = :webkit
|
29
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<meta name="ROBOTS" content="NOODP" />
|
6
|
+
<title><%%= title %></title>
|
7
|
+
<%%= stylesheet_link_tag :application, :media => 'all' %>
|
8
|
+
<%%= csrf_meta_tags %>
|
9
|
+
</head>
|
10
|
+
<body class="<%%= body_class %>">
|
11
|
+
<%%= render 'flashes' -%>
|
12
|
+
<%%= yield %>
|
13
|
+
<%%= render 'javascript' %>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# https://devcenter.heroku.com/articles/rails-unicorn
|
2
|
+
|
3
|
+
worker_processes (ENV['WEB_CONCURRENCY'] || 3).to_i
|
4
|
+
timeout (ENV['WEB_TIMEOUT'] || 5).to_i
|
5
|
+
preload_app true
|
6
|
+
|
7
|
+
before_fork do |server, worker|
|
8
|
+
Signal.trap 'TERM' do
|
9
|
+
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
|
10
|
+
Process.kill 'QUIT', Process.pid
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined? ActiveRecord::Base
|
14
|
+
ActiveRecord::Base.connection.disconnect!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
after_fork do |server, worker|
|
19
|
+
Signal.trap 'TERM' do
|
20
|
+
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined? ActiveRecord::Base
|
24
|
+
config = Rails.application.config.database_configuration[Rails.env]
|
25
|
+
config['reaping_frequency'] = (ENV['DB_REAPING_FREQUENCY'] || 10).to_i
|
26
|
+
config['pool'] = (ENV['DB_POOL'] || 2).to_i
|
27
|
+
ActiveRecord::Base.establish_connection(config)
|
28
|
+
end
|
29
|
+
end
|