suspenders 20230113.0 → 20250317.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.
- checksums.yaml +4 -4
- data/README.md +98 -170
- data/Rakefile +17 -0
- data/lib/generators/suspenders/accessibility_generator.rb +24 -0
- data/lib/generators/suspenders/advisories_generator.rb +32 -0
- data/lib/generators/suspenders/ci_generator.rb +54 -0
- data/lib/generators/suspenders/email_generator.rb +56 -0
- data/lib/generators/suspenders/environments/development_generator.rb +50 -0
- data/lib/generators/suspenders/environments/production_generator.rb +27 -0
- data/lib/generators/suspenders/environments/test_generator.rb +39 -0
- data/lib/generators/suspenders/factories_generator.rb +64 -0
- data/lib/generators/suspenders/inline_svg_generator.rb +24 -0
- data/lib/generators/suspenders/install/web_generator.rb +85 -0
- data/lib/generators/suspenders/jobs_generator.rb +34 -0
- data/lib/generators/suspenders/lint_generator.rb +94 -0
- data/lib/generators/suspenders/prerequisites_generator.rb +19 -0
- data/lib/generators/suspenders/rake_generator.rb +25 -0
- data/lib/generators/suspenders/setup_generator.rb +14 -0
- data/lib/generators/suspenders/styles_generator.rb +84 -0
- data/lib/generators/suspenders/tasks_generator.rb +20 -0
- data/lib/generators/suspenders/testing_generator.rb +113 -0
- data/lib/generators/suspenders/views_generator.rb +38 -0
- data/lib/generators/templates/ci/ci.yml.tt +148 -0
- data/lib/generators/templates/email/email_interceptor.rb +11 -0
- data/lib/generators/templates/factories/factories_spec.rb +7 -0
- data/lib/generators/templates/factories/factories_test.rb +9 -0
- data/lib/generators/templates/install/web/CONTRIBUTING.md +94 -0
- data/lib/generators/templates/lint/config_better_html.yml +2 -0
- data/lib/generators/templates/lint/config_initializers_better_html.rb +9 -0
- data/lib/generators/templates/lint/erb-lint.yml +63 -0
- data/lib/generators/templates/lint/erblint.rake +47 -0
- data/lib/generators/templates/lint/eslintrc.json +7 -0
- data/lib/generators/templates/lint/package.json +4 -0
- data/lib/generators/templates/lint/prettierignore +1 -0
- data/lib/generators/templates/lint/prettierrc +11 -0
- data/lib/generators/templates/lint/rubocop.yml.tt +7 -0
- data/lib/generators/templates/prerequisites/node-version.tt +1 -0
- data/lib/generators/templates/setup/bin_setup.rb +39 -0
- data/lib/generators/templates/styles/postcss.config.js +11 -0
- data/lib/generators/templates/testing/driver.rb +5 -0
- data/lib/generators/templates/views/flashes.html.erb +7 -0
- data/lib/install/web.rb +70 -0
- data/lib/suspenders/cleanup/generate_readme.rb +165 -0
- data/lib/suspenders/cleanup/organize_gemfile.rb +134 -0
- data/lib/suspenders/engine.rb +5 -0
- data/lib/suspenders/generators.rb +126 -0
- data/lib/suspenders/railtie.rb +4 -0
- data/lib/suspenders/version.rb +4 -6
- data/lib/suspenders.rb +9 -33
- data/lib/tasks/suspenders.rake +37 -0
- metadata +81 -173
- data/.ruby-version +0 -1
- data/CONTRIBUTING.md +0 -59
- data/GOALS.md +0 -65
- data/LICENSE +0 -21
- data/NEWS.md +0 -738
- data/RELEASING.md +0 -18
- data/bin/suspenders +0 -50
- data/docs/heroku_deploy.md +0 -19
- data/docs/rails_7.md +0 -5
- data/lib/suspenders/actions/strip_comments_action.rb +0 -254
- data/lib/suspenders/actions.rb +0 -106
- data/lib/suspenders/adapters/heroku.rb +0 -136
- data/lib/suspenders/app_builder.rb +0 -267
- data/lib/suspenders/exit_on_failure.rb +0 -19
- data/lib/suspenders/generators/accessibility_generator.rb +0 -12
- data/lib/suspenders/generators/advisories_generator.rb +0 -15
- data/lib/suspenders/generators/analytics_generator.rb +0 -24
- data/lib/suspenders/generators/app_generator.rb +0 -215
- data/lib/suspenders/generators/base.rb +0 -60
- data/lib/suspenders/generators/ci_generator.rb +0 -32
- data/lib/suspenders/generators/db_optimizations_generator.rb +0 -18
- data/lib/suspenders/generators/factories_generator.rb +0 -22
- data/lib/suspenders/generators/forms_generator.rb +0 -18
- data/lib/suspenders/generators/inline_svg_generator.rb +0 -14
- data/lib/suspenders/generators/jobs_generator.rb +0 -37
- data/lib/suspenders/generators/js_driver_generator.rb +0 -18
- data/lib/suspenders/generators/json_generator.rb +0 -14
- data/lib/suspenders/generators/lint_generator.rb +0 -14
- data/lib/suspenders/generators/production/compression_generator.rb +0 -14
- data/lib/suspenders/generators/production/deployment_generator.rb +0 -16
- data/lib/suspenders/generators/production/email_generator.rb +0 -34
- data/lib/suspenders/generators/production/force_tls_generator.rb +0 -11
- data/lib/suspenders/generators/production/manifest_generator.rb +0 -25
- data/lib/suspenders/generators/production/single_redirect.rb +0 -15
- data/lib/suspenders/generators/production/timeout_generator.rb +0 -22
- data/lib/suspenders/generators/profiler_generator.rb +0 -35
- data/lib/suspenders/generators/runner_generator.rb +0 -48
- data/lib/suspenders/generators/staging/pull_requests_generator.rb +0 -25
- data/lib/suspenders/generators/static_generator.rb +0 -14
- data/lib/suspenders/generators/stylelint_generator.rb +0 -71
- data/lib/suspenders/generators/stylesheet_base_generator.rb +0 -15
- data/lib/suspenders/generators/testing_generator.rb +0 -43
- data/lib/suspenders/generators/views_generator.rb +0 -25
- data/templates/Gemfile.erb +0 -49
- data/templates/Procfile +0 -2
- data/templates/README.md.erb +0 -28
- data/templates/_analytics.html.erb +0 -8
- data/templates/_css_overrides.html.erb +0 -7
- data/templates/_flashes.html.erb +0 -7
- data/templates/active_job.rb +0 -14
- data/templates/application.postcss.css +0 -1
- data/templates/bin_auto_migrate +0 -5
- data/templates/bin_deploy +0 -10
- data/templates/bin_setup +0 -28
- data/templates/bin_setup_review_app.erb +0 -21
- data/templates/bin_yarn +0 -18
- data/templates/bundler_audit.rake +0 -4
- data/templates/capybara_silence_puma.rb +0 -1
- data/templates/chromedriver.rb +0 -27
- data/templates/circle.yml.erb +0 -6
- data/templates/config_locales_en.yml.erb +0 -19
- data/templates/descriptions/advisories.md +0 -5
- data/templates/descriptions/analytics.md +0 -4
- data/templates/descriptions/ci.md +0 -4
- data/templates/descriptions/compression.md +0 -4
- data/templates/descriptions/db_optimizations.md +0 -2
- data/templates/descriptions/deployment.md +0 -5
- data/templates/descriptions/email.md +0 -9
- data/templates/descriptions/factories.md +0 -12
- data/templates/descriptions/force_tls.md +0 -1
- data/templates/descriptions/forms.md +0 -1
- data/templates/descriptions/inline_svg.md +0 -2
- data/templates/descriptions/jobs.md +0 -3
- data/templates/descriptions/js_driver.md +0 -4
- data/templates/descriptions/json.md +0 -1
- data/templates/descriptions/lint.md +0 -3
- data/templates/descriptions/manifest.md +0 -2
- data/templates/descriptions/profiler.md +0 -7
- data/templates/descriptions/pull_requests.md +0 -4
- data/templates/descriptions/runner.md +0 -10
- data/templates/descriptions/single_redirect.md +0 -1
- data/templates/descriptions/static.md +0 -5
- data/templates/descriptions/stylelint.md +0 -3
- data/templates/descriptions/stylesheet_base.md +0 -1
- data/templates/descriptions/testing.md +0 -9
- data/templates/descriptions/timeout.md +0 -4
- data/templates/descriptions/views.md +0 -8
- data/templates/email.rb +0 -3
- data/templates/errors.rb +0 -35
- data/templates/flashes_helper.rb +0 -5
- data/templates/hound.yml +0 -15
- data/templates/json_encoding.rb +0 -1
- data/templates/oj.rb +0 -3
- data/templates/partials/ci_simplecov.rb +0 -14
- data/templates/partials/db_optimizations_configuration.rb +0 -7
- data/templates/partials/deployment_readme.md +0 -8
- data/templates/partials/email_smtp.rb +0 -2
- data/templates/partials/profiler_readme.md +0 -8
- data/templates/partials/pull_requests_config.rb +0 -5
- data/templates/partials/runner_readme.md +0 -31
- data/templates/partials/runner_setup.rb +0 -2
- data/templates/postcss.config.js +0 -8
- data/templates/postgresql_database.yml.erb +0 -20
- data/templates/rack_mini_profiler.rb +0 -7
- data/templates/rails_helper.rb +0 -25
- data/templates/sample_env +0 -12
- data/templates/secrets.yml +0 -8
- data/templates/smtp.rb +0 -9
- data/templates/spec_helper.rb +0 -25
- data/templates/suspenders_gitignore +0 -18
- data/templates/suspenders_layout.html.erb.erb +0 -23
- /data/{templates → lib/generators/templates/factories}/factories.rb +0 -0
- /data/{templates → lib/generators/templates/factories}/factory_bot_rspec.rb +0 -0
- /data/{templates → lib/generators/templates/inline_svg}/inline_svg.rb +0 -0
- /data/{templates → lib/generators/templates/lint}/stylelintrc.json +0 -0
- /data/{templates → lib/generators/templates/tasks}/dev.rake +0 -0
- /data/{templates → lib/generators/templates/testing}/action_mailer.rb +0 -0
- /data/{templates → lib/generators/templates/testing}/i18n.rb +0 -0
- /data/{templates/shoulda_matchers_config_rspec.rb → lib/generators/templates/testing/shoulda_matchers.rb} +0 -0
data/RELEASING.md
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# Releasing
|
2
|
-
|
3
|
-
1. Update `NEWS.md` to reflect the changes since last release.
|
4
|
-
2. Update `lib/suspenders/version.rb` file accordingly.
|
5
|
-
3. Commit changes. There shouldn't be code changes, and thus CI doesn't need to
|
6
|
-
run; you can add `[ci skip]` to the commit message.
|
7
|
-
4. Tag the release: `git tag vVERSION -a -s`. 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
|
-
```sh
|
12
|
-
gem build suspenders.gemspec
|
13
|
-
gem push suspenders-*.gem
|
14
|
-
```
|
15
|
-
7. Add a new GitHub release:
|
16
|
-
https://github.com/thoughtbot/suspenders/releases/new?tag=vVERSION
|
17
|
-
8. Announce the new release, making sure to thank the contributors who helped
|
18
|
-
shape this version!
|
data/bin/suspenders
DELETED
@@ -1,50 +0,0 @@
|
|
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
|
-
activate_rails_version = ->(rails_version) do
|
8
|
-
rails_bin_path = Gem.activate_bin_path("railties", "rails", rails_version)
|
9
|
-
rails_path = File.expand_path("../..", rails_bin_path)
|
10
|
-
$LOAD_PATH.unshift(rails_path)
|
11
|
-
end
|
12
|
-
|
13
|
-
if str = ARGV.first
|
14
|
-
str = str.b[/\A_(.*)_\z/, 1]
|
15
|
-
|
16
|
-
if str && Gem::Version.correct?(str)
|
17
|
-
rails_version = str
|
18
|
-
ARGV.shift
|
19
|
-
|
20
|
-
begin
|
21
|
-
activate_rails_version.call(rails_version)
|
22
|
-
rescue Gem::GemNotFoundException
|
23
|
-
abort "Suspenders error: Unable to find Rails version #{rails_version}"
|
24
|
-
end
|
25
|
-
else
|
26
|
-
require "suspenders/version"
|
27
|
-
|
28
|
-
spec = Gem::Specification.find_by_name("rails", Suspenders::RAILS_VERSION)
|
29
|
-
|
30
|
-
activate_rails_version.call(spec.version.to_s)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
require "suspenders"
|
35
|
-
|
36
|
-
if ARGV.empty?
|
37
|
-
puts "Please provide a path for the new application"
|
38
|
-
puts
|
39
|
-
puts "See --help for more info"
|
40
|
-
exit 0
|
41
|
-
elsif ["-v", "--version"].include? ARGV[0]
|
42
|
-
puts Suspenders::VERSION
|
43
|
-
exit 0
|
44
|
-
end
|
45
|
-
|
46
|
-
templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
|
47
|
-
Suspenders::AppGenerator.source_root templates_root
|
48
|
-
Suspenders::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
|
49
|
-
|
50
|
-
Suspenders::AppGenerator.start
|
data/docs/heroku_deploy.md
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# Deploying to Heroku
|
2
|
-
|
3
|
-
## Setup
|
4
|
-
|
5
|
-
Deploying to Heroku requires two additional steps:
|
6
|
-
|
7
|
-
1. Set the following environment variables:
|
8
|
-
|
9
|
-
- `ASSET_HOST`: `siteURL.herokuapp.com`
|
10
|
-
- `APPLICATION_HOST`: `siteURL.herokuapp.com`
|
11
|
-
- `SMTP_ADDRESS`: `smtp.example.com`
|
12
|
-
- `SMTP_DOMAIN`: `example.com`
|
13
|
-
- `SMTP_USERNAME`: `username`
|
14
|
-
- `SMTP_PASSWORD`: `password`
|
15
|
-
- `AUTO_MIGRATE_DB`: `true`
|
16
|
-
|
17
|
-
## Execution
|
18
|
-
|
19
|
-
- Use the `./bin/deploy` convention for deploying to Heroku
|
data/docs/rails_7.md
DELETED
@@ -1,254 +0,0 @@
|
|
1
|
-
require "parser/current"
|
2
|
-
|
3
|
-
module Suspenders
|
4
|
-
module Actions
|
5
|
-
class StripCommentsAction
|
6
|
-
class << self
|
7
|
-
def call(source)
|
8
|
-
parser = Parser::CurrentRuby.new
|
9
|
-
|
10
|
-
source
|
11
|
-
.then { |s| strip_comments(s, parser) }
|
12
|
-
.then { |s| strip_trailing_whitespace(s) }
|
13
|
-
.then { |s| strip_dup_newlines(s) }
|
14
|
-
.then { |s| strip_leading_scope_newlines(s, parser) }
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def strip_comments(source, parser)
|
20
|
-
StripComments.call(source, parser.reset)
|
21
|
-
end
|
22
|
-
|
23
|
-
def strip_trailing_whitespace(source)
|
24
|
-
source.gsub(/[[:blank:]]+$/, "")
|
25
|
-
end
|
26
|
-
|
27
|
-
def strip_dup_newlines(source)
|
28
|
-
source.gsub(/\n{2,}/, "\n\n")
|
29
|
-
end
|
30
|
-
|
31
|
-
def strip_leading_scope_newlines(source, parser)
|
32
|
-
StripLeadingScopeNewlines.call(source, parser.reset)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Strips full-line and inline comments from a buffer but does
|
37
|
-
# not remove whitespaces or newlines after the fact. Example
|
38
|
-
# input:
|
39
|
-
#
|
40
|
-
# MyGem.application.configure do |config|
|
41
|
-
# # Full-line comment
|
42
|
-
# config.option1 = :value # Inline comment
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# The output is:
|
46
|
-
#
|
47
|
-
# MyGem.application.configure do |config|
|
48
|
-
#
|
49
|
-
# config.option1 = :value
|
50
|
-
# end
|
51
|
-
class StripComments
|
52
|
-
class << self
|
53
|
-
def call(source, parser)
|
54
|
-
buffer = Parser::Source::Buffer.new(nil, source: source)
|
55
|
-
rewriter = Parser::Source::TreeRewriter.new(buffer)
|
56
|
-
|
57
|
-
_, comments = parser.parse_with_comments(buffer)
|
58
|
-
|
59
|
-
comments.each do |comment|
|
60
|
-
strip_comment(comment, buffer, rewriter)
|
61
|
-
end
|
62
|
-
|
63
|
-
rewriter.process
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def strip_comment(comment, buffer, rewriter)
|
69
|
-
expr = comment.location.expression
|
70
|
-
|
71
|
-
if full_line_comment?(expr)
|
72
|
-
expr = full_line_comment_expr(expr, buffer)
|
73
|
-
end
|
74
|
-
|
75
|
-
rewriter.remove(expr)
|
76
|
-
end
|
77
|
-
|
78
|
-
def full_line_comment_expr(expr, buffer)
|
79
|
-
pos = BackwardStringScanner.beginning_of_line_pos(expr, expr.begin_pos)
|
80
|
-
|
81
|
-
Parser::Source::Range.new(buffer, pos, expr.end_pos + 1)
|
82
|
-
end
|
83
|
-
|
84
|
-
def full_line_comment?(expr)
|
85
|
-
expr.source == expr.source_line.lstrip
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# A tiny, non-stateful backward string scanner somewhat inspired
|
91
|
-
# by Ruby's StringScanner. Ruby's StringScanner is unable to
|
92
|
-
# seek backward on a string.
|
93
|
-
class BackwardStringScanner
|
94
|
-
def self.beginning_of_line_pos(expr, initial_pos)
|
95
|
-
skip_before(expr, initial_pos) { |char| char == "\n" }
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.skip_before(expr, initial_pos, &block)
|
99
|
-
skip_until(expr, initial_pos, -1, &block)
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.skip_until(expr, initial_pos, lookup_inc = 0)
|
103
|
-
pos = initial_pos
|
104
|
-
|
105
|
-
loop do
|
106
|
-
break if pos.zero?
|
107
|
-
char = expr.source_buffer.source[pos + lookup_inc]
|
108
|
-
break if yield(char)
|
109
|
-
pos -= 1
|
110
|
-
end
|
111
|
-
|
112
|
-
pos
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# The intent of this class is purely aesthetic: remove leading
|
117
|
-
# newlines inside of code scopes like blocks and begin/end.
|
118
|
-
# Example input:
|
119
|
-
#
|
120
|
-
# module MyGem
|
121
|
-
#
|
122
|
-
# MyGem.application.configure do |config|
|
123
|
-
#
|
124
|
-
# config.option1 = true
|
125
|
-
#
|
126
|
-
# config.option2 = false
|
127
|
-
# end
|
128
|
-
# end
|
129
|
-
#
|
130
|
-
# The output is:
|
131
|
-
#
|
132
|
-
# module MyGem
|
133
|
-
# MyGem.application.configure do |config|
|
134
|
-
# config.option1 = true
|
135
|
-
#
|
136
|
-
# config.option2 = false
|
137
|
-
# end
|
138
|
-
# end
|
139
|
-
class StripLeadingScopeNewlines
|
140
|
-
def self.call(source, parser)
|
141
|
-
buffer = Parser::Source::Buffer.new(nil, source: source)
|
142
|
-
ast = parser.parse(buffer)
|
143
|
-
|
144
|
-
LeadingNewlineStripRewriter.new.rewrite(buffer, ast).lstrip
|
145
|
-
end
|
146
|
-
|
147
|
-
class LeadingNewlineStripRewriter < Parser::TreeRewriter
|
148
|
-
def on_module(node)
|
149
|
-
strip_newline_before(node.children[1])
|
150
|
-
strip_newline_after(node.children.last)
|
151
|
-
|
152
|
-
super
|
153
|
-
end
|
154
|
-
|
155
|
-
def on_class(node)
|
156
|
-
strip_newline_before(node.children[2])
|
157
|
-
strip_newline_after(node.children.last)
|
158
|
-
|
159
|
-
super
|
160
|
-
end
|
161
|
-
|
162
|
-
def on_begin(node)
|
163
|
-
handle_begin(node)
|
164
|
-
|
165
|
-
super
|
166
|
-
end
|
167
|
-
|
168
|
-
def on_kwbegin(node)
|
169
|
-
strip_newline_before(node.children[0])
|
170
|
-
strip_newline_after(node.children.last)
|
171
|
-
|
172
|
-
handle_begin(node)
|
173
|
-
|
174
|
-
super
|
175
|
-
end
|
176
|
-
|
177
|
-
def on_block(node)
|
178
|
-
strip_newline_before(node.children[2])
|
179
|
-
strip_newline_after(node.children.last)
|
180
|
-
|
181
|
-
super
|
182
|
-
end
|
183
|
-
|
184
|
-
private
|
185
|
-
|
186
|
-
def handle_begin(node)
|
187
|
-
strip_blank_lines_between_setter_calls(node.children)
|
188
|
-
|
189
|
-
node.children.each do |child_node|
|
190
|
-
send("on_#{child_node.type}", child_node)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def strip_blank_lines_between_setter_calls(children)
|
195
|
-
pairs = children.each_cons(2).to_a
|
196
|
-
|
197
|
-
pairs.each do |(node_before, node_after)|
|
198
|
-
if setter_call?(node_before) && setter_call?(node_after)
|
199
|
-
strip_newline_before(node_after)
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def setter_call?(node)
|
205
|
-
node.children[1].to_s.end_with?("=")
|
206
|
-
end
|
207
|
-
|
208
|
-
def strip_newline_before(node)
|
209
|
-
return if node.nil?
|
210
|
-
|
211
|
-
expr = node.location.expression
|
212
|
-
end_pos = find_end_pos(expr, expr.begin_pos)
|
213
|
-
begin_pos = find_begin_pos(expr, end_pos)
|
214
|
-
|
215
|
-
strip_source_range(expr, begin_pos, end_pos)
|
216
|
-
end
|
217
|
-
|
218
|
-
def strip_newline_after(node)
|
219
|
-
return if node.nil?
|
220
|
-
|
221
|
-
expr = node.location.expression
|
222
|
-
source = expr.source_buffer.source
|
223
|
-
|
224
|
-
if source[expr.end_pos + 1] == "\n"
|
225
|
-
strip_source_range(expr, expr.end_pos, expr.end_pos + 1)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def find_end_pos(expr, begin_pos)
|
230
|
-
BackwardStringScanner.skip_until(expr, begin_pos) do |char|
|
231
|
-
char == "\n"
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
def find_begin_pos(expr, end_pos)
|
236
|
-
BackwardStringScanner.skip_before(expr, end_pos) do |char|
|
237
|
-
char != "\n" && char != " "
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
def strip_source_range(expr, begin_pos, end_pos)
|
242
|
-
remove(
|
243
|
-
Parser::Source::Range.new(
|
244
|
-
expr.source_buffer,
|
245
|
-
begin_pos,
|
246
|
-
end_pos
|
247
|
-
)
|
248
|
-
)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
data/lib/suspenders/actions.rb
DELETED
@@ -1,106 +0,0 @@
|
|
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.write(path, 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 action_mailer_asset_host(rails_env, host)
|
18
|
-
config = "config.action_mailer.asset_host = #{host}"
|
19
|
-
configure_environment(rails_env, config)
|
20
|
-
end
|
21
|
-
|
22
|
-
def configure_environment(rails_env, config)
|
23
|
-
inject_into_file(
|
24
|
-
"config/environments/#{rails_env}.rb",
|
25
|
-
"\n #{config}",
|
26
|
-
before: "\nend"
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
def expand_json(file, data)
|
31
|
-
action ExpandJson.new(destination_root, file, data)
|
32
|
-
end
|
33
|
-
|
34
|
-
def gem(*args)
|
35
|
-
options = args.extract_options!
|
36
|
-
name, *versions = args
|
37
|
-
|
38
|
-
parts = [quote(name)]
|
39
|
-
|
40
|
-
if (versions = versions.any? ? versions : options.delete(:version))
|
41
|
-
versions = Array(versions)
|
42
|
-
versions.each do |version|
|
43
|
-
parts << quote(version)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
parts << quote(options) unless options.empty?
|
48
|
-
|
49
|
-
str = []
|
50
|
-
str << indentation
|
51
|
-
str << "gem #{parts.join(", ")}"
|
52
|
-
append_file "Gemfile", %(\n#{str.join}\n), verbose: false
|
53
|
-
end
|
54
|
-
|
55
|
-
class ExpandJson
|
56
|
-
def initialize(destination_root, file, data)
|
57
|
-
@destination_root = destination_root
|
58
|
-
@file = file
|
59
|
-
@data = data
|
60
|
-
end
|
61
|
-
|
62
|
-
def invoke!
|
63
|
-
write_out { |existing_json| existing_json.deep_merge(data) }
|
64
|
-
end
|
65
|
-
|
66
|
-
def revoke!
|
67
|
-
write_out { |existing_json| hash_unmerge(existing_json, data) }
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
attr_reader :destination_root, :file, :data
|
73
|
-
|
74
|
-
def write_out
|
75
|
-
new_json = yield(existing_json)
|
76
|
-
IO.write(destination_file, JSON.pretty_generate(new_json))
|
77
|
-
end
|
78
|
-
|
79
|
-
def destination_file
|
80
|
-
File.join(destination_root, file)
|
81
|
-
end
|
82
|
-
|
83
|
-
def existing_json
|
84
|
-
JSON.parse(IO.read(destination_file), symbolize_names: true)
|
85
|
-
rescue Errno::ENOENT
|
86
|
-
{}
|
87
|
-
end
|
88
|
-
|
89
|
-
def hash_unmerge(hash, subhash)
|
90
|
-
subhash.reduce(hash) do |acc, (k, v)|
|
91
|
-
if hash.has_key?(k)
|
92
|
-
if v == hash[k]
|
93
|
-
acc.except(k)
|
94
|
-
elsif v.is_a?(Hash)
|
95
|
-
acc.merge(k => hash_unmerge(hash[k], v))
|
96
|
-
else
|
97
|
-
acc
|
98
|
-
end
|
99
|
-
else
|
100
|
-
acc
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,136 +0,0 @@
|
|
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
|
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 create_staging_heroku_app(flags)
|
20
|
-
app_name = heroku_app_name_for("staging")
|
21
|
-
|
22
|
-
run_toolbelt_command "create #{app_name} #{flags}", "staging"
|
23
|
-
end
|
24
|
-
|
25
|
-
def create_production_heroku_app(flags)
|
26
|
-
app_name = heroku_app_name_for("production")
|
27
|
-
|
28
|
-
run_toolbelt_command "create #{app_name} #{flags}", "production"
|
29
|
-
end
|
30
|
-
|
31
|
-
def set_heroku_rails_secrets
|
32
|
-
%w[staging production].each do |environment|
|
33
|
-
run_toolbelt_command(
|
34
|
-
"config:add SECRET_KEY_BASE=#{generate_secret}",
|
35
|
-
environment
|
36
|
-
)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def set_heroku_honeybadger_env
|
41
|
-
%w[staging production].each do |environment|
|
42
|
-
run_toolbelt_command(
|
43
|
-
"config:add HONEYBADGER_ENV=#{environment}",
|
44
|
-
environment
|
45
|
-
)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def set_heroku_backup_schedule
|
50
|
-
%w[staging production].each do |environment|
|
51
|
-
run_toolbelt_command(
|
52
|
-
"pg:backups:schedule DATABASE_URL --at '10:00 UTC'",
|
53
|
-
environment
|
54
|
-
)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def create_heroku_pipeline
|
59
|
-
pipelines_plugin = `heroku help | grep pipelines`
|
60
|
-
if pipelines_plugin.empty?
|
61
|
-
puts "You need heroku pipelines plugin. Run: brew upgrade heroku-toolbelt"
|
62
|
-
exit 1
|
63
|
-
end
|
64
|
-
|
65
|
-
run_toolbelt_command(
|
66
|
-
"pipelines:create #{heroku_app_name} \
|
67
|
-
-a #{heroku_app_name}-staging --stage staging",
|
68
|
-
"staging"
|
69
|
-
)
|
70
|
-
|
71
|
-
run_toolbelt_command(
|
72
|
-
"pipelines:add #{heroku_app_name} \
|
73
|
-
-a #{heroku_app_name}-production --stage production",
|
74
|
-
"production"
|
75
|
-
)
|
76
|
-
end
|
77
|
-
|
78
|
-
def set_heroku_application_host
|
79
|
-
%w[staging production].each do |environment|
|
80
|
-
run_toolbelt_command(
|
81
|
-
"config:add APPLICATION_HOST=#{heroku_app_name}-#{environment}.herokuapp.com",
|
82
|
-
environment
|
83
|
-
)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def set_heroku_buildpacks
|
88
|
-
%w[staging production].each do |environment|
|
89
|
-
run_toolbelt_command(
|
90
|
-
"buildpacks:add --index 1 heroku/nodejs",
|
91
|
-
environment
|
92
|
-
)
|
93
|
-
run_toolbelt_command(
|
94
|
-
"buildpacks:add --index 2 heroku/ruby",
|
95
|
-
environment
|
96
|
-
)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
|
102
|
-
attr_reader :app_builder
|
103
|
-
|
104
|
-
def command_to_join_heroku_app(environment)
|
105
|
-
heroku_app_name = heroku_app_name_for(environment)
|
106
|
-
<<~SHELL
|
107
|
-
|
108
|
-
if heroku apps:info --app #{heroku_app_name} > /dev/null 2>&1; then
|
109
|
-
git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true
|
110
|
-
printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n'
|
111
|
-
else
|
112
|
-
printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n'
|
113
|
-
fi
|
114
|
-
SHELL
|
115
|
-
end
|
116
|
-
|
117
|
-
def heroku_app_name
|
118
|
-
app_builder.app_name.dasherize
|
119
|
-
end
|
120
|
-
|
121
|
-
def heroku_app_name_for(environment)
|
122
|
-
"#{heroku_app_name}-#{environment}"
|
123
|
-
end
|
124
|
-
|
125
|
-
def generate_secret
|
126
|
-
SecureRandom.hex(64)
|
127
|
-
end
|
128
|
-
|
129
|
-
def run_toolbelt_command(command, environment)
|
130
|
-
app_builder.run(
|
131
|
-
"heroku #{command} --remote #{environment}"
|
132
|
-
)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|