2022-01-26 12:08:38 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
|
|
module Diff
|
|
|
|
module CustomDiff
|
2022-06-21 17:19:12 +05:30
|
|
|
RENDERED_TIMEOUT_BACKGROUND = 20.seconds
|
|
|
|
RENDERED_TIMEOUT_FOREGROUND = 1.5.seconds
|
|
|
|
BACKGROUND_EXECUTION = 'background'
|
|
|
|
FOREGROUND_EXECUTION = 'foreground'
|
|
|
|
LOG_IPYNBDIFF_GENERATED = 'IPYNB_DIFF_GENERATED'
|
|
|
|
LOG_IPYNBDIFF_TIMEOUT = 'IPYNB_DIFF_TIMEOUT'
|
|
|
|
LOG_IPYNBDIFF_INVALID = 'IPYNB_DIFF_INVALID'
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
class << self
|
|
|
|
def preprocess_before_diff(path, old_blob, new_blob)
|
|
|
|
return unless path.ends_with? '.ipynb'
|
|
|
|
|
2022-06-21 17:19:12 +05:30
|
|
|
Timeout.timeout(timeout_time) do
|
|
|
|
transformed_diff(old_blob&.data, new_blob&.data)&.tap do
|
|
|
|
transformed_for_diff(new_blob, old_blob)
|
|
|
|
log_event(LOG_IPYNBDIFF_GENERATED)
|
|
|
|
end
|
2022-01-26 12:08:38 +05:30
|
|
|
end
|
2022-06-21 17:19:12 +05:30
|
|
|
rescue Timeout::Error => e
|
|
|
|
rendered_timeout.increment(source: execution_source)
|
|
|
|
log_event(LOG_IPYNBDIFF_TIMEOUT, e)
|
2022-05-07 20:08:51 +05:30
|
|
|
rescue IpynbDiff::InvalidNotebookError, IpynbDiff::InvalidTokenError => e
|
2022-06-21 17:19:12 +05:30
|
|
|
log_event(LOG_IPYNBDIFF_INVALID, e)
|
2022-01-26 12:08:38 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def transformed_diff(before, after)
|
|
|
|
transformed_diff = IpynbDiff.diff(before, after,
|
2022-05-07 20:08:51 +05:30
|
|
|
raise_if_invalid_nb: true,
|
|
|
|
diffy_opts: { include_diff_info: true }).to_s(:text)
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
strip_diff_frontmatter(transformed_diff)
|
|
|
|
end
|
|
|
|
|
|
|
|
def transformed_blob_language(blob)
|
|
|
|
'md' if transformed_for_diff?(blob)
|
|
|
|
end
|
|
|
|
|
|
|
|
def transformed_blob_data(blob)
|
|
|
|
if transformed_for_diff?(blob)
|
2022-05-07 20:08:51 +05:30
|
|
|
IpynbDiff.transform(blob.data, raise_errors: true, include_frontmatter: false)
|
2022-01-26 12:08:38 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def strip_diff_frontmatter(diff_content)
|
|
|
|
diff_content.scan(/.*\n/)[2..]&.join('') if diff_content.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def blobs_with_transformed_diffs
|
|
|
|
@blobs_with_transformed_diffs ||= {}
|
|
|
|
end
|
|
|
|
|
|
|
|
def transformed_for_diff?(blob)
|
|
|
|
blobs_with_transformed_diffs[blob]
|
|
|
|
end
|
|
|
|
|
|
|
|
def transformed_for_diff(*blobs)
|
|
|
|
blobs.each do |b|
|
|
|
|
blobs_with_transformed_diffs[b] = true if b
|
|
|
|
end
|
|
|
|
end
|
2022-06-21 17:19:12 +05:30
|
|
|
|
|
|
|
def rendered_timeout
|
|
|
|
@rendered_timeout ||= Gitlab::Metrics.counter(
|
|
|
|
:ipynb_semantic_diff_timeouts_total,
|
|
|
|
'Counts the times notebook rendering timed out'
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def timeout_time
|
|
|
|
Gitlab::Runtime.sidekiq? ? RENDERED_TIMEOUT_BACKGROUND : RENDERED_TIMEOUT_FOREGROUND
|
|
|
|
end
|
|
|
|
|
|
|
|
def execution_source
|
|
|
|
Gitlab::Runtime.sidekiq? ? BACKGROUND_EXECUTION : FOREGROUND_EXECUTION
|
|
|
|
end
|
|
|
|
|
|
|
|
def log_event(message, error = nil)
|
|
|
|
Gitlab::AppLogger.info({ message: message })
|
|
|
|
Gitlab::ErrorTracking.track_exception(error) if error
|
|
|
|
nil
|
|
|
|
end
|
2022-01-26 12:08:38 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|