gitlab-org--gitlab-foss/lib/gitlab/ci/trace.rb

212 lines
5 KiB
Ruby
Raw Normal View History

module Gitlab
module Ci
class Trace
ArchiveError = Class.new(StandardError)
attr_reader :job
delegate :old_trace, to: :job
def initialize(job)
@job = job
end
def html(last_lines: nil)
read do |stream|
stream.html(last_lines: last_lines)
end
end
def raw(last_lines: nil)
read do |stream|
stream.raw(last_lines: last_lines)
end
end
def extract_coverage(regex)
read do |stream|
stream.extract_coverage(regex)
end
end
2017-09-25 12:54:08 -04:00
def extract_sections
read do |stream|
stream.extract_sections
end
end
def set(data)
2018-04-05 03:16:01 -04:00
write('w+b') do |stream|
data = job.hide_secrets(data)
stream.set(data)
end
end
def append(data, offset)
write('a+b') do |stream|
current_length = stream.size
break current_length unless current_length == offset
data = job.hide_secrets(data)
stream.append(data, offset)
stream.size
end
end
def exist?
trace_artifact&.exists? || job.trace_chunks.any? || current_path.present? || old_trace.present?
end
def read
stream = Gitlab::Ci::Trace::Stream.new do
2018-01-26 12:38:54 -05:00
if trace_artifact
2018-01-25 04:50:56 -05:00
trace_artifact.open
elsif job.trace_chunks.any?
2018-04-04 06:19:17 -04:00
Gitlab::Ci::Trace::ChunkedIO.new(job)
2018-01-25 04:50:56 -05:00
elsif current_path
File.open(current_path, "rb")
elsif old_trace
StringIO.new(old_trace)
end
end
yield stream
ensure
stream&.close
end
def write(mode)
stream = Gitlab::Ci::Trace::Stream.new do
2018-04-04 06:19:17 -04:00
if current_path
2018-04-05 03:16:01 -04:00
File.open(current_path, mode)
2018-04-04 06:19:17 -04:00
elsif Feature.enabled?('ci_enable_live_trace')
Gitlab::Ci::Trace::ChunkedIO.new(job)
2018-03-27 05:01:26 -04:00
else
2018-04-05 03:16:01 -04:00
File.open(ensure_path, mode)
2018-03-27 05:01:26 -04:00
end
end
yield(stream).tap do
job.touch if job.needs_touch?
end
ensure
stream&.close
end
def erase!
2018-01-26 12:38:54 -05:00
trace_artifact&.destroy
2018-01-25 08:46:38 -05:00
paths.each do |trace_path|
FileUtils.rm(trace_path, force: true)
end
job.trace_chunks.fast_destroy_all
job.erase_old_trace!
end
def archive!
raise ArchiveError, 'Already archived' if trace_artifact
raise ArchiveError, 'Job is not finished yet' unless job.complete?
if job.trace_chunks.any?
2018-04-04 06:19:17 -04:00
Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
archive_stream!(stream)
stream.destroy!
2018-03-28 13:13:08 -04:00
end
elsif current_path
File.open(current_path) do |stream|
archive_stream!(stream)
FileUtils.rm(current_path)
end
elsif old_trace
StringIO.new(old_trace, 'rb').tap do |stream|
archive_stream!(stream)
job.erase_old_trace!
end
end
end
private
def archive_stream!(stream)
clone_file!(stream, JobArtifactUploader.workhorse_upload_path) do |clone_path|
create_build_trace!(job, clone_path)
end
end
def clone_file!(src_stream, temp_dir)
FileUtils.mkdir_p(temp_dir)
Dir.mktmpdir('tmp-trace', temp_dir) do |dir_path|
temp_path = File.join(dir_path, "job.log")
FileUtils.touch(temp_path)
size = IO.copy_stream(src_stream, temp_path)
raise ArchiveError, 'Failed to copy stream' unless size == src_stream.size
2018-03-01 03:38:44 -05:00
yield(temp_path)
end
end
def create_build_trace!(job, path)
File.open(path) do |stream|
job.create_job_artifacts_trace!(
project: job.project,
file_type: :trace,
file: stream,
file_sha256: Digest::SHA256.file(path).hexdigest)
end
end
2018-03-29 04:43:32 -04:00
def ensure_path
return current_path if current_path
ensure_directory
default_path
end
def ensure_directory
unless Dir.exist?(default_directory)
FileUtils.mkdir_p(default_directory)
end
end
2018-01-26 12:00:29 -05:00
def current_path
@current_path ||= paths.find do |trace_path|
File.exist?(trace_path)
end
end
def paths
[
2018-01-26 12:38:54 -05:00
default_path,
deprecated_path
].compact
end
2018-01-26 12:38:54 -05:00
def default_directory
File.join(
Settings.gitlab_ci.builds_path,
2018-01-26 12:38:54 -05:00
job.created_at.utc.strftime("%Y_%m"),
job.project_id.to_s
)
end
2018-01-26 12:38:54 -05:00
def default_path
File.join(default_directory, "#{job.id}.log")
end
def deprecated_path
File.join(
Settings.gitlab_ci.builds_path,
job.created_at.utc.strftime("%Y_%m"),
job.project.ci_id.to_s,
"#{job.id}.log"
) if job.project&.ci_id
end
2018-01-25 04:50:56 -05:00
def trace_artifact
job.job_artifacts_trace
end
end
end
end