debian-mirror-gitlab/lib/gitlab/ci/lint.rb

143 lines
4.4 KiB
Ruby
Raw Normal View History

2020-11-24 15:15:51 +05:30
# frozen_string_literal: true
module Gitlab
module Ci
class Lint
class Result
2022-07-16 23:28:13 +05:30
attr_reader :jobs, :merged_yaml, :errors, :warnings, :includes
2020-11-24 15:15:51 +05:30
2022-07-16 23:28:13 +05:30
def initialize(jobs:, merged_yaml:, errors:, warnings:, includes:)
2020-11-24 15:15:51 +05:30
@jobs = jobs
2021-01-03 14:25:43 +05:30
@merged_yaml = merged_yaml
2020-11-24 15:15:51 +05:30
@errors = errors
@warnings = warnings
2022-07-16 23:28:13 +05:30
@includes = includes
2020-11-24 15:15:51 +05:30
end
def valid?
@errors.empty?
end
2022-07-16 23:28:13 +05:30
def status
valid? ? :valid : :invalid
end
2020-11-24 15:15:51 +05:30
end
2022-04-04 11:22:00 +05:30
LOG_MAX_DURATION_THRESHOLD = 2.seconds
2021-03-08 18:12:59 +05:30
def initialize(project:, current_user:, sha: nil)
2020-11-24 15:15:51 +05:30
@project = project
@current_user = current_user
2021-11-11 11:23:49 +05:30
@sha = sha || project&.repository&.commit&.sha
2020-11-24 15:15:51 +05:30
end
2022-04-04 11:22:00 +05:30
def validate(content, dry_run: false, ref: @project&.default_branch)
2021-01-29 00:20:46 +05:30
if dry_run
2022-04-04 11:22:00 +05:30
simulate_pipeline_creation(content, ref)
2020-11-24 15:15:51 +05:30
else
static_validation(content)
end
end
private
2022-04-04 11:22:00 +05:30
def simulate_pipeline_creation(content, ref)
2020-11-24 15:15:51 +05:30
pipeline = ::Ci::CreatePipelineService
2022-04-04 11:22:00 +05:30
.new(@project, @current_user, ref: ref)
2020-11-24 15:15:51 +05:30
.execute(:push, dry_run: true, content: content)
2021-10-27 15:23:28 +05:30
.payload
2020-11-24 15:15:51 +05:30
Result.new(
jobs: dry_run_convert_to_jobs(pipeline.stages),
2022-07-16 23:28:13 +05:30
merged_yaml: pipeline.config_metadata.try(:[], :merged_yaml),
2020-11-24 15:15:51 +05:30
errors: pipeline.error_messages.map(&:content),
2022-07-16 23:28:13 +05:30
warnings: pipeline.warning_messages(limit: ::Gitlab::Ci::Warnings::MAX_LIMIT).map(&:content),
includes: pipeline.config_metadata.try(:[], :includes)
2020-11-24 15:15:51 +05:30
)
end
def static_validation(content)
2022-04-04 11:22:00 +05:30
logger = build_logger
result = yaml_processor_result(content, logger)
2020-11-24 15:15:51 +05:30
Result.new(
jobs: static_validation_convert_to_jobs(result),
2022-07-16 23:28:13 +05:30
merged_yaml: result.config_metadata[:merged_yaml],
2020-11-24 15:15:51 +05:30
errors: result.errors,
2022-07-16 23:28:13 +05:30
warnings: result.warnings.take(::Gitlab::Ci::Warnings::MAX_LIMIT), # rubocop: disable CodeReuse/ActiveRecord
includes: result.config_metadata[:includes]
2020-11-24 15:15:51 +05:30
)
2022-04-04 11:22:00 +05:30
ensure
logger.commit(pipeline: ::Ci::Pipeline.new, caller: self.class.name)
end
def yaml_processor_result(content, logger)
2023-03-04 22:38:38 +05:30
logger.instrument(:yaml_process, once: true) do
2022-04-04 11:22:00 +05:30
Gitlab::Ci::YamlProcessor.new(content, project: @project,
user: @current_user,
sha: @sha,
logger: logger).execute
end
2020-11-24 15:15:51 +05:30
end
def dry_run_convert_to_jobs(stages)
stages.reduce([]) do |jobs, stage|
jobs + stage.statuses.map do |job|
{
name: job.name,
stage: stage.name,
before_script: job.options[:before_script].to_a,
script: job.options[:script].to_a,
after_script: job.options[:after_script].to_a,
tag_list: (job.tag_list if job.is_a?(::Ci::Build)).to_a,
environment: job.options.dig(:environment, :name),
when: job.when,
allow_failure: job.allow_failure
}
end
end
end
def static_validation_convert_to_jobs(result)
jobs = []
return jobs unless result.valid?
result.stages.each do |stage_name|
result.builds.each do |job|
next unless job[:stage] == stage_name
jobs << {
name: job[:name],
stage: stage_name,
before_script: job.dig(:options, :before_script).to_a,
script: job.dig(:options, :script).to_a,
after_script: job.dig(:options, :after_script).to_a,
tag_list: job[:tag_list].to_a,
only: job[:only],
except: job[:except],
environment: job[:environment],
when: job[:when],
2021-03-08 18:12:59 +05:30
allow_failure: job[:allow_failure],
2023-03-04 22:38:38 +05:30
needs: job[:needs_attributes]
2020-11-24 15:15:51 +05:30
}
end
end
jobs
end
2022-04-04 11:22:00 +05:30
def build_logger
Gitlab::Ci::Pipeline::Logger.new(project: @project) do |l|
l.log_when do |observations|
2023-03-04 22:38:38 +05:30
duration = observations['yaml_process_duration_s']
next false unless duration
2022-04-04 11:22:00 +05:30
2023-03-04 22:38:38 +05:30
duration >= LOG_MAX_DURATION_THRESHOLD
2022-04-04 11:22:00 +05:30
end
end
end
2020-11-24 15:15:51 +05:30
end
end
end