2020-04-08 14:13:33 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Ci
|
|
|
|
class ParseDotenvArtifactService < ::BaseService
|
2021-12-11 22:18:48 +05:30
|
|
|
include ::Gitlab::Utils::StrongMemoize
|
2023-04-23 21:23:45 +05:30
|
|
|
include ::Gitlab::EncodingHelper
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
SizeLimitError = Class.new(StandardError)
|
|
|
|
ParserError = Class.new(StandardError)
|
|
|
|
|
|
|
|
def execute(artifact)
|
|
|
|
validate!(artifact)
|
|
|
|
|
|
|
|
variables = parse!(artifact)
|
|
|
|
Ci::JobVariable.bulk_insert!(variables)
|
|
|
|
|
|
|
|
success
|
2022-01-26 12:08:38 +05:30
|
|
|
rescue SizeLimitError, ParserError, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => error
|
2020-04-08 14:13:33 +05:30
|
|
|
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
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
unless artifact.file.size < dotenv_size_limit
|
2020-04-08 14:13:33 +05:30
|
|
|
raise SizeLimitError,
|
2021-12-11 22:18:48 +05:30
|
|
|
"Dotenv Artifact Too Big. Maximum Allowable Size: #{dotenv_size_limit}"
|
2020-04-08 14:13:33 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def parse!(artifact)
|
2022-01-26 12:08:38 +05:30
|
|
|
variables = {}
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
artifact.each_blob do |blob|
|
2023-04-23 21:23:45 +05:30
|
|
|
# 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))
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
blob.each_line do |line|
|
|
|
|
key, value = scan_line!(line)
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
variables[key] = Ci::JobVariable.new(job_id: artifact.job_id,
|
2022-11-25 23:54:43 +05:30
|
|
|
source: :dotenv, key: key, value: value, raw: false)
|
2020-04-08 14:13:33 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
if variables.size > dotenv_variable_limit
|
2020-04-08 14:13:33 +05:30
|
|
|
raise SizeLimitError,
|
2021-12-11 22:18:48 +05:30
|
|
|
"Dotenv files cannot have more than #{dotenv_variable_limit} variables"
|
2020-04-08 14:13:33 +05:30
|
|
|
end
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
variables.values
|
2020-04-08 14:13:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def scan_line!(line)
|
2020-11-24 15:15:51 +05:30
|
|
|
result = line.scan(/^(.*?)=(.*)$/).last
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
raise ParserError, 'Invalid Format' if result.nil?
|
|
|
|
|
|
|
|
result.each(&:strip!)
|
|
|
|
end
|
2021-12-11 22:18:48 +05:30
|
|
|
|
|
|
|
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
|
2020-04-08 14:13:33 +05:30
|
|
|
end
|
|
|
|
end
|