debian-mirror-gitlab/lib/gitlab/ci/trace.rb

242 lines
5.9 KiB
Ruby
Raw Normal View History

2018-12-13 13:39:08 +05:30
# frozen_string_literal: true
2017-08-17 22:00:37 +05:30
module Gitlab
module Ci
class Trace
2018-11-08 19:23:39 +05:30
include ExclusiveLeaseGuard
LEASE_TIMEOUT = 1.hour
2018-03-27 19:54:05 +05:30
ArchiveError = Class.new(StandardError)
2018-11-08 19:23:39 +05:30
AlreadyArchivedError = Class.new(StandardError)
2018-03-27 19:54:05 +05:30
2017-08-17 22:00:37 +05:30
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
2018-03-17 18:26:18 +05:30
def extract_sections
read do |stream|
stream.extract_sections
end
end
2017-08-17 22:00:37 +05:30
def set(data)
2018-10-15 14:42:47 +05:30
write('w+b') do |stream|
2017-08-17 22:00:37 +05:30
data = job.hide_secrets(data)
stream.set(data)
end
end
def append(data, offset)
2018-10-15 14:42:47 +05:30
write('a+b') do |stream|
2017-08-17 22:00:37 +05:30
current_length = stream.size
2018-10-15 14:42:47 +05:30
break current_length unless current_length == offset
2017-08-17 22:00:37 +05:30
data = job.hide_secrets(data)
stream.append(data, offset)
stream.size
end
end
def exist?
2018-10-15 14:42:47 +05:30
trace_artifact&.exists? || job.trace_chunks.any? || current_path.present? || old_trace.present?
2017-08-17 22:00:37 +05:30
end
def read
stream = Gitlab::Ci::Trace::Stream.new do
2018-03-17 18:26:18 +05:30
if trace_artifact
trace_artifact.open
2018-10-15 14:42:47 +05:30
elsif job.trace_chunks.any?
Gitlab::Ci::Trace::ChunkedIO.new(job)
2018-03-17 18:26:18 +05:30
elsif current_path
2017-08-17 22:00:37 +05:30
File.open(current_path, "rb")
elsif old_trace
StringIO.new(old_trace)
end
end
yield stream
ensure
stream&.close
end
2018-10-15 14:42:47 +05:30
def write(mode)
2017-08-17 22:00:37 +05:30
stream = Gitlab::Ci::Trace::Stream.new do
2018-11-08 19:23:39 +05:30
if trace_artifact
raise AlreadyArchivedError, 'Could not write to the archived trace'
elsif current_path
2018-10-15 14:42:47 +05:30
File.open(current_path, mode)
elsif Feature.enabled?('ci_enable_live_trace')
Gitlab::Ci::Trace::ChunkedIO.new(job)
else
File.open(ensure_path, mode)
end
2017-08-17 22:00:37 +05:30
end
yield(stream).tap do
job.touch if job.needs_touch?
end
ensure
stream&.close
end
def erase!
2018-11-08 19:23:39 +05:30
##
# Erase the archived trace
trace_artifact&.destroy!
##
# Erase the live trace
job.trace_chunks.fast_destroy_all # Destroy chunks of a live trace
FileUtils.rm_f(current_path) if current_path # Remove a trace file of a live trace
job.erase_old_trace! if job.has_old_trace? # Remove a trace in database of a live trace
ensure
@current_path = nil
end
2018-03-17 18:26:18 +05:30
2018-11-08 19:23:39 +05:30
def archive!
try_obtain_lease do
unsafe_archive!
2017-08-17 22:00:37 +05:30
end
end
2018-11-08 19:23:39 +05:30
private
def unsafe_archive!
raise AlreadyArchivedError, 'Could not archive again' if trace_artifact
2018-03-27 19:54:05 +05:30
raise ArchiveError, 'Job is not finished yet' unless job.complete?
2018-10-15 14:42:47 +05:30
if job.trace_chunks.any?
Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
archive_stream!(stream)
stream.destroy!
end
elsif current_path
2018-03-27 19:54:05 +05:30
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
def archive_stream!(stream)
clone_file!(stream, JobArtifactUploader.workhorse_upload_path) do |clone_path|
2018-10-15 14:42:47 +05:30
create_build_trace!(job, clone_path)
2018-03-27 19:54:05 +05:30
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
yield(temp_path)
end
end
2018-10-15 14:42:47 +05:30
def create_build_trace!(job, path)
2018-03-27 19:54:05 +05:30
File.open(path) do |stream|
2018-11-18 11:00:15 +05:30
# TODO: Set `file_format: :raw` after we've cleaned up legacy traces migration
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20307
2018-03-27 19:54:05 +05:30
job.create_job_artifacts_trace!(
project: job.project,
file_type: :trace,
file: stream,
file_sha256: Digest::SHA256.file(path).hexdigest)
end
end
2017-08-17 22:00:37 +05:30
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
def current_path
@current_path ||= paths.find do |trace_path|
File.exist?(trace_path)
end
end
def paths
[
default_path,
deprecated_path
].compact
end
def default_directory
File.join(
Settings.gitlab_ci.builds_path,
job.created_at.utc.strftime("%Y_%m"),
job.project_id.to_s
)
end
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-03-17 18:26:18 +05:30
def trace_artifact
job.job_artifacts_trace
end
2018-11-08 19:23:39 +05:30
# For ExclusiveLeaseGuard concern
def lease_key
@lease_key ||= "trace:archive:#{job.id}"
end
# For ExclusiveLeaseGuard concern
def lease_timeout
LEASE_TIMEOUT
end
2017-08-17 22:00:37 +05:30
end
end
end