Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## master (unreleased)

* Adds Sidekiq generator. ([@TheZero0-ctrl][])
* Update Tailwind generator to use tailwindcss-rails gem instead of manually installing everything via npm ([@coolprobn][])
* Fixed callback method name for Google OAuth2 Omniauth ([@coezbek][] & [@coolprobn][])

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ The boring generator introduces following generators:
- Install Annotate: `rails generate boring:annotate:install`
- Install CanCanCan: `rails generate boring:cancancan:install`
- Install Gitlab CI: `rails generate boring:ci:gitlab_ci:install`
- Install Sidekiq: `rails generate boring:sidekiq:install`

## Screencasts

Expand Down
93 changes: 93 additions & 0 deletions lib/generators/boring/sidekiq/install/install_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: true

require "boring_generators/generator_helper"

module Boring
module Sidekiq
class InstallGenerator < Rails::Generators::Base
include BoringGenerators::GeneratorHelper

desc "Adds Sidekiq to the application"
source_root File.expand_path("templates", __dir__)

class_option :skip_web_ui,
type: :boolean,
aliases: "-sw",
default: false,
desc:
"Tell us if you want to skip sidekiq routes for viewing Web UI. Defaults to false."
class_option :skip_authenticated_web_ui,
type: :boolean,
aliases: "-saw",
default: false,
desc:
"Tell us if you want sidekiq web UI to only be accessed by authenticated users. Defaults to false."
class_option :skip_procfile_config,
type: :boolean,
aliases: "-sp",
default: false,
desc:
"Tell us if you want to skip adding sidekiq worker to Procfile. Defaults to false."

def add_sidekiq_gem
say "Adding sidekiq gem to Gemfile", :green
check_and_install_gem("sidekiq")
bundle_install
end
Comment on lines +32 to +36
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid double bundling; check_and_install_gem already runs bundle install.

This currently triggers bundle install twice, slowing the generator.

Apply this diff:

   def add_sidekiq_gem
     say "Adding sidekiq gem to Gemfile", :green
     check_and_install_gem("sidekiq")
-    bundle_install
   end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def add_sidekiq_gem
say "Adding sidekiq gem to Gemfile", :green
check_and_install_gem("sidekiq")
bundle_install
end
def add_sidekiq_gem
say "Adding sidekiq gem to Gemfile", :green
check_and_install_gem("sidekiq")
end
🤖 Prompt for AI Agents
In lib/generators/boring/sidekiq/install/install_generator.rb around lines 32 to
36, the generator calls bundle_install after check_and_install_gem even though
check_and_install_gem already performs bundling; remove the redundant
bundle_install call so the Gemfile is only bundled once, leaving the say message
and check_and_install_gem invocation intact.


def set_sidekiq_as_active_job_adapter
say "Setting sidekiq as active_job adapter", :green

inject_into_file "config/application.rb",
optimize_indentation(
"config.active_job.queue_adapter = :sidekiq\n",
4
),
after: /class Application < Rails::Application\n/
end

def add_sidekiq_web_ui
return if options[:skip_web_ui]

say "Adding sidekiq web UI", :green

if options[:skip_authenticated_web_ui]
route = "mount Sidekiq::Web => '/sidekiq'\n\n"
else
route = <<~RUBY
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end

RUBY
end

Comment on lines +49 to +64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Don’t assume Devise; generate a safe route that works without it.

Using authenticate :user will break apps without Devise. Provide a conditional fallback so routes compile even when Devise isn’t installed.

Apply this diff:

   def add_sidekiq_web_ui
     return if options[:skip_web_ui]
 
     say "Adding sidekiq web UI", :green
 
-    if options[:skip_authenticated_web_ui]
-      route = "mount Sidekiq::Web => '/sidekiq'\n\n"
-    else
-      route = <<~RUBY
-        authenticate :user do
-          mount Sidekiq::Web => '/sidekiq'
-        end
-
-      RUBY
-    end
+    mount_line = "mount Sidekiq::Web => '/sidekiq'"
+    if options[:skip_authenticated_web_ui]
+      route = "#{mount_line}\n\n"
+    else
+      route = <<~RUBY
+        if defined?(Devise)
+          authenticate :user do
+            #{mount_line}
+          end
+        else
+          #{mount_line}
+        end
+
+      RUBY
+    end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def add_sidekiq_web_ui
return if options[:skip_web_ui]
say "Adding sidekiq web UI", :green
if options[:skip_authenticated_web_ui]
route = "mount Sidekiq::Web => '/sidekiq'\n\n"
else
route = <<~RUBY
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
RUBY
end
def add_sidekiq_web_ui
return if options[:skip_web_ui]
say "Adding sidekiq web UI", :green
mount_line = "mount Sidekiq::Web => '/sidekiq'"
if options[:skip_authenticated_web_ui]
route = "#{mount_line}\n\n"
else
route = <<~RUBY
if defined?(Devise)
authenticate :user do
#{mount_line}
end
else
#{mount_line}
end
RUBY
end
🤖 Prompt for AI Agents
In lib/generators/boring/sidekiq/install/install_generator.rb around lines 49 to
64, the generator unconditionally uses authenticate :user (Devise), which will
break apps without Devise; change the generated route to wrap the authenticate
block in a runtime check and provide a fallback mount so routes compile without
Devise. Replace the current route assignment with a HEREDOC that emits: if
defined?(Devise) then authenticate :user do mount Sidekiq::Web => '/sidekiq' end
else mount Sidekiq::Web => '/sidekiq' end (preserving newlines/indentation) so
the generated routes work whether or not Devise is installed.

inject_into_file "config/routes.rb",
"require 'sidekiq/web'\n\n",
before: "Rails.application.routes.draw do\n"

inject_into_file "config/routes.rb",
optimize_indentation(route, 2),
after: "Rails.application.routes.draw do\n"
end

def add_sidekiq_worker_to_procfile
return if options[:skip_procfile_config] || !File.exist?("Procfile.dev")

say "Adding sidekiq worker to Procfile.dev", :green
append_to_file "Procfile.dev", "worker: bundle exec sidekiq"
end
Comment on lines +74 to +79
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Append worker: on a new line and avoid duplicates in Procfile.dev.

Without a newline, the worker entry can be glued to the last line. Also, prevent multiple worker lines across repeated runs.

Apply this diff:

   def add_sidekiq_worker_to_procfile
     return if options[:skip_procfile_config] || !File.exist?("Procfile.dev")
 
     say "Adding sidekiq worker to Procfile.dev", :green
-    append_to_file "Procfile.dev", "worker: bundle exec sidekiq"
+    path = "Procfile.dev"
+    content = File.read(path)
+    return if content.include?("worker: bundle exec sidekiq")
+
+    needs_newline = !content.end_with?("\n")
+    append_to_file path, "#{needs_newline ? "\n" : ""}worker: bundle exec sidekiq\n"
   end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def add_sidekiq_worker_to_procfile
return if options[:skip_procfile_config] || !File.exist?("Procfile.dev")
say "Adding sidekiq worker to Procfile.dev", :green
append_to_file "Procfile.dev", "worker: bundle exec sidekiq"
end
def add_sidekiq_worker_to_procfile
return if options[:skip_procfile_config] || !File.exist?("Procfile.dev")
say "Adding sidekiq worker to Procfile.dev", :green
path = "Procfile.dev"
content = File.read(path)
return if content.include?("worker: bundle exec sidekiq")
needs_newline = !content.end_with?("\n")
append_to_file path, "#{needs_newline ? "\n" : ""}worker: bundle exec sidekiq\n"
end
🤖 Prompt for AI Agents
In lib/generators/boring/sidekiq/install/install_generator.rb around lines 74 to
79, the generator appends "worker: bundle exec sidekiq" without ensuring a
preceding newline and without checking for duplicates; update the method to
first detect an existing Procfile.dev entry for a sidekiq worker and do nothing
if found, otherwise append the worker line preceded by a newline (or ensure the
file ends with a newline before appending) so the new entry stays on its own
line and repeated runs do not create duplicate worker lines.


def show_message
return if options[:skip_routes]

if options[:authenticate_routes_with_devise]
readme "README"
else
say "\nWe've added Sidekiq routes. Please protect it as necessary to suit your requirements.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update to " ... ... Please protect it with authentication as necessary ... ... ..."

:yellow
end
end
Comment on lines +81 to +90
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix options mismatch in show_message.

skip_routes and authenticate_routes_with_devise aren’t declared; the message may be misleading when --skip_web_ui is used. Use existing options to decide what to print/read.

Apply this diff:

   def show_message
-    return if options[:skip_routes]
-
-    if options[:authenticate_routes_with_devise]
-      readme "README"
-    else
-      say "\nWe've added Sidekiq routes. Please protect it as necessary to suit your requirements.",
-          :yellow
-    end
+    return if options[:skip_web_ui]
+
+    if options[:skip_authenticated_web_ui]
+      say "\nWe've added Sidekiq routes. Please protect it with authentication as necessary to suit your requirements.",
+          :yellow
+    else
+      readme "README"
+    end
   end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def show_message
return if options[:skip_routes]
if options[:authenticate_routes_with_devise]
readme "README"
else
say "\nWe've added Sidekiq routes. Please protect it as necessary to suit your requirements.",
:yellow
end
end
def show_message
return if options[:skip_web_ui]
if options[:skip_authenticated_web_ui]
say "\nWe've added Sidekiq routes. Please protect it with authentication as necessary to suit your requirements.",
:yellow
else
readme "README"
end
end
🤖 Prompt for AI Agents
In lib/generators/boring/sidekiq/install/install_generator.rb around lines 81 to
90, the show_message method checks non-existent options (:skip_routes and
:authenticate_routes_with_devise) which can produce incorrect output; change it
to use the actual options—return early if options[:skip_web_ui], and branch on
options[:authenticate_with_devise] so that when authenticate_with_devise is true
you call readme "README" otherwise you print the yellow notice about protecting
the Sidekiq web UI.

end
end
end
12 changes: 12 additions & 0 deletions lib/generators/boring/sidekiq/install/templates/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
===============================================================================

We've protected Sidekiq routes with Devise to ensure only authenticated users can access them.
This is implemented in the following snippet located in the config/routes.rb file.
```
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
```
Please adjust it as necessary to suit your requirements.

===============================================================================
76 changes: 76 additions & 0 deletions test/generators/sidekiq_install_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true

require "test_helper"
require "generators/boring/sidekiq/install/install_generator"

class SidekiqInstallGeneratorTest < Rails::Generators::TestCase
tests Boring::Sidekiq::InstallGenerator
setup :build_app
teardown :teardown_app

include GeneratorHelper
include ActiveSupport::Testing::Isolation

def destination_root
app_path
end

def test_should_configure_sidekiq
Dir.chdir(app_path) do
add_procfile
quietly { run_generator }

assert_gem "sidekiq"
assert_file "config/application.rb" do |content|
assert_match(/config\.active_job\.queue_adapter = :sidekiq/, content)
end
assert_file "config/routes.rb" do |content|
assert_match(/require 'sidekiq\/web'/, content)
assert_match(/authenticate :user do/, content)
assert_match(/mount Sidekiq::Web/, content)
end

assert_file "Procfile.dev" do |content|
assert_match(/worker: bundle exec sidekiq/, content)
end
end
end

def test_should_skip_sidekiq_web_ui
Dir.chdir(app_path) do
quietly { run_generator %w[--skip_web_ui] }

assert_file "config/routes.rb" do |content|
assert_no_match(/mount Sidekiq::Web/, content)
end
end
end
Comment on lines +39 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick

Also assert require 'sidekiq/web' is not added when Web UI is skipped.

Strengthens the contract when --skip_web_ui is used.

Apply this diff:

   assert_file "config/routes.rb" do |content|
     assert_no_match(/mount Sidekiq::Web/, content)
+    assert_no_match(/require 'sidekiq\/web'/, content)
   end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_should_skip_sidekiq_web_ui
Dir.chdir(app_path) do
quietly { run_generator %w[--skip_web_ui] }
assert_file "config/routes.rb" do |content|
assert_no_match(/mount Sidekiq::Web/, content)
end
end
end
def test_should_skip_sidekiq_web_ui
Dir.chdir(app_path) do
quietly { run_generator %w[--skip_web_ui] }
assert_file "config/routes.rb" do |content|
assert_no_match(/mount Sidekiq::Web/, content)
assert_no_match(/require 'sidekiq\/web'/, content)
end
end
end
🤖 Prompt for AI Agents
In test/generators/sidekiq_install_generator_test.rb around lines 39 to 47, the
test for --skip_web_ui checks that routes do not mount Sidekiq::Web but doesn't
assert that the require 'sidekiq/web' line is also omitted; update the assertion
block to also assert_no_match for a require statement (e.g.
assert_no_match(/require ['"]sidekiq\/web['"]/, content)) so the test fails if
the generator inadvertently adds the require when Web UI is skipped.


def test_should_skip_authenticated_web_ui
Dir.chdir(app_path) do
quietly { run_generator %w[--skip_authenticated_web_ui] }

assert_file "config/routes.rb" do |content|
refute_match(/authenticate :user do/, content)
assert_match(/mount Sidekiq::Web/, content)
end
end
end

def test_should_skip_procfile_config
Dir.chdir(app_path) do
add_procfile
quietly { run_generator %w[--skip_procfile_config] }

assert_file "Procfile.dev" do |content|
assert_no_match(/worker: bundle exec sidekiq/, content)
end
end
end

private

def add_procfile
File.write("#{app_path}/Procfile.dev", "web: bin/rails server -p 3000 -b 0.0.0.0")
end
end