Refactor files structure (#20)

add tests and fix #2
This commit is contained in:
Miguel Savignano 2019-10-29 01:16:37 +01:00 committed by Andrew Mason
parent 97fef59c82
commit b796f9a6dd
8 changed files with 3527 additions and 125 deletions

View File

@ -0,0 +1,58 @@
# frozen_string_literal: true
class GithubCheckRunService
CHECK_NAME = 'Rubocop'
def initialize(report, github_data, report_adapter)
@report = report
@github_data = github_data
@report_adapter = report_adapter
@client = GithubClient.new(@github_data[:token], user_agent: 'rubocop-action')
end
def run
id = @client.post(
endpoint_url,
create_check_payload
)['id']
@summary = @report_adapter.summary(@report)
@annotations = @report_adapter.annotations(@report)
@conclusion = @report_adapter.conslusion(@report)
@client.patch(
"#{endpoint_url}/#{id}",
update_check_payload
)
end
private
def endpoint_url
"/repos/#{@github_data[:owner]}/#{@github_data[:repo]}/check-runs"
end
def create_check_payload
{
name: CHECK_NAME,
head_sha: @github_data[:sha],
status: 'in_progress',
started_at: Time.now.iso8601
}
end
def update_check_payload
{
name: CHECK_NAME,
head_sha: @github_data[:sha],
status: 'completed',
completed_at: Time.now.iso8601,
conclusion: @conclusion,
output: {
title: CHECK_NAME,
summary: @summary,
annotations: @annotations
}
}
end
end

40
lib/github_client.rb Normal file
View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class GithubClient
def initialize(github_token, user_agent: 'ruby')
@github_token = github_token
@user_agent = user_agent
end
def patch(url, body = {})
request_http do |http|
http.patch(url, body.to_json, headers)
end
end
def post(url, body = {})
request_http do |http|
http.post(url, body.to_json, headers)
end
end
private
def headers
@headers ||= {
"Content-Type": 'application/json',
"Accept": 'application/vnd.github.antiope-preview+json',
"Authorization": "Bearer #{@github_token}",
"User-Agent": @user_agent
}
end
def request_http
http = Net::HTTP.new('api.github.com', 443)
http.use_ssl = true
response = yield(http)
raise "#{response.message}: #{response.body}" if response.code.to_i >= 300
JSON.parse(response.body)
end
end

View File

@ -1,134 +1,29 @@
# frozen_string_literal: true
require 'net/http'
require 'json'
require 'time'
require_relative './report_adapter'
require_relative './github_check_run_service'
require_relative './github_client'
@GITHUB_SHA = ENV["GITHUB_SHA"]
@GITHUB_EVENT_PATH = ENV["GITHUB_EVENT_PATH"]
@GITHUB_TOKEN = ENV["GITHUB_TOKEN"]
@GITHUB_WORKSPACE = ENV["GITHUB_WORKSPACE"]
def read_json(path)
JSON.parse(File.read(path))
end
@event = JSON.parse(File.read(ENV["GITHUB_EVENT_PATH"]))
@repository = @event["repository"]
@owner = @repository["owner"]["login"]
@repo = @repository["name"]
@conclusion = "success"
@check_name = "Rubocop"
@headers = {
"Content-Type": 'application/json',
"Accept": 'application/vnd.github.antiope-preview+json',
"Authorization": "Bearer #{@GITHUB_TOKEN}",
"User-Agent": 'rubocop-action'
@event_json = read_json(ENV['GITHUB_EVENT_PATH']) if ENV['GITHUB_EVENT_PATH']
@github_data = {
sha: ENV['GITHUB_SHA'],
token: ENV['GITHUB_TOKEN'],
owner: ENV['GITHUB_REPOSITORY_OWNER'] || @event_json.dig('repository', 'owner', 'login'),
repo: ENV['GITHUB_REPOSITORY_NAME'] || @event_json.dig('repository', 'name')
}
def create_check
body = {
"name" => @check_name,
"head_sha" => @GITHUB_SHA,
"status" => "in_progress",
"started_at" => Time.now.iso8601
}
http = Net::HTTP.new('api.github.com', 443)
http.use_ssl = true
path = "/repos/#{@owner}/#{@repo}/check-runs"
resp = http.post(path, body.to_json, @headers)
if resp.code.to_i >= 300
raise resp.message
@report =
if ENV['REPORT_PATH']
read_json(ENV['REPORT_PATH'])
else
Dir.chdir(ENV['GITHUB_WORKSPACE']) { JSON.parse(`rubocop -f json`) }
end
data = JSON.parse(resp.body)
return data["id"]
end
def update_check(id, conclusion, output)
body = {
"name" => @check_name,
"completed_at" => Time.now.iso8601,
"conclusion" => conclusion,
"output" => output
}
http = Net::HTTP.new('api.github.com', 443)
http.use_ssl = true
path = "/repos/#{@owner}/#{@repo}/check-runs/#{id}"
resp = http.patch(path, body.to_json, @headers)
if resp.code.to_i >= 300
raise resp.message
end
end
@annotation_levels = {
"refactor" => 'failure',
"convention" => 'failure',
"warning" => 'warning',
"error" => 'failure',
"fatal" => 'failure'
}
def run_rubocop
annotations = annotation_messages
output = {
"title": @check_name,
"summary": "#{annotations.size} offense(s) found",
"annotations" => annotations
}
return { "output" => output, "conclusion" => @conclusion }
end
def annotation_messages
errors = nil
count = 0
annotation_list = []
Dir.chdir(@GITHUB_WORKSPACE) {
errors = JSON.parse(`rubocop --format json`)
}
errors["files"].each do |file|
path = file["path"]
offenses = file["offenses"]
offenses.each do |offense|
severity = offense["severity"]
message = offense["message"]
location = offense["location"]
annotation_level = @annotation_levels[severity]
count = count + 1
return annotation_list if count == 48
if annotation_level == "failure"
@conclusion = "failure"
end
annotation_list.push({
"path" => path,
"start_line" => location["start_line"],
"end_line" => location["start_line"],
"annotation_level": annotation_level,
"message" => message
})
end
end
return annotation_list
end
def run
id = create_check()
begin
results = run_rubocop()
conclusion = results["conclusion"]
output = results["output"]
update_check(id, conclusion, output)
rescue
update_check(id, "failure", nil)
fail
end
end
run()
GithubCheckRunService.new(@report, @github_data, ReportAdapter).run

54
lib/report_adapter.rb Normal file
View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
class ReportAdapter
class << self
CONCLUSION_TYPES = { failure: 'failure', success: 'success' }.freeze
ANNOTATION_LEVELS = {
'refactor' => 'failure',
'convention' => 'failure',
'warning' => 'warning',
'error' => 'failure',
'fatal' => 'failure'
}.freeze
def conslusion(report)
return CONCLUSION_TYPES[:failure] if total_offenses(report).positive?
CONCLUSION_TYPES[:success]
end
def summary(report)
"#{total_offenses(report)} offense(s) found"
end
def annotations(report)
annotation_list = []
count = 0
report['files'].each do |file|
file['offenses'].each do |offense|
count += 1
return annotation_list if count == 48
location = offense['location']
annotation_list.push({
'path' => file['path'],
'start_line' => location['start_line'],
'end_line' => location['last_line'],
'annotation_level' => annotation_level(offense['severity']),
'message' => offense['message']
})
end
end
end
private
def annotation_level(severity)
ANNOTATION_LEVELS[severity]
end
def total_offenses(report)
report.dig('summary', 'offense_count')
end
end
end

3301
spec/fixtures/report.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
require './spec/spec_helper'
describe GithubCheckRunService do
let(:rubocop_report) { JSON(File.read('./spec/fixtures/report.json')) }
let(:github_data) { { sha: 'sha', token: 'token', owner: 'owner', repo: 'repository_name' } }
let(:service) { GithubCheckRunService.new(rubocop_report, github_data, ReportAdapter) }
it '#run' do
stub_request(:any, 'https://api.github.com/repos/owner/repository_name/check-runs/id')
.to_return(status: 200, body: '{}')
stub_request(:any, 'https://api.github.com/repos/owner/repository_name/check-runs')
.to_return(status: 200, body: '{"id": "id"}')
output = service.run
expect(output).to be_a(Hash)
end
end

View File

@ -0,0 +1,30 @@
require './spec/spec_helper'
describe ReportAdapter do
let(:rubocop_report) {
JSON(File.read('./spec/fixtures/report.json'))
}
let(:adapter) { ReportAdapter }
it '.conslusion' do
result = adapter.conslusion(rubocop_report)
expect(result).to eq('failure')
end
it '.summary' do
result = adapter.summary(rubocop_report)
expect(result).to eq('201 offense(s) found')
end
it '.annotations' do
result = adapter.annotations(rubocop_report)
expect(result.first).to eq({
'path' => 'Gemfile',
'start_line' => 1,
'end_line' => 1,
'annotation_level' => 'failure',
'message' => 'Missing magic comment `# frozen_string_literal: true`.'
})
end
end

6
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,6 @@
require 'webmock/rspec'
require 'json'
require 'pry'
require './lib/report_adapter'
require './lib/github_check_run_service'
require './lib/github_client'