Skip to content

Instantly share code, notes, and snippets.

@stem
Last active April 30, 2021 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stem/e0f71dc5c31f5187dad739023d7b50bf to your computer and use it in GitHub Desktop.
Save stem/e0f71dc5c31f5187dad739023d7b50bf to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require "yaml"
module RuboCop
module Cop
module Epicery
# Cop to ensure all jobs are properly configured :
# - inherits ::ApplicationJob WITH the :: to avoid nasty namespace issues
# - calls sidekiq_options queue: "something"
#
# TODO: make the queue name type a cop parameter (string|symbol)
# TODO: make the sidekiq config files pattern a cop parameter
# TODO: use memoization to avoid loading N times the sidekiq config
class Job < ::RuboCop::Cop::Base
extend AutoCorrector
def basename(node)
path = node.location.expression.source_buffer.name
File.basename(path)
end
def_node_matcher :class_name, <<~PATTERN
(class (const nil? $_) ...)
PATTERN
# check if this is the main class of this file, according
# to the rails file name convention : SomeClass is defined is some_class.rb
def main_class?(node)
name = class_name(node)
basename(node) == "#{name.to_s.underscore}.rb"
end
def in_subdir?(node, prefix)
path = node.location.expression.source_buffer.name
path = RuboCop::PathUtil.smart_path(path)
path.start_with?(prefix)
end
def_node_matcher :application_job?, <<~PATTERN
(class (const ...) (const cbase :ApplicationJob) ...)
PATTERN
def_node_matcher :queue_name?, <<~PATTERN
`(send nil? :sidekiq_options (hash <(pair (sym :queue) $(...)) ...>))
PATTERN
def on_class(node)
return unless in_subdir?(node, "app/jobs/")
return unless main_class?(node)
return add_offense(node, message: "Jobs should inherit from ::ApplicationJob") unless application_job?(node)
expression = queue_name?(node)
return add_offense(node, message: "Manually set a queue; the default is not executed!") unless expression
unless expression.children[0].is_a?(String)
add_offense(expression, message: "Use a string as the queue name") do |corrector|
corrector.replace(expression, expression.children[0].to_s.inspect)
end
end
known_queues = Dir.glob("#{__dir__}/../../**/sidekiq*.yml").flat_map do |file|
YAML.load(File.read(file))[:queues] # rubocop:disable Security/YAMLLoad
end
unless known_queues.include?(expression.children[0].to_s)
add_offense(expression, message: "Unkown queue name")
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment