Skip to content

Commit

Permalink
Merge pull request #92 from FRRouting/master
Browse files Browse the repository at this point in the history
Release 2.3.7
  • Loading branch information
RodrigoMNardi authored Aug 23, 2024
2 parents 1e77306 + d8bba16 commit 02ddd8e
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 50 deletions.
39 changes: 39 additions & 0 deletions lib/github/topotest_failures/retrieve_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# retrieve_error.rb
# Part of NetDEF CI System
#
# Copyright (c) 2024 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# frozen_string_literal: true

module Github
module TopotestFailures
class RetrieveError
attr_reader :failures

def initialize(job)
@job = job
@failures = []
end

def retrieve
fetch_failures(BambooCi::Result.fetch(@job.job_ref))

@failures
end

def fetch_failures(output)
output.dig('testResults', 'failedTests', 'testResult')&.each do |test_result|
@failures << {
'suite' => test_result['className'],
'case' => test_result['methodName'],
'message' => test_result.dig('errors', 'error').map { |error| error['message'] }.join("\n"),
'execution_time' => test_result['durationInSeconds']
}
end
end
end
end
end
59 changes: 15 additions & 44 deletions lib/github/update_status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,12 @@ class UpdateStatus
def initialize(payload)
@status = payload['status']

@output =
if payload.dig('output', 'title').nil? and payload.dig('output', 'summary').nil?
{}
else
{ title: payload.dig('output', 'title'), summary: payload.dig('output', 'summary') }
end

@reference = payload['bamboo_ref'] || 'invalid_reference'
@job = CiJob.find_by(job_ref: payload['bamboo_ref'])
@check_suite = @job&.check_suite
@failures = payload['failures']

logger_initializer
logger(Logger::WARN, "UpdateStatus: #{@reference} #{@status} (Output in info log)")
logger(Logger::INFO, "UpdateStatus: #{@reference} #{@status} #{@output}")
end

def update
Expand Down Expand Up @@ -68,9 +59,9 @@ def failures_stats
def update_status
case @status
when 'in_progress'
@job.in_progress(@github_check, output: @output)
@job.in_progress(@github_check)
when 'success'
@job.success(@github_check, output: @output)
@job.success(@github_check)
slack_notify_success
else
failure
Expand Down Expand Up @@ -128,46 +119,26 @@ def current_execution?
# The unable2find string must match the phrase defined in the ci-files repository file
# github_checks/hook_api.py method __topotest_title_summary
def failure
unable2find = "There was some test that failed, but I couldn't find the log."
fetch_and_update_failures(unable2find) if !@output.empty? and @output[:summary].match?(unable2find)
@job.failure(@github_check)

@job.failure(@github_check, output: @output)
failures_stats if @job.name.downcase.match? 'topotest' and @failures.is_a? Array
retrieve_stats
end

def fetch_and_update_failures(to_be_replaced)
count = 0
begin
output = BambooCi::Result.fetch(@job.job_ref)
return if output.nil? or output.empty?
def retrieve_stats
return failures_stats if @failures.is_a? Array and !@failures.empty?

@output[:summary] = @output[:summary].sub(to_be_replaced, fetch_failures(output))[0..65_535]
rescue NoMethodError => e
logger Logger::ERROR, "#{e.class} #{e.message}"
count += 1
sleep 5
retry if count <= 10
end
retrieve_errors
end

def fetch_failures(output)
buffer = ''
output.dig('testResults', 'failedTests', 'testResult')&.each do |test_result|
message = ''
test_result.dig('errors', 'error').each do |error|
message += error['message']
buffer += message
end

@failures << {
'suite' => test_result['className'],
'case' => test_result['methodName'],
'message' => message,
'execution_time' => test_result['durationInSeconds']
}
end
def retrieve_errors
@retrieve_error = Github::TopotestFailures::RetrieveError.new(@job)
@retrieve_error.retrieve

return if @retrieve_error.failures.empty?

@failures = @retrieve_error.failures

buffer
failures_stats
end

def slack_notify_success
Expand Down
1 change: 1 addition & 0 deletions lib/github_ci_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
require_relative 'github/plan_execution/finished'
require_relative 'github/user_info'
require_relative 'github/build/skip_old_tests'
require_relative 'github/topotest_failures/retrieve_error'

# Helpers libs
require_relative 'helpers/configuration'
Expand Down
35 changes: 29 additions & 6 deletions spec/lib/github/update_status_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
allow(fake_github_check).to receive(:queued).and_return(ci_job.check_suite)

allow(Github::Build::UnavailableJobs).to receive(:new).and_return(fake_unavailable)

allow(BambooCi::Result).to receive(:fetch).and_return({})
end

context 'when Ci Job Checkout Code update from queued -> failure' do
Expand Down Expand Up @@ -276,8 +278,33 @@
update_status.update
end

it 'must update the output' do
expect(ci_job).to have_received(:failure).with(fake_github_check, output: expected_output)
it 'must create TopoTestFailure' do
expect(TopotestFailure.all.size).to eq(1)
expect(TopotestFailure.last.to_h).to eq(expected_topotest_failure)
end
end

context 'when updated a test that failed and it has no error output - AddressSanitizer' do
let(:payload) do
{
'status' => status,
'bamboo_ref' => ci_job.job_ref,
'output' => {
'title' => 'Failed test',
'summary' => 'Details at https://netdef.org/browse/FRR-PULLREQ3-ASAN9D12AMD64-123'
},
'failures' => []
}
end

before do
allow(CiJob).to receive(:find_by).and_return(ci_job)
allow(ci_job).to receive(:failure)
allow(BambooCi::Result).to receive(:fetch).and_return(fake_output)

ci_job.update(name: 'AddressSanitizer Debian 12 amd64')

update_status.update
end

it 'must create TopoTestFailure' do
Expand Down Expand Up @@ -323,10 +350,6 @@
update_status.update
end

it 'must maintain the same output' do
expect(ci_job).to have_received(:failure).with(fake_github_check, output: expected_output)
end

it 'must not create a TopoTestFailure' do
expect(TopotestFailure.all.size).to eq(0)
end
Expand Down
46 changes: 46 additions & 0 deletions tasks/retrieve_address_sanitizer_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# retrieve_address_sanitizer_error.rb
#
# > Overview
# The retrieve_address_sanitizer_error.rb script is part of the NetDEF CI System.
# It is designed to retrieve and log AddressSanitizer errors from CI jobs that have failed.
# The script processes CI jobs, retrieves errors using the Github::TopotestFailures::RetrieveError class,
# and logs these errors into the TopotestFailure model.
#
# Part of NetDEF CI System
#
# Copyright (c) 2024 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# frozen_string_literal: true

require_relative '../config/setup'

CiJob
.left_outer_joins(:topotest_failures)
.joins(:stage)
.where(topotest_failures: { id: nil })
.where("ci_jobs.name LIKE '%AddressSanitizer%'")
.where(status: :failure)
.where(stage: { status: :failure })
.where('ci_jobs.created_at > ?', 6.month.ago)
.each do |job|
next if job.topotest_failures.any?

CiJob.transaction do
failures = Github::TopotestFailures::RetrieveError.new(job).retrieve

puts "Found #{failures.size} failures for job #{job.job_ref}"

next if failures.empty?

failures.each do |failure|
TopotestFailure.create(ci_job: job,
test_suite: failure['suite'],
test_case: failure['case'],
message: failure['message'],
execution_time: failure['execution_time'])
end
end
end

0 comments on commit 02ddd8e

Please sign in to comment.