81 lines
2.1 KiB
Ruby
81 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Ci
|
|
class ParseDotenvArtifactService < ::BaseService
|
|
include ::Gitlab::Utils::StrongMemoize
|
|
include ::Gitlab::EncodingHelper
|
|
|
|
SizeLimitError = Class.new(StandardError)
|
|
ParserError = Class.new(StandardError)
|
|
|
|
def execute(artifact)
|
|
validate!(artifact)
|
|
|
|
variables = parse!(artifact)
|
|
Ci::JobVariable.bulk_insert!(variables)
|
|
|
|
success
|
|
rescue SizeLimitError, ParserError, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => error
|
|
Gitlab::ErrorTracking.track_exception(error, job_id: artifact.job_id)
|
|
error(error.message, :bad_request)
|
|
end
|
|
|
|
private
|
|
|
|
def validate!(artifact)
|
|
unless artifact&.dotenv?
|
|
raise ArgumentError, 'Artifact is not dotenv file type'
|
|
end
|
|
|
|
unless artifact.file.size < dotenv_size_limit
|
|
raise SizeLimitError,
|
|
"Dotenv Artifact Too Big. Maximum Allowable Size: #{dotenv_size_limit}"
|
|
end
|
|
end
|
|
|
|
def parse!(artifact)
|
|
variables = {}
|
|
|
|
artifact.each_blob do |blob|
|
|
# Windows powershell may output UTF-16LE files, so convert the whole file
|
|
# to UTF-8 before proceeding.
|
|
blob = strip_bom(encode_utf8_with_replacement_character(blob))
|
|
|
|
blob.each_line do |line|
|
|
key, value = scan_line!(line)
|
|
|
|
variables[key] = Ci::JobVariable.new(
|
|
job_id: artifact.job_id,
|
|
source: :dotenv,
|
|
key: key,
|
|
value: value,
|
|
raw: false
|
|
)
|
|
end
|
|
end
|
|
|
|
if variables.size > dotenv_variable_limit
|
|
raise SizeLimitError,
|
|
"Dotenv files cannot have more than #{dotenv_variable_limit} variables"
|
|
end
|
|
|
|
variables.values
|
|
end
|
|
|
|
def scan_line!(line)
|
|
result = line.scan(/^(.*?)=(.*)$/).last
|
|
|
|
raise ParserError, 'Invalid Format' if result.nil?
|
|
|
|
result.each(&:strip!)
|
|
end
|
|
|
|
def dotenv_variable_limit
|
|
strong_memoize(:dotenv_variable_limit) { project.actual_limits.dotenv_variables }
|
|
end
|
|
|
|
def dotenv_size_limit
|
|
strong_memoize(:dotenv_size_limit) { project.actual_limits.dotenv_size }
|
|
end
|
|
end
|
|
end
|