module Gitlab module Ci class Trace 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 def extract_sections read do |stream| stream.extract_sections end end def set(data) write do |stream| data = job.hide_secrets(data) stream.set(data) end end def append(data, offset) write do |stream| current_length = stream.size return -current_length unless current_length == offset data = job.hide_secrets(data) stream.append(data, offset) stream.size end end def exist? current_path.present? || old_trace.present? end def read stream = Gitlab::Ci::Trace::Stream.new do if current_path File.open(current_path, "rb") elsif old_trace StringIO.new(old_trace) end end yield stream ensure stream&.close end def write stream = Gitlab::Ci::Trace::Stream.new do File.open(ensure_path, "a+b") end yield(stream).tap do job.touch if job.needs_touch? end ensure stream&.close end def erase! paths.each do |trace_path| FileUtils.rm(trace_path, force: true) end job.erase_old_trace! end private 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 end end end