71 lines
1.9 KiB
Ruby
71 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Ci
|
|
class ParseDotenvArtifactService < ::BaseService
|
|
include ::Gitlab::Utils::StrongMemoize
|
|
|
|
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|
|
|
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)
|
|
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
|