diff --git a/NEWS.md b/NEWS.md index 44770f5bd..be26e7a10 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ Unreleased * Remove `suspenders` system executable * Introduce `suspenders:accessibility` generator * Introduce `Suspenders::Generators::APIAppUnsupported` module and concern +* Introduce `suspenders:rake` generator 20230113.0 (January, 13, 2023) diff --git a/README.md b/README.md index 27d95fa2d..8d769565f 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,16 @@ Installs [capybara_accessibility_audit] and [capybara_accessible_selectors] [capybara_accessibility_audit]: https://github.com/thoughtbot/capybara_accessibility_audit [capybara_accessible_selectors]: https://github.com/citizensadvice/capybara_accessible_selectors +### Rake + +Configures the default Rake task to audit and lint the codebase with +[bundler-audit][] and [standard][]. + +`/bin/rails g suspenders:rake` + + [bundler-audit]: https://github.com/rubysec/bundler-audit + [standard]: https://github.com/standardrb/standard + ## Contributing See the [CONTRIBUTING] document. diff --git a/lib/generators/suspenders/rake_generator.rb b/lib/generators/suspenders/rake_generator.rb new file mode 100644 index 000000000..e8b276e2e --- /dev/null +++ b/lib/generators/suspenders/rake_generator.rb @@ -0,0 +1,25 @@ +module Suspenders + module Generators + class RakeGenerator < Rails::Generators::Base + source_root File.expand_path("../../templates/rake", __FILE__) + desc(<<~TEXT) + Configures the default Rake task to audit and lint the codebase with `bundler-audit` and `standard`. + TEXT + + def add_bundler_audit_and_standard + gem_group :development, :test do + gem "bundler-audit", ">= 0.7.0", require: false + gem "standard" + end + Bundler.with_unbundled_env { run "bundle install" } + end + + def configurea_rake_task + copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake" + + insert_into_file "Rakefile", "\nrequire \"standard/rake\"", after: "require_relative \"config/application\"" + append_file "Rakefile", %(\ntask default: %i[bundle:audit standard]\n) + end + end + end +end diff --git a/lib/generators/templates/rake/bundler_audit.rake b/lib/generators/templates/rake/bundler_audit.rake new file mode 100644 index 000000000..72f6b5120 --- /dev/null +++ b/lib/generators/templates/rake/bundler_audit.rake @@ -0,0 +1,4 @@ +if Rails.env.development? || Rails.env.test? + require "bundler/audit/task" + Bundler::Audit::Task.new +end diff --git a/test/generators/suspenders/rake_generator_test.rb b/test/generators/suspenders/rake_generator_test.rb new file mode 100644 index 000000000..5b9cc836f --- /dev/null +++ b/test/generators/suspenders/rake_generator_test.rb @@ -0,0 +1,99 @@ +require "test_helper" +require "generators/suspenders/rake_generator" + +module Suspenders + module Generators + class RakeGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::RakeGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "adds gems to Gemfile" do + expected_output = <<~RUBY + group :development, :test do + gem "bundler-audit", ">= 0.7.0", require: false + gem "standard" + end + RUBY + + run_generator + + assert_file app_root("Gemfile") do |file| + assert_match(expected_output, file) + end + end + + test "installs gems with Bundler" do + Bundler.stubs(:with_unbundled_env).yields + generator.expects(:run).with("bundle install").once + + capture(:stdout) do + generator.add_bundler_audit_and_standard + end + end + + test "creates custom Rake task" do + expected_rake_task = <<~RUBY + if Rails.env.development? || Rails.env.test? + require "bundler/audit/task" + Bundler::Audit::Task.new + end + RUBY + + run_generator + + assert_file app_root("lib/tasks/bundler_audit.rake") do |file| + assert_match expected_rake_task, file + end + end + + test "modifies existing Rakefile" do + rakefile = <<~RUBY + require_relative "config/application" + + Rails.application.load_tasks + RUBY + File.open(app_root("Rakefile"), "w") { _1.write rakefile } + + expected_rakefile = <<~RUBY + require_relative "config/application" + require "standard/rake" + + Rails.application.load_tasks + + task default: %i[bundle:audit standard] + RUBY + + run_generator + + assert_file app_root("Rakefile") do |file| + assert_equal expected_rakefile, file + end + end + + test "generator has a description" do + description = <<~TEXT + Configures the default Rake task to audit and lint the codebase with `bundler-audit` and `standard`. + TEXT + + assert_equal description, generator_class.desc + end + + private + + def prepare_destination + touch "Gemfile" + backup_file "Rakefile" + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_file_if_exists "lib/tasks/bundler_audit.rake" + restore_file "Rakefile" + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 060d7dc22..3fb50d589 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -68,8 +68,6 @@ class Application < Rails::Application restore_file "config/application.rb" end - private - def backup_file(file) FileUtils.mv app_root(file), app_root("#{file}.bak") touch file