Skip to content

Commit

Permalink
Merge branch 'master' into hotfix/debian12
Browse files Browse the repository at this point in the history
  • Loading branch information
RodrigoMNardi authored Sep 5, 2024
2 parents ad7bd1e + 102b07f commit fe213e9
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 74 deletions.
2 changes: 2 additions & 0 deletions lib/github/build/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def initialize(check_suite, github, jobs, logger_level: Logger::INFO)
def create_summary(rerun: false)
logger(Logger::INFO, "SUMMARY #{@stages.inspect}")

Github::Build::SkipOldTests.new(@check_suite).skip_old_tests

@stages.each do |stage_config|
create_check_run_stage(stage_config)
end
Expand Down
45 changes: 45 additions & 0 deletions lib/github/build/skip_old_tests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# skip_old_tests.rb
# Part of NetDEF CI System
#
# Copyright (c) 2024 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# frozen_string_literal: true

module Github
module Build
class SkipOldTests
attr_reader :stages

def initialize(check_suite)
@check_suite = check_suite
@github = Github::Check.new(@check_suite)
@stages = StageConfiguration.all.map { |config| "[CI] #{config.github_check_run_name}" }
@logger = GithubLogger.instance.create('github_skip_old_tests.log', Logger::INFO)
end

def skip_old_tests
%w[queued in_progress success failure queued].each do |status|
@github
.check_runs_for_ref(@check_suite.pull_request.repository,
@check_suite.commit_sha_ref, status: status)[:check_runs]
&.each { |check_run| skipping_old_test(check_run) }
end
end

private

def skipping_old_test(check_run)
return if check_run[:app][:name] != 'NetDEF CI Hook' or @stages.include?(check_run[:name])

@logger.info("Skipping old test suite: #{check_run[:name]}")
puts("Skipping old test suite: #{check_run[:name]}")

message = 'Old test suite, skipping...'
@github.skipped(check_run[:id], { title: "#{check_run[:name]} summary", summary: message })
end
end
end
end
29 changes: 11 additions & 18 deletions lib/github/build/summary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ def build_summary
msg = "Github::Build::Summary - #{@job.inspect}, #{current_stage.inspect}, bamboo info: #{bamboo_info}"
@pr_log.info(msg)

return if current_stage.cancelled?

# Update current stage
update_summary(current_stage)
# Check if current stage finished
Expand Down Expand Up @@ -71,7 +73,7 @@ def must_update_previous_stage(current_stage)
end

def must_cancel_next_stages(current_stage)
return if @job.success? or @job.in_progress? or @job.queued?
return unless current_stage.failure? or current_stage.skipped? or current_stage.cancelled?
return unless current_stage.configuration.mandatory?

Stage
Expand All @@ -96,7 +98,7 @@ def must_continue_next_stage(current_stage)
.where(configuration: { position: current_stage.configuration.position + 1 })
.first

return if next_stage.nil?
return if next_stage.nil? or next_stage.cancelled?

update_summary(next_stage)
end
Expand All @@ -110,56 +112,47 @@ def cancelling_next_stage(pending_stage)
"The previous stage failed and the remaining tests will be canceled.\nDetails at [#{url}](#{url})."
}

logger(Logger::INFO, "cancelling_next_stage - pending_stage: #{pending_stage.inspect}\n#{output}")
logger(Logger::INFO, "cancelling_next_stage - pending_stage: #{pending_stage.inspect}")

pending_stage.cancelled(@github, output: output)
pending_stage.jobs.each { |job| job.cancelled(@github) }
end

def finished_summary(stage)
logger(Logger::INFO, "Finished stage: #{stage.inspect}, CiJob status: #{@job.status}")
logger(Logger::INFO, "Finished stage: #{stage.inspect}, running? #{stage.reload.running?}")

return if @job.in_progress? or stage.running?

finished_stage_summary(stage)
end

def finished_stage_summary(stage)
logger(Logger::INFO, "finished_stage_summary: #{stage.inspect}. Reason Job: #{@job.inspect}")

url = "https://ci1.netdef.org/browse/#{stage.check_suite.bamboo_ci_ref}"
output = {
title: "#{stage.name} summary",
summary: "#{summary_basic_output(stage)}\nDetails at [#{url}](#{url}).".force_encoding('utf-8')
}

finished_stage_update(stage, output)

logger(Logger::INFO, "finished_stage_summary: #{stage.inspect} #{output.inspect}")
end

def finished_stage_update(stage, output)
if stage.jobs.failure.empty?
logger(Logger::WARN, "Stage: #{stage.name} finished - failure")
stage.success(@github, output: output, agent: @agent)
else
logger(Logger::WARN, "Stage: #{stage.name} finished - success")
stage.failure(@github, output: output, agent: @agent)
stage.success(@github, output: output, agent: @agent)

return
end

logger(Logger::WARN, "Stage: #{stage.name} finished - failure")
stage.failure(@github, output: output, agent: @agent)
end

def update_summary(stage)
logger(Logger::INFO, "Updating summary status #{stage.inspect} -> @job.status: #{@job.status}")

url = "https://ci1.netdef.org/browse/#{@check_suite.bamboo_ci_ref}"
output = {
title: "#{stage.name} summary",
summary: "#{summary_basic_output(stage)}\nDetails at [#{url}](#{url}).".force_encoding('utf-8')
}

logger(Logger::INFO, "update_summary: #{stage.inspect} #{output.inspect}")

logger(Logger::WARN, "Updating stage: #{stage.name} to in_progress")
stage.in_progress(@github, output: output)
stage.update_output(@github, output: output)
Expand Down
4 changes: 4 additions & 0 deletions lib/github/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def comment_reaction_thumb_down(repo, comment_id)
accept: Octokit::Preview::PREVIEW_TYPES[:reactions])
end

def check_runs_for_ref(repo, sha, status: 'queued')
@app.check_runs_for_ref(repo, sha, status: status, accept: Octokit::Preview::PREVIEW_TYPES[:checks])
end

def create(name)
@app.create_check_run(
@check_suite.pull_request.repository,
Expand Down
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
58 changes: 8 additions & 50 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']
@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,13 @@ 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, output: @output)
failures_stats if @job.name.downcase.match? 'topotest' and @failures.is_a? Array
end
@job.failure(@github_check)

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?

@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
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
return failures_stats if @failures.is_a? Array and !@failures.empty?

buffer
CiJobFetchTopotestFailures
.delay(run_at: 5.minutes.from_now, queue: 'fetch_topotest_failures')
.update(@job.id, 1)
end

def slack_notify_success
Expand Down
4 changes: 4 additions & 0 deletions lib/github_ci_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
require_relative 'github/update_status'
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 All @@ -36,7 +38,9 @@
require_relative 'helpers/sinatra_payload'
require_relative 'helpers/telemetry'

# Workers
require_relative '../workers/ci_job_status'
require_relative '../workers/ci_job_fetch_topotest_failures'

# Slack libs
require_relative 'slack/slack'
Expand Down
61 changes: 61 additions & 0 deletions spec/lib/github/build/action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,72 @@
allow(fake_github_check).to receive(:success).and_return(ci_job.check_suite)
allow(fake_github_check).to receive(:cancelled).and_return(ci_job.check_suite)
allow(fake_github_check).to receive(:queued).and_return(ci_job.check_suite)
allow(fake_github_check).to receive(:check_runs_for_ref).and_return({})
allow(BambooCi::Result).to receive(:fetch).and_return({})

stage
end

context 'when previous check suite has old tests' do
let(:ci_job) { create(:ci_job, stage: stage, check_suite: check_suite) }
let(:old_test) { create(:ci_job, stage: stage, check_suite: check_suite) }
let(:skip_info) do
{
check_runs: [
{
app: {
name: 'NetDEF CI Hook'
},
name: old_test.name,
id: 1
}
]
}
end

before do
old_test
allow(Stage).to receive(:create).and_return(stage)
allow(stage).to receive(:persisted?).and_return(false)
allow(fake_github_check).to receive(:check_runs_for_ref).and_return(skip_info)
end

it 'must create a stage' do
action.create_summary(rerun: false)
expect(check_suite.reload.stages.size).to eq(1)
end
end

context 'when previous check suite has old tests - but wrong app' do
let(:ci_job) { create(:ci_job, stage: stage, check_suite: check_suite) }
let(:old_test) { create(:ci_job, stage: stage, check_suite: check_suite) }
let(:skip_info) do
{
check_runs: [
{
app: {
name: 'NetDEF CI'
},
name: old_test.name,
id: 1
}
]
}
end

before do
old_test
allow(Stage).to receive(:create).and_return(stage)
allow(stage).to receive(:persisted?).and_return(false)
allow(fake_github_check).to receive(:check_runs_for_ref).and_return(skip_info)
end

it 'must create a stage' do
action.create_summary(rerun: false)
expect(check_suite.reload.stages.size).to eq(1)
end
end

context 'when could not create stage' do
let(:ci_job) { create(:ci_job, stage: stage, check_suite: check_suite) }

Expand Down
2 changes: 2 additions & 0 deletions spec/lib/github/build_plan_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
allow(fake_github_check).to receive(:in_progress).and_return(fake_check_run)
allow(fake_github_check).to receive(:queued).and_return(fake_check_run)
allow(fake_github_check).to receive(:fetch_username).and_return({})
allow(fake_github_check).to receive(:fetch_username).and_return({})
allow(fake_github_check).to receive(:check_runs_for_ref).and_return({})

allow(BambooCi::RunningPlan).to receive(:fetch).with(fake_plan_run.bamboo_reference).and_return(ci_jobs)
end
Expand Down
1 change: 1 addition & 0 deletions spec/lib/github/re_run/command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
allow(fake_github_check).to receive(:comment_reaction_thumb_up)
allow(fake_github_check).to receive(:skipped)
allow(fake_github_check).to receive(:fetch_username).and_return({})
allow(fake_github_check).to receive(:check_runs_for_ref).and_return({})

allow(BambooCi::PlanRun).to receive(:new).and_return(fake_plan_run)
allow(fake_plan_run).to receive(:start_plan).and_return(200)
Expand Down
Loading

0 comments on commit fe213e9

Please sign in to comment.