nextgen 0.18.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 232f4be6f3272b3ea41b9ec5b00dec9839cfa895e191ca4877a15adbc362531a
4
- data.tar.gz: 9118e393ffb6addc9d93c1050d673b07c775de544f8d0378347f5c17239b633d
3
+ metadata.gz: '08e56651b3e6d88022098471a5b3e04b20ca703ac5e973425fb68f806b271e4a'
4
+ data.tar.gz: fed2715b9bdb7625434ef6983a15118e1fe29cd3f64a0f182928c1805920f7ed
5
5
  SHA512:
6
- metadata.gz: 06704c5b229053280d8501695edd1dbc4c611ae727dc4b7979a533227ba9ab26e597f3602f27af5dd6241bede88e0d60dedbaebc81d99da7d705da885c83a1fb
7
- data.tar.gz: c7e27d364cbd00690fe2dbec0ec0e5792e3ee22834081c8efcdd0d313145f4d8085160c12067d5672193beeefe1c3d741087469f3d1b93ccef996581fd3cb825
6
+ metadata.gz: 5481874c31115de5229ba346ede332453731c46604b01e974ee1d34471ff1dfcc290dbcdbf2170f03e64b44333d1c83ced987204c6c43abf58637c416e18628c
7
+ data.tar.gz: 679b4f278c8493da2ed8b34df79c761073f010262bf66eff305a974051f1a1ff52dd89542dc6a852bbacbe7e4a4a46fda95355d68e7cc0e8e6bfb55c53c31682
data/README.md CHANGED
@@ -26,7 +26,7 @@ Nextgen is an **interactive** and flexible alternative to `rails new` that inclu
26
26
 
27
27
  ## Requirements
28
28
 
29
- Nextgen generates apps using **Rails 7.1**.
29
+ Nextgen generates apps using **Rails 7.2**.
30
30
 
31
31
  - **Ruby 3.1+** is required
32
32
  - **Rubygems 3.4.8+** is required (run `gem update --system` to get it)
@@ -54,7 +54,7 @@ Check out the [examples directory](./examples) to see some Rails apps that were
54
54
 
55
55
  ## What's included
56
56
 
57
- **Nextgen starts with the "omakase" default behavior of `rails new`,** so you get the great things included in Rails 7.1 like a production-ready Dockerfile, your choice of database platform, CSS framework, etc. You can also interactively disable parts of the default stack that you don't need, like JBuilder or Action Mailbox.
57
+ **Nextgen starts with the "omakase" default behavior of `rails new`,** so you get the great things included in Rails 7.2 like RuboCop, a GitHub Actions CI workflow, your choice of database platform, CSS framework, etc. You can also interactively disable parts of the default stack that you don't need, like JBuilder or Action Mailbox.
58
58
 
59
59
  On top of that foundation, Nextgen offers dozens of useful enhancements to the vanilla Rails experience. You are free to pick and choose which (if any) of these to apply to your new project. Behind the scenes, **each enhancement is applied in a separate git commit,** so that you can later see what was applied and why, and revert the suggestions if necessary.
60
60
 
@@ -65,18 +65,21 @@ Here are some highlights of what Nextgen brings to the table:
65
65
 
66
66
  ### GitHub Actions
67
67
 
68
- Nextgen can optionally set up a GitHub Actions CI workflow for your app that automatically runs tests, linters, and security checks based on the gems and packages you have installed.
68
+ If you've opted into GitHub Actions, Nextgen will automatically add jobs to your CI workflow based on the gems and packages you have installed.
69
69
 
70
70
  ### Minitest or RSpec
71
71
 
72
72
  Prefer RSpec? Nextgen can set you up with RSpec, plus the gems and configuration you need for system specs (browser testing). Or stick with the Rails Minitest defaults. In either case, Nextgen will set up a good default Rake task and appropriate CI job.
73
73
 
74
+ ### Opinionated RuboCop Config
75
+
76
+ By default, Rails apps include RuboCop with a config defined by the [rubocop-rails-omakase](https://github.com/rails/rubocop-rails-omakase) gem. Nextgen allows you to opt out of RuboCop entirely, or use Nextgen's own custom RuboCop config. Nextgen's config will automatically include Capybara, FactoryBot, and RSpec rules, should your app include those frameworks.
77
+
74
78
  ### Gems
75
79
 
76
80
  Nextgen can install and configure your choice of these recommended gems:
77
81
 
78
82
  - [annotate](https://github.com/ctran/annotate_models)
79
- - [brakeman](https://github.com/presidentbeef/brakeman)
80
83
  - [bundler-audit](https://github.com/rubysec/bundler-audit)
81
84
  - [capybara-lockstep](https://github.com/makandra/capybara-lockstep)
82
85
  - [dotenv](https://github.com/bkeepers/dotenv)
@@ -88,7 +91,6 @@ Nextgen can install and configure your choice of these recommended gems:
88
91
  - [pgcli-rails](https://github.com/mattbrictson/pgcli-rails)
89
92
  - [rack-canonical-host](https://github.com/tylerhunt/rack-canonical-host)
90
93
  - [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler)
91
- - [rubocop](https://github.com/rubocop/rubocop)
92
94
  - [shoulda-matchers](https://github.com/thoughtbot/shoulda-matchers)
93
95
  - [sidekiq](https://github.com/sidekiq/sidekiq)
94
96
  - [thor](https://github.com/rails/thor)
@@ -16,6 +16,10 @@ rspec_system_testing:
16
16
  - rspec
17
17
  - system_testing
18
18
 
19
+ rspec_github_actions:
20
+ description: "Add RSpec job to GitHub Actions CI workflow"
21
+ requires: rspec
22
+
19
23
  node:
20
24
  description: "Set up Node and Yarn"
21
25
 
@@ -37,10 +41,6 @@ basic_auth:
37
41
  prompt: "BasicAuth controller concern"
38
42
  description: "Allow app to be secured with ENV-based basic auth credentials"
39
43
 
40
- brakeman:
41
- prompt: "Brakeman"
42
- description: "Install brakeman gem for security checks"
43
-
44
44
  bundler_audit:
45
45
  prompt: "Bundler Audit"
46
46
  description: "Install bundler-audit gem to detect CVEs in Ruby dependencies"
@@ -143,13 +143,10 @@ vcr:
143
143
  requires: test_framework
144
144
 
145
145
  rubocop:
146
- prompt: "RuboCop"
147
- description: "Install rubocop gems; apply formatting rules"
146
+ prompt: "RuboCop (nextgen custom config)"
147
+ description: "Replace rubocop-rails-omakase with a custom config"
148
+ requires: rubocop
148
149
 
149
150
  overcommit:
150
151
  prompt: "Overcommit"
151
152
  description: "Configure overcommit pre-commit git hooks"
152
-
153
- github_actions:
154
- prompt: "GitHub Actions"
155
- description: "Configure GitHub Actions workflow for CI"
@@ -22,6 +22,12 @@ module Nextgen
22
22
  end
23
23
  alias add_package_json_script add_package_json_scripts
24
24
 
25
+ def remove_package_json_script(name)
26
+ cmd = "npm pkg delete scripts.#{name.to_s.shellescape}"
27
+ say_status :run, cmd.truncate(60), :green
28
+ run! cmd, verbose: false
29
+ end
30
+
25
31
  def yarn_command(cmd, capture: false)
26
32
  say_status :yarn, cmd, :green
27
33
  output = run! "yarn #{cmd}", capture: true, verbose: false
@@ -45,6 +45,7 @@ module Nextgen
45
45
  ask_frontend_management unless rails_opts.api?
46
46
  ask_css unless rails_opts.api? || rails_opts.skip_asset_pipeline?
47
47
  ask_javascript unless rails_opts.api? || rails_opts.skip_asset_pipeline?
48
+ ask_rails_tools
48
49
  ask_rails_frameworks
49
50
  ask_test_framework
50
51
  ask_system_testing if rails_opts.frontend? && rails_opts.test_framework?
@@ -165,8 +166,7 @@ module Nextgen
165
166
  )
166
167
 
167
168
  if frontend == :vite
168
- rails_opts.asset_pipeline = nil
169
- rails_opts.javascript = "vite"
169
+ rails_opts.vite!
170
170
  else
171
171
  rails_opts.asset_pipeline = frontend
172
172
  end
@@ -196,6 +196,26 @@ module Nextgen
196
196
  )
197
197
  end
198
198
 
199
+ def ask_rails_tools
200
+ opt_out = {
201
+ "Brakeman" => "brakeman",
202
+ "GitHub Actions CI" => "ci",
203
+ "RuboCop" => "rubocop"
204
+ }
205
+ opt_in = {
206
+ "devcontainer files" => "devcontainer"
207
+ }
208
+
209
+ answers = prompt.multi_select(
210
+ "Rails can preinstall the following. Which do you need?",
211
+ opt_out.merge(opt_in),
212
+ default: opt_out.keys.reverse
213
+ )
214
+
215
+ rails_opts.devcontainer! if answers.delete("devcontainer")
216
+ (opt_out.values - answers).each { rails_opts.skip_optional_feature!(_1) }
217
+ end
218
+
199
219
  def ask_rails_frameworks
200
220
  frameworks = {
201
221
  "JBuilder" => "jbuilder",
@@ -222,7 +242,7 @@ module Nextgen
222
242
  default: frameworks.keys.reverse
223
243
  )
224
244
 
225
- (frameworks.values - answers).each { rails_opts.skip_optional_framework!(_1) }
245
+ (frameworks.values - answers).each { rails_opts.skip_optional_feature!(_1) }
226
246
  end
227
247
 
228
248
  def ask_test_framework
@@ -40,14 +40,15 @@ if File.exist?("test/application_system_test_case.rb")
40
40
  gsub_file "Gemfile", /gem "selenium-webdriver"$/, '\0, require: false'
41
41
  end
42
42
 
43
- if File.exist?(".ruby-version") && File.read(".ruby-version").match?(/\A\d+\.\d+.\d+.\s*\z/m)
44
- say_git "DRY up Gemfile and .ruby-version file"
45
- replacement = if bundler_ruby_file_supported?
46
- 'ruby file: ".ruby-version"'
47
- else
48
- 'ruby Pathname.new(__dir__).join(".ruby-version").read.strip'
49
- end
50
- gsub_file "Gemfile", /^ruby "\d.*"$/, replacement
43
+ missing_ruby_decl = !File.read("Gemfile").match?(/^ruby /)
44
+ if missing_ruby_decl && File.exist?(".ruby-version") && File.read(".ruby-version").match?(/\A\d+\.\d+.\d+.\s*\z/m)
45
+ say_git "Add ruby declaration to Gemfile"
46
+ ruby_decl = if bundler_ruby_file_supported?
47
+ 'ruby file: ".ruby-version"'
48
+ else
49
+ 'ruby Pathname.new(__dir__).join(".ruby-version").read.strip'
50
+ end
51
+ gsub_file "Gemfile", /^source .*$/, '\0' + "\n#{ruby_decl}"
51
52
  end
52
53
 
53
54
  if File.exist?("app/views/layouts/application.html.erb")
@@ -70,7 +71,7 @@ gsub_file "config/environments/production.rb",
70
71
 
71
72
  if File.exist?("config/database.yml")
72
73
  say_git "Create initial schema.rb"
73
- rails_command "db:prepare"
74
+ rails_command "db:create db:migrate"
74
75
  end
75
76
 
76
77
  if (time_zone = read_system_time_zone_name)
@@ -2,3 +2,25 @@
2
2
 
3
3
  install_gem "bundler-audit", group: :development, require: false
4
4
  binstub "bundler-audit"
5
+
6
+ if File.exist?(".github/workflows/ci.yml")
7
+ say_git "Add bundle-audit job to CI workflow"
8
+ inject_into_file ".github/workflows/ci.yml", <<-YAML, after: /^jobs:\n/
9
+ scan_gems:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: .ruby-version
20
+ bundler-cache: true
21
+
22
+ - name: Scan for security vulnerabilities in Ruby dependencies
23
+ run: bundle exec bundle-audit check --update -v
24
+
25
+ YAML
26
+ end
@@ -24,5 +24,31 @@ say_git "Add eslint to default rake task"
24
24
  copy_file "lib/tasks/eslint.rake"
25
25
  add_lint_task "eslint"
26
26
 
27
+ if File.exist?(".github/workflows/ci.yml")
28
+ say_git "Add eslint job to CI workflow"
29
+ node_spec = File.exist?(".node-version") ? 'node-version-file: ".node-version"' : 'node-version: "lts/*"'
30
+ inject_into_file ".github/workflows/ci.yml", <<-YAML, after: /^jobs:\n/
31
+ eslint:
32
+ runs-on: ubuntu-latest
33
+
34
+ steps:
35
+ - name: Checkout code
36
+ uses: actions/checkout@v4
37
+
38
+ - name: Set up Node
39
+ uses: actions/setup-node@v4
40
+ with:
41
+ #{node_spec}
42
+ cache: yarn
43
+
44
+ - name: Install Yarn packages
45
+ run: npx --yes ci
46
+
47
+ - name: Lint JavaScript files with eslint
48
+ run: yarn lint:js
49
+
50
+ YAML
51
+ end
52
+
27
53
  say_git "Auto-correct any existing issues"
28
54
  run "yarn fix:js", capture: true
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ return unless File.exist?(".github/workflows/ci.yml")
4
+
5
+ erb = <<~YAML
6
+ test:
7
+ runs-on: ubuntu-latest
8
+
9
+ <%- if gems.include?("pg") -%>
10
+ services:
11
+ postgres:
12
+ image: postgres
13
+ env:
14
+ POSTGRES_USER: postgres
15
+ POSTGRES_PASSWORD: postgres
16
+ ports:
17
+ - 5432:5432
18
+ options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=3
19
+
20
+ <%- end -%>
21
+ steps:
22
+ <%- if gems.include?("capybara") -%>
23
+ - name: Install packages
24
+ run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable
25
+
26
+ <%- end -%>
27
+ - name: Checkout code
28
+ uses: actions/checkout@v4
29
+
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: .ruby-version
34
+ bundler-cache: true
35
+
36
+ - name: Run tests
37
+ env:
38
+ RAILS_ENV: test
39
+ <%- if gems.include?("pg") -%>
40
+ DATABASE_URL: postgres://postgres:postgres@localhost:5432
41
+ <%- end -%>
42
+ <%- if File.exist?("config/database.yml") -%>
43
+ run: bin/rails db:test:prepare && bin/rspec
44
+ <%- else -%>
45
+ run: bundle exec rspec
46
+ <%- end -%>
47
+ <%- if gems.include?("capybara") -%>
48
+
49
+ - name: Keep screenshots from failed system tests
50
+ uses: actions/upload-artifact@v4
51
+ if: failure()
52
+ with:
53
+ name: screenshots
54
+ path: ${{ github.workspace }}/tmp/screenshots
55
+ if-no-files-found: ignore
56
+ <%- end -%>
57
+
58
+ YAML
59
+
60
+ require "erb"
61
+ gems = File.exist?("Gemfile") ? File.read("Gemfile").scan(/^\s*gem ["'](.+?)["']/).flatten : []
62
+ job = ERB.new(erb, trim_mode: "-").result(binding)
63
+ inject_into_file ".github/workflows/ci.yml", job.gsub(/^/, " "), after: /^jobs:\n/
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  say_git "Install rubocop gems"
4
+ remove_gem "rubocop-rails-omakase"
4
5
  gemfile = File.read("Gemfile")
5
6
  plugins = []
6
7
  plugins << "capybara" if gemfile.match?(/^\s*gem ['"]capybara['"]/)
@@ -12,8 +13,8 @@ install_gem("rubocop-rails", version: ">= 2.22.0", group: :development, require:
12
13
  install_gems(*plugins.map { "rubocop-#{_1}" }, "rubocop", group: :development, require: false)
13
14
  binstub "rubocop"
14
15
 
15
- say_git "Generate .rubocop.yml"
16
- template ".rubocop.yml", context: binding
16
+ say_git "Replace .rubocop.yml"
17
+ template ".rubocop.yml", context: binding, force: true
17
18
 
18
19
  if File.exist?(".erb-lint.yml")
19
20
  say_git "Regenerate .erb-lint.yml with rubocop support"
@@ -22,5 +22,31 @@ say_git "Add stylelint to default rake task"
22
22
  copy_file "lib/tasks/stylelint.rake"
23
23
  add_lint_task "stylelint"
24
24
 
25
+ if File.exist?(".github/workflows/ci.yml")
26
+ say_git "Add stylelint job to CI workflow"
27
+ node_spec = File.exist?(".node-version") ? 'node-version-file: ".node-version"' : 'node-version: "lts/*"'
28
+ inject_into_file ".github/workflows/ci.yml", <<-YAML, after: /^jobs:\n/
29
+ stylelint:
30
+ runs-on: ubuntu-latest
31
+
32
+ steps:
33
+ - name: Checkout code
34
+ uses: actions/checkout@v4
35
+
36
+ - name: Set up Node
37
+ uses: actions/setup-node@v4
38
+ with:
39
+ #{node_spec}
40
+ cache: yarn
41
+
42
+ - name: Install Yarn packages
43
+ run: npx --yes ci
44
+
45
+ - name: Lint CSS files with stylelint
46
+ run: yarn lint:css
47
+
48
+ YAML
49
+ end
50
+
25
51
  say_git "Auto-correct any existing issues"
26
52
  run "yarn fix:css", capture: true
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ say_git "Remove esbuild"
4
+ remove_yarn_package "esbuild"
5
+ remove_package_json_script(:build)
6
+
3
7
  say_git "Install the vite_rails gem"
4
8
  install_gem "vite_rails", version: "~> 3.0"
5
9
 
@@ -92,11 +96,10 @@ copy_file "app/frontend/images/example.svg"
92
96
  # TODO: rspec support
93
97
  copy_file "test/helpers/inline_svg_helper_test.rb" if File.exist?("test/vite_helper.rb")
94
98
 
95
- say_git "Add a `yarn start` script"
96
- start = "concurrently -i -k --kill-others-on-fail -p none 'RUBY_DEBUG_OPEN=true bin/rails s' 'bin/vite dev'"
97
- add_package_json_script(start:)
98
- add_yarn_package "concurrently", dev: true
99
- copy_file "bin/dev-yarn", "bin/dev", mode: :preserve, force: true
99
+ say_git "Add a `bin/dev` script that uses run-pty"
100
+ add_yarn_package "run-pty@^5", dev: true
101
+ copy_file "bin/dev-node", "bin/dev", mode: :preserve, force: true
102
+ copy_file "run-pty.json"
100
103
  remove_file "Procfile.dev"
101
104
 
102
105
  say_git "Add Safari cache workaround in development"
@@ -116,3 +119,19 @@ comment_lines "config/environments/development.rb", /^\s*config\.assets\./
116
119
  comment_lines "config/environments/production.rb", /^\s*config\.assets\./
117
120
  gsub_file "app/views/layouts/application.html.erb", /^.*<%= stylesheet_link_tag.*$/, ""
118
121
  remove_gem "sprockets-rails"
122
+
123
+ if File.exist?(".github/workflows/ci.yml")
124
+ say_git "Add Node steps to CI workflow"
125
+ node_spec = File.exist?(".node-version") ? 'node-version-file: ".node-version"' : 'node-version: "lts/*"'
126
+ inject_into_file ".github/workflows/ci.yml", <<-YAML, before: /^\s+- name: Run tests/
127
+
128
+ - name: Set up Node
129
+ uses: actions/setup-node@v4
130
+ with:
131
+ #{node_spec}
132
+ cache: yarn
133
+
134
+ - name: Install Yarn packages
135
+ run: npx --yes ci
136
+ YAML
137
+ end
@@ -19,15 +19,18 @@ module Nextgen
19
19
 
20
20
  ASSET_PIPELINES = %w[sprockets propshaft].freeze
21
21
 
22
- OPTIONAL_FRAMEWORKS = %w[
22
+ OPTIONAL_FEATURES = %w[
23
23
  action_mailer
24
24
  action_mailbox
25
25
  action_text
26
26
  active_job
27
27
  active_storage
28
28
  action_cable
29
+ brakeman
30
+ ci
29
31
  hotwire
30
32
  jbuilder
33
+ rubocop
31
34
  ].freeze
32
35
 
33
36
  attr_reader :asset_pipeline, :css, :javascript, :database, :test_framework
@@ -35,7 +38,9 @@ module Nextgen
35
38
  def initialize
36
39
  @api = false
37
40
  @edge = false
38
- @skip_frameworks = []
41
+ @vite = false
42
+ @devcontainer = nil
43
+ @skip_features = []
39
44
  @skip_system_test = false
40
45
  @test_framework = "minitest"
41
46
  end
@@ -55,16 +60,19 @@ module Nextgen
55
60
 
56
61
  def javascript=(framework)
57
62
  raise ArgumentError, "Can't specify javascript in API mode" if api? && framework
58
-
59
- if skip_asset_pipeline? && framework != "vite"
60
- raise ArgumentError, "Can't specify javascript when asset pipeline is disabled"
61
- end
63
+ raise ArgumentError, "Can't specify javascript when asset pipeline is disabled" if skip_asset_pipeline?
62
64
 
63
65
  @javascript = framework
64
66
  end
65
67
 
68
+ def vite!
69
+ self.asset_pipeline = nil
70
+ @javascript = "esbuild"
71
+ @vite = true
72
+ end
73
+
66
74
  def vite?
67
- @javascript == "vite"
75
+ @vite
68
76
  end
69
77
 
70
78
  def skip_javascript?
@@ -99,6 +107,10 @@ module Nextgen
99
107
  @edge
100
108
  end
101
109
 
110
+ def devcontainer!
111
+ @devcontainer = true
112
+ end
113
+
102
114
  def api!
103
115
  raise ArgumentError, "Can't specify API mode if css is already specified" if css
104
116
  raise ArgumentError, "Can't specify API mode if javascript is already specified" if javascript
@@ -115,13 +127,17 @@ module Nextgen
115
127
  end
116
128
 
117
129
  def requires_node?
118
- %w[bootstrap bulma postcss sass].include?(css) || %w[webpack esbuild rollup vite].include?(javascript)
130
+ %w[bootstrap bulma postcss sass].include?(css) || %w[webpack esbuild rollup].include?(javascript)
119
131
  end
120
132
 
121
133
  def rspec?
122
134
  @test_framework == "rspec"
123
135
  end
124
136
 
137
+ def rubocop?
138
+ !skip_optional_feature?("rubocop")
139
+ end
140
+
125
141
  def active_record?
126
142
  !skip_active_record?
127
143
  end
@@ -151,23 +167,23 @@ module Nextgen
151
167
  end
152
168
 
153
169
  def action_mailer?
154
- !skip_optional_framework?("action_mailer")
170
+ !skip_optional_feature?("action_mailer")
155
171
  end
156
172
 
157
173
  def active_job?
158
- !skip_optional_framework?("active_job")
174
+ !skip_optional_feature?("active_job")
159
175
  end
160
176
 
161
- def skip_optional_framework!(framework)
162
- raise ArgumentError, "Unknown framework: #{framework}" unless OPTIONAL_FRAMEWORKS.include?(framework)
177
+ def skip_optional_feature!(feature)
178
+ raise ArgumentError, "Unknown feature: #{feature}" unless OPTIONAL_FEATURES.include?(feature)
163
179
 
164
- skip_frameworks << framework
180
+ skip_features << feature
165
181
  end
166
182
 
167
- def skip_optional_framework?(framework)
168
- raise ArgumentError, "Unknown framework: #{framework}" unless OPTIONAL_FRAMEWORKS.include?(framework)
183
+ def skip_optional_feature?(feature)
184
+ raise ArgumentError, "Unknown feature: #{feature}" unless OPTIONAL_FEATURES.include?(feature)
169
185
 
170
- skip_frameworks.include?(framework)
186
+ skip_features.include?(feature)
171
187
  end
172
188
 
173
189
  def to_args # rubocop:disable Metrics/PerceivedComplexity
@@ -183,12 +199,13 @@ module Nextgen
183
199
  args << "--database=#{database}" if database
184
200
  args << "--css=#{css}" if css
185
201
  args << "--javascript=#{javascript}" if javascript
186
- args.push(*skip_frameworks.map { "--skip-#{_1.tr("_", "-")}" })
202
+ args << "--devcontainer" if @devcontainer
203
+ args.push(*skip_features.map { "--skip-#{_1.tr("_", "-")}" })
187
204
  end
188
205
  end
189
206
 
190
207
  private
191
208
 
192
- attr_reader :skip_frameworks
209
+ attr_reader :skip_features
193
210
  end
194
211
  end
@@ -21,7 +21,8 @@ module Nextgen
21
21
  @gemfile = gemfile
22
22
  .gsub(/^\s*#.*/, "") # remove comments
23
23
  .gsub(/(\s*\n)+/, "\n") # remove blank lines
24
- .gsub(/^(ruby.*)/, "\n\\1\n") # ensure blank space around "ruby" line
24
+ .sub(/^(ruby.*)/, "\n\\1") # ensure blank space before "ruby" line
25
+ .sub(/^(gem.*)/, "\n\\1") # ensure blank space before first "gem" line
25
26
  .gsub(/^(group.*)/, "\n\\1") # ensure blank space before each "group" block
26
27
  nil
27
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nextgen
4
- VERSION = "0.18.0"
4
+ VERSION = "0.20.0"
5
5
  end
@@ -178,6 +178,9 @@ Rails/I18nLocaleTexts:
178
178
  Rails/Inquiry:
179
179
  Enabled: false
180
180
 
181
+ Rails/LinkToBlank:
182
+ Enabled: false
183
+
181
184
  Rails/NotNullColumn:
182
185
  Enabled: false
183
186
 
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- exec "yarn", "start", *ARGV
4
+ exec "npx", "run-pty", "run-pty.json", *ARGV
@@ -0,0 +1,16 @@
1
+ [
2
+ {
3
+ "command": ["bin/rails", "server"],
4
+ "status": {
5
+ "Listening on": null
6
+ },
7
+ "defaultStatus": ["⏳", "S"]
8
+ },
9
+ {
10
+ "command": ["bin/vite", "dev"],
11
+ "status": {
12
+ "ready in": null
13
+ },
14
+ "defaultStatus": ["⏳", "S"]
15
+ }
16
+ ]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nextgen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Brictson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-03 00:00:00.000000000 Z
11
+ date: 2024-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.1
19
+ version: 7.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.1
26
+ version: 7.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -107,7 +107,6 @@ files:
107
107
  - lib/nextgen/generators/annotate.rb
108
108
  - lib/nextgen/generators/base.rb
109
109
  - lib/nextgen/generators/basic_auth.rb
110
- - lib/nextgen/generators/brakeman.rb
111
110
  - lib/nextgen/generators/bundler_audit.rb
112
111
  - lib/nextgen/generators/capybara_lockstep.rb
113
112
  - lib/nextgen/generators/clean_gemfile.rb
@@ -116,7 +115,6 @@ files:
116
115
  - lib/nextgen/generators/eslint.rb
117
116
  - lib/nextgen/generators/factory_bot_rails.rb
118
117
  - lib/nextgen/generators/git_safe.rb
119
- - lib/nextgen/generators/github_actions.rb
120
118
  - lib/nextgen/generators/github_pr_template.rb
121
119
  - lib/nextgen/generators/good_migrations.rb
122
120
  - lib/nextgen/generators/home_controller.rb
@@ -128,6 +126,7 @@ files:
128
126
  - lib/nextgen/generators/pgcli_rails.rb
129
127
  - lib/nextgen/generators/rack_canonical_host.rb
130
128
  - lib/nextgen/generators/rack_mini_profiler.rb
129
+ - lib/nextgen/generators/rspec_github_actions.rb
131
130
  - lib/nextgen/generators/rspec_rails.rb
132
131
  - lib/nextgen/generators/rspec_system_testing.rb
133
132
  - lib/nextgen/generators/rubocop.rb
@@ -148,8 +147,6 @@ files:
148
147
  - template/.env.sample
149
148
  - template/.erb-lint.yml.tt
150
149
  - template/.github/PULL_REQUEST_TEMPLATE.md.tt
151
- - template/.github/dependabot.yml
152
- - template/.github/workflows/ci.yml.tt
153
150
  - template/.overcommit.yml.tt
154
151
  - template/.prettierrc.cjs
155
152
  - template/.rubocop.yml.tt
@@ -168,7 +165,7 @@ files:
168
165
  - template/app/helpers/inline_svg_helper.rb
169
166
  - template/app/views/home/index.html.erb.tt
170
167
  - template/bin/dev
171
- - template/bin/dev-yarn
168
+ - template/bin/dev-node
172
169
  - template/bin/setup
173
170
  - template/config/environments/staging.rb
174
171
  - template/config/initializers/generators.rb
@@ -186,6 +183,7 @@ files:
186
183
  - template/lib/vite_inline_svg_file_loader.rb
187
184
  - template/package.json
188
185
  - template/postcss.config.cjs
186
+ - template/run-pty.json
189
187
  - template/spec/support/factory_bot.rb
190
188
  - template/spec/support/mailer.rb
191
189
  - template/spec/support/shoulda.rb
@@ -224,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
222
  - !ruby/object:Gem::Version
225
223
  version: '0'
226
224
  requirements: []
227
- rubygems_version: 3.5.16
225
+ rubygems_version: 3.5.11
228
226
  signing_key:
229
227
  specification_version: 4
230
228
  summary: Generate your next Rails app interactively!
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- install_gem "brakeman", group: :development, require: false
4
- binstub "brakeman"
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- gems = File.exist?("Gemfile") ? File.read("Gemfile").scan(/^\s*gem ["'](.+?)["']/).flatten : []
4
- template ".github/workflows/ci.yml.tt", context: binding
5
- copy_file ".github/dependabot.yml"
@@ -1,9 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: github-actions
4
- directory: "/"
5
- schedule:
6
- interval: monthly
7
- time: "06:00"
8
- timezone: America/Los_Angeles
9
- open-pull-requests-limit: 10
@@ -1,142 +0,0 @@
1
- name: CI
2
- on:
3
- pull_request:
4
- push:
5
- branches:
6
- - main
7
- env:
8
- RAILS_ENV: test
9
- jobs:
10
- <% if minitest? || rspec? -%>
11
- test:
12
- name: "<%= minitest? ? "Test" : "RSpec" %>"
13
- runs-on: ubuntu-latest
14
- <% if gems.include?("pg") -%>
15
- env:
16
- DATABASE_URL: postgres://postgres:postgres@localhost:5432/ci
17
- services:
18
- postgres:
19
- image: postgres:16-alpine
20
- env:
21
- POSTGRES_DB: ci
22
- POSTGRES_USER: postgres
23
- POSTGRES_PASSWORD: postgres
24
- ports:
25
- - 5432:5432
26
- options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
27
- <% end -%>
28
- steps:
29
- - uses: actions/checkout@v4
30
- - uses: ruby/setup-ruby@v1
31
- with:
32
- bundler-cache: true
33
- <% if File.exist?("package.json") -%>
34
- - uses: actions/setup-node@v4
35
- with:
36
- <% if File.exist?(".node-version") -%>
37
- node-version-file: ".node-version"
38
- <% else -%>
39
- node-version: "lts/*"
40
- <% end -%>
41
- cache: yarn
42
- - run: npx --yes ci
43
- <% end -%>
44
- <% if gems.include?("capybara") -%>
45
- - run: mkdir -p ./tmp/screenshots
46
- <% end -%>
47
- <% if File.exist?("config/database.yml") -%>
48
- - run: bundle exec rake db:prepare
49
- <% end -%>
50
- <% if rspec? -%>
51
- - run: bundle exec rspec
52
- <% else -%>
53
- - run: bundle exec rake test:all
54
- <% end -%>
55
- <% if gems.include?("capybara") -%>
56
- - uses: actions/upload-artifact@v4
57
- if: failure()
58
- with:
59
- name: capybara-screenshots
60
- path: ./tmp/screenshots/
61
- retention-days: 7
62
- if-no-files-found: ignore
63
- <% end -%>
64
- <% end -%>
65
- <% if gems.include?("erb_lint") -%>
66
- erblint:
67
- name: "Lint / erblint"
68
- runs-on: ubuntu-latest
69
- steps:
70
- - uses: actions/checkout@v4
71
- - uses: ruby/setup-ruby@v1
72
- with:
73
- bundler-cache: true
74
- - run: bin/erblint --lint-all
75
- <% end -%>
76
- <% if Dir["eslint.config.*"].any? -%>
77
- eslint:
78
- name: "Lint / eslint"
79
- runs-on: ubuntu-latest
80
- steps:
81
- - uses: actions/checkout@v4
82
- - uses: actions/setup-node@v4
83
- with:
84
- <% if File.exist?(".node-version") -%>
85
- node-version-file: ".node-version"
86
- <% else -%>
87
- node-version: "lts/*"
88
- <% end -%>
89
- cache: yarn
90
- - run: npx --yes ci
91
- - run: yarn lint:js
92
- <% end -%>
93
- <% if gems.include?("rubocop") -%>
94
- rubocop:
95
- name: "Lint / rubocop"
96
- runs-on: ubuntu-latest
97
- steps:
98
- - uses: actions/checkout@v4
99
- - uses: ruby/setup-ruby@v1
100
- with:
101
- bundler-cache: true
102
- - run: bin/rubocop
103
- <% end -%>
104
- <% if Dir[".stylelintrc*"].any? -%>
105
- stylelint:
106
- name: "Lint / stylelint"
107
- runs-on: ubuntu-latest
108
- steps:
109
- - uses: actions/checkout@v4
110
- - uses: actions/setup-node@v4
111
- with:
112
- <% if File.exist?(".node-version") -%>
113
- node-version-file: ".node-version"
114
- <% else -%>
115
- node-version: "lts/*"
116
- <% end -%>
117
- cache: yarn
118
- - run: npx --yes ci
119
- - run: yarn lint:css
120
- <% end -%>
121
- <% if gems.include?("brakeman") -%>
122
- brakeman:
123
- name: "Security / brakeman"
124
- runs-on: ubuntu-latest
125
- steps:
126
- - uses: actions/checkout@v4
127
- - uses: ruby/setup-ruby@v1
128
- with:
129
- bundler-cache: true
130
- - run: bundle exec brakeman --exit-on-warn --no-progress --color --output /dev/stdout
131
- <% end -%>
132
- <% if gems.include?("bundler-audit") -%>
133
- bundle-audit:
134
- name: "Security / bundle-audit"
135
- runs-on: ubuntu-latest
136
- steps:
137
- - uses: actions/checkout@v4
138
- - uses: ruby/setup-ruby@v1
139
- with:
140
- bundler-cache: true
141
- - run: bundle exec bundle-audit check --update -v
142
- <% end -%>