Last active
August 13, 2017 18:24
-
-
Save ShimShtein/341b746f15826261053e97c2f435ff1a to your computer and use it in GitHub Desktop.
Inspecting provisioning templates with Rubocop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ErbStrip | |
ERB_REGEX = /(?<start_tag><%[-=]?)(?<script>([^#]).*?)(?<end_tag>-?%>)/m | |
def initialize(source) | |
@source = source | |
end | |
def strip | |
out = '' | |
current_position = 0 | |
while (match = next_erb(current_position)) | |
out << fill_newlines(current_position, match.begin(2) - 1) | |
out << match[:script] | |
out << ';' | |
out << ' ' * (match[:end_tag].length - 1) | |
current_position = match.end(3) | |
end | |
out | |
end | |
def next_erb(start_pos) | |
@source.match(ERB_REGEX, start_pos) | |
end | |
def fill_newlines(start, finish) | |
newlines = @source[start..finish].split("\n") | |
newlines.map { |line| ' ' * line.length }.join("\n") | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
module RuboCop | |
module Cop | |
module Foreman | |
# This cop checks for calls to foreman_url without params | |
class ForemanUrl < Cop | |
MSG = 'Call foreman_url with (\'built\') `%s`.'.freeze | |
def_node_matcher :foreman_url_call?, '(send nil :foreman_url)' | |
def on_send(node) | |
return unless foreman_url_call?(node) | |
add_offense(node, :expression) | |
end | |
private | |
def message(node) | |
format(MSG, node.source) | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# RuboCop::TargetFinder.new(nil) | |
module RuboCop | |
class TargetFinder | |
def ruby_file_with_erb?(file) | |
ruby_file_without_erb?(file) || File.extname(file) == '.erb' | |
end | |
alias_method :ruby_file_without_erb?, :ruby_file? | |
alias_method :ruby_file?, :ruby_file_with_erb? | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/ruby | |
unless ARGV.length == 1 | |
print <<-MESSAGE | |
Usage: | |
inspect_template /path/to/template_source.erb | |
MESSAGE | |
exit | |
end | |
require 'tempfile' | |
load 'erb_strip.rb' | |
load 'rubocop_json_processor.rb' | |
template_source_file = ARGV[0] | |
template_source_buffer = File.read(template_source_file) | |
template_destination = File.basename(template_source_file, '.erb') | |
Tempfile.open([template_destination, '.erb']) do |modified_template| | |
modified_template_buffer = ErbStrip.new(template_source_buffer).strip | |
modified_template.write(modified_template_buffer) | |
modified_template.flush | |
json_temp_file = Tempfile.new(['template_report', '.json']) | |
json_temp_file_name = json_temp_file.path | |
json_temp_file.close # we don't need this file to remain open. | |
`cat #{modified_template.path} | rubocop -d -s "#{template_source_file}" -r "#{Dir.pwd}/foreman_callback_cop.rb" --only "Foreman/ForemanUrl" -r "#{Dir.pwd}/foreman_erb_monkey_patch.rb" --format json --out #{json_temp_file_name}` | |
RubocopJsonProcessor.new(json_temp_file_name).to_clang | |
json_temp_file.unlink | |
end | |
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
class RubocopJsonProcessor | |
def initialize(json_file) | |
@report = JSON.parse(File.read(json_file)) | |
end | |
def to_clang | |
@report['files'].each do |file_report| | |
report_file(file_report['path'], file_report['offenses']) | |
end | |
end | |
private | |
def report_file(filename, offenses) | |
report "File: \"#{filename}\"" | |
buffer = File.read(filename) | |
lines = buffer.split("\n") | |
offenses.each do |offense_report| | |
report_offense(lines, offense_report) | |
end | |
end | |
def report_offense(lines, offense) | |
report "Message: #{offense['message']}" | |
report 'Source:' | |
report_source(lines, offense['location']) | |
end | |
def report_source(lines, location) | |
report lines[location['line'] - 1] | |
highlight = (' ' * (location['column'] - 1)) + ('^' * location['length']) | |
report highlight | |
end | |
def report(line) | |
puts line | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment