From 7cbc21d05e3c31a02a6a284c8d73b94617da3f24 Mon Sep 17 00:00:00 2001 From: minktom Date: Mon, 28 Apr 2025 10:16:59 +0200 Subject: [PATCH] Add GitHub Actions reporter to support custom offense formatting This commit introduces a new reporter, `GithubActionsReporter`, to format and display linter offenses in a way compatible with GitHub Actions annotations. It also updates CLI documentation and tests to reflect the added format option. New specs verify the reporter's behavior and output accuracy. --- .../reporters/github_actions_reporter.rb | 44 ++++++++++++++ spec/erb_lint/cli_spec.rb | 3 +- .../reporters/github_actions_reporter_spec.rb | 59 +++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 lib/erb_lint/reporters/github_actions_reporter.rb create mode 100644 spec/erb_lint/reporters/github_actions_reporter_spec.rb diff --git a/lib/erb_lint/reporters/github_actions_reporter.rb b/lib/erb_lint/reporters/github_actions_reporter.rb new file mode 100644 index 00000000..45dd5df3 --- /dev/null +++ b/lib/erb_lint/reporters/github_actions_reporter.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module ERBLint + module Reporters + class GithubActionsReporter < ERBLint::Reporter + ESCAPE_MAP = { "%" => "%25", "\n" => "%0A", "\r" => "%0D" }.freeze + + def preview; end + + def show + puts formatted_data + end + + private + + def formatted_data + formatted_files.join("\n") + end + + def formatted_files + processed_files.flat_map do |filename, offenses| + offenses.map do |offense| + format_offense(filename, offense) + end + end + end + + def format_offense(filename, offense) + message = github_escape("#{offense.simple_name}: #{offense.message}") + severity = github_severity(offense) + + "::#{severity} file=#{filename},line=#{offense.line_number},col=#{offense.column}::#{message}" + end + + def github_escape(string) + string.gsub(Regexp.union(ESCAPE_MAP.keys), ESCAPE_MAP) + end + + def github_severity(offense) + [nil, :error, :fatal].include?(offense.severity) ? "warning" : "error" + end + end + end +end diff --git a/spec/erb_lint/cli_spec.rb b/spec/erb_lint/cli_spec.rb index 1f60fa73..a6506498 100644 --- a/spec/erb_lint/cli_spec.rb +++ b/spec/erb_lint/cli_spec.rb @@ -92,7 +92,7 @@ def run(processed_source) it "shows format instructions" do expect { subject }.to( output(Regexp.new("Report offenses in the given format: " \ - "\\(compact, gitlab, json, junit, multiline\\) " \ + "\\(compact, github_actions, gitlab, json, junit, multiline\\) " \ "\\(default: multiline\\)")).to_stdout, ) end @@ -527,6 +527,7 @@ def run(processed_source) expect { subject }.to(output(Regexp.new(Regexp.escape(<<~EOF.strip))).to_stderr) nonexistentformat: is not a valid format. Available formats: - compact + - github_actions - gitlab - json - junit diff --git a/spec/erb_lint/reporters/github_actions_reporter_spec.rb b/spec/erb_lint/reporters/github_actions_reporter_spec.rb new file mode 100644 index 00000000..8d337049 --- /dev/null +++ b/spec/erb_lint/reporters/github_actions_reporter_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe ERBLint::Reporters::GithubActionsReporter do + describe ".show" do + subject { described_class.new(stats, false).show } + + let(:stats) do + ERBLint::Stats.new( + found: 2, + processed_files: { + "app/views/subscriptions/_loader.html.erb" => offenses, + }, + corrected: 1, + ) + end + + let(:offenses) do + [ + instance_double( + ERBLint::Offense, + message: "Extra space detected where there should be no space.", + line_number: 1, + column: 7, + simple_name: "SpaceInHtmlTag", + severity: :warning, + last_line: 1, + last_column: 9, + length: 2, + ), + instance_double( + ERBLint::Offense, + message: "Remove newline before `%>` to match start of tag.", + line_number: 52, + column: 10, + simple_name: "ClosingErbTagIndent", + severity: :error, + last_line: 54, + last_column: 10, + length: 10, + ), + ] + end + + let(:expected_lines) do + [ + "::error file=app/views/subscriptions/_loader.html.erb,line=1,col=7" \ + "::SpaceInHtmlTag: Extra space detected where there should be no space.", + "::warning file=app/views/subscriptions/_loader.html.erb,line=52,col=10" \ + "::ClosingErbTagIndent: Remove newline before `%25>` to match start of tag.", + ].join("\n") + end + + it "displays formatted offenses output" do + expect { subject }.to(output(expected_lines + "\n").to_stdout) + end + end +end