nextgen 0.17.1 → 0.19.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: 38db6779e6011d4a674dbfcb2337f6d54778694a5c661163e79f9a22b279bb32
4
- data.tar.gz: f4b8be15108161721b9ad1d2b48ede9715ef5a73941fde89a8a02bd6c1a79676
3
+ metadata.gz: 3edae2de4ab3ae24151dd71c0290d210d0fd179a45c33c54489acd55255a29ee
4
+ data.tar.gz: a53fcf76ce1ed853a1780e482e9a18cd1fd3892bff1b50673b346c8fab41a2e7
5
5
  SHA512:
6
- metadata.gz: e986c9049350c61178690483c17b6a1ad1c905a7ed513ba101d1eb6d1718d22fddf67a82e2c436afd9f6b6370460030eaf12621b701dfffa3cee53216a66d4fa
7
- data.tar.gz: b2a46622619b7bc69b04decccba76197f98624ebaa636d570e21d8db9983ad8e7d075cc025e996708fe1c02dac5b35fc579c1b282f87b1090cd9bb2f3627c671
6
+ metadata.gz: 91247ebc9a98da4a399e1c3b5e050d42929f7c7588d690b33f54f3b67dc09dd6eb03d7b3419afb595cd0783258b2ffa9eb61373d1c8cab847c6da9eb3af0dcd1
7
+ data.tar.gz: b85506430333e00cd2a3d697217aacef71909838c75f62bac800a32e88db321d5a314fac2611b6733584131e46d4b33ce33886c48ac286e39a14b08a00f6e4a0
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)
@@ -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)
@@ -107,7 +109,7 @@ Nextgen can optionally install and configure these Node packages to work nicely
107
109
  [Vite](https://vitejs.dev) (pronounced _veet_) is a next generation Node-based frontend build system and hot-reloading dev server. It can completely take the place of the asset pipeline and integrate seamlessly with Rails via the [vite_rails](https://github.com/ElMassimo/vite_ruby) gem. If you opt-in, Nextgen can set you up with Vite and adds a bunch of vite_rails best practices:
108
110
 
109
111
  - All frontend sources (CSS, JS, images) are moved to `app/frontend`
110
- - A `yarn start` script is used to start the Rails server and Vite dev server
112
+ - A `bin/dev` script is used to start the Rails server and Vite dev server
111
113
  - The [autoprefixer](https://github.com/postcss/autoprefixer) package is installed and activated via PostCSS
112
114
  - A base set of CSS files are added, including [modern_normalize](https://github.com/sindresorhus/modern-normalize)
113
115
  - A Vite-compatible inline SVG helper is added
@@ -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
@@ -15,6 +15,11 @@ copy_file "DEPLOYMENT.md"
15
15
  say_git "Create a Procfile"
16
16
  template "Procfile.tt"
17
17
 
18
+ unless File.exist?("bin/dev")
19
+ say_git "Create bin/dev script"
20
+ copy_file "bin/dev", mode: :preserve
21
+ end
22
+
18
23
  say_git "Set up default rake task"
19
24
  test_task = "test:all" if minitest?
20
25
  append_to_file "Rakefile", <<~RUBY
@@ -35,14 +40,15 @@ if File.exist?("test/application_system_test_case.rb")
35
40
  gsub_file "Gemfile", /gem "selenium-webdriver"$/, '\0, require: false'
36
41
  end
37
42
 
38
- if File.exist?(".ruby-version") && File.read(".ruby-version").match?(/\A\d+\.\d+.\d+.\s*\z/m)
39
- say_git "DRY up Gemfile and .ruby-version file"
40
- replacement = if bundler_ruby_file_supported?
41
- 'ruby file: ".ruby-version"'
42
- else
43
- 'ruby Pathname.new(__dir__).join(".ruby-version").read.strip'
44
- end
45
- 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}"
46
52
  end
47
53
 
48
54
  if File.exist?("app/views/layouts/application.html.erb")
@@ -65,7 +71,7 @@ gsub_file "config/environments/production.rb",
65
71
 
66
72
  if File.exist?("config/database.yml")
67
73
  say_git "Create initial schema.rb"
68
- rails_command "db:prepare"
74
+ rails_command "db:create db:migrate"
69
75
  end
70
76
 
71
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
 
@@ -96,8 +100,7 @@ say_git "Add a `yarn start` script"
96
100
  start = "concurrently -i -k --kill-others-on-fail -p none 'RUBY_DEBUG_OPEN=true bin/rails s' 'bin/vite dev'"
97
101
  add_package_json_script(start:)
98
102
  add_yarn_package "concurrently", dev: true
99
- gsub_file "README.md", %r{bin/rails s(erver)?}, "yarn start"
100
- gsub_file "bin/setup", %r{bin/rails s(erver)?}, "yarn start"
103
+ copy_file "bin/dev-yarn", "bin/dev", mode: :preserve, force: true
101
104
  remove_file "Procfile.dev"
102
105
 
103
106
  say_git "Add Safari cache workaround in development"
@@ -117,3 +120,19 @@ comment_lines "config/environments/development.rb", /^\s*config\.assets\./
117
120
  comment_lines "config/environments/production.rb", /^\s*config\.assets\./
118
121
  gsub_file "app/views/layouts/application.html.erb", /^.*<%= stylesheet_link_tag.*$/, ""
119
122
  remove_gem "sprockets-rails"
123
+
124
+ if File.exist?(".github/workflows/ci.yml")
125
+ say_git "Add Node steps to CI workflow"
126
+ node_spec = File.exist?(".node-version") ? 'node-version-file: ".node-version"' : 'node-version: "lts/*"'
127
+ inject_into_file ".github/workflows/ci.yml", <<-YAML, before: /^\s+- name: Run tests/
128
+
129
+ - name: Set up Node
130
+ uses: actions/setup-node@v4
131
+ with:
132
+ #{node_spec}
133
+ cache: yarn
134
+
135
+ - name: Install Yarn packages
136
+ run: npx --yes ci
137
+ YAML
138
+ 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.17.1"
4
+ VERSION = "0.19.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
 
@@ -38,7 +38,7 @@ bin/setup
38
38
  Start the Rails server with this command:
39
39
 
40
40
  ```
41
- bin/rails s
41
+ bin/dev
42
42
  ```
43
43
 
44
44
  The app will be located at <http://localhost:3000/>.
data/template/bin/dev ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ exec "./bin/rails", "server", *ARGV
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ exec "yarn", "start", *ARGV
data/template/bin/setup CHANGED
@@ -20,7 +20,7 @@ def setup!
20
20
  end
21
21
 
22
22
  say_status :Ready!,
23
- "Use #{colorize("bin/rails s", :yellow)} to start the app, " \
23
+ "Use #{colorize("bin/dev", :yellow)} to start the app, " \
24
24
  "or #{colorize("bin/rake", :yellow)} to run tests"
25
25
  end
26
26
 
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.17.1
4
+ version: 0.19.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-07-25 00:00:00.000000000 Z
11
+ date: 2024-08-10 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
@@ -167,6 +164,8 @@ files:
167
164
  - template/app/frontend/stylesheets/reset.css
168
165
  - template/app/helpers/inline_svg_helper.rb
169
166
  - template/app/views/home/index.html.erb.tt
167
+ - template/bin/dev
168
+ - template/bin/dev-yarn
170
169
  - template/bin/setup
171
170
  - template/config/environments/staging.rb
172
171
  - template/config/initializers/generators.rb
@@ -222,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
221
  - !ruby/object:Gem::Version
223
222
  version: '0'
224
223
  requirements: []
225
- rubygems_version: 3.5.11
224
+ rubygems_version: 3.5.16
226
225
  signing_key:
227
226
  specification_version: 4
228
227
  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 -%>