2017-08-17 22:00:37 +05:30
|
|
|
#!/usr/bin/env ruby
|
2021-03-11 19:13:27 +05:30
|
|
|
# frozen_string_literal: true
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
# We don't have auto-loading here
|
2019-10-12 21:52:04 +05:30
|
|
|
require_relative '../lib/gitlab'
|
2018-03-17 18:26:18 +05:30
|
|
|
require_relative '../lib/gitlab/popen'
|
|
|
|
require_relative '../lib/gitlab/popen/runner'
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
class StaticAnalysis
|
|
|
|
ALLOWED_WARNINGS = [
|
|
|
|
# https://github.com/browserslist/browserslist/blob/d0ec62eb48c41c218478cd3ac28684df051cc865/node.js#L329
|
|
|
|
# warns if caniuse-lite package is older than 6 months. Ignore this
|
|
|
|
# warning message so that GitLab backports don't fail.
|
|
|
|
"Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`"
|
|
|
|
].freeze
|
|
|
|
|
|
|
|
# `gettext:updated_check` and `gitlab:sidekiq:sidekiq_queues_yml:check` will fail on FOSS installations
|
|
|
|
# (e.g. gitlab-org/gitlab-foss) since they test against a single
|
|
|
|
# file that is generated by an EE installation, which can
|
|
|
|
# contain values that a FOSS installation won't find. To work
|
|
|
|
# around this we will only enable this task on EE installations.
|
|
|
|
TASKS_BY_DURATIONS_SECONDS_DESC = {
|
2021-09-04 01:27:46 +05:30
|
|
|
%w[bin/rake lint:haml] => 488,
|
|
|
|
(Gitlab.ee? ? %w[bin/rake gettext:updated_check] : nil) => 410,
|
2020-06-23 00:09:42 +05:30
|
|
|
# Most of the time, RuboCop finishes in 30 seconds, but sometimes it can take around 1200 seconds so we set a
|
|
|
|
# duration of 300 to lower the likelihood that it will run in the same job as another long task...
|
2021-09-30 23:02:18 +05:30
|
|
|
%w[bundle exec rubocop --parallel --except Gitlab/MarkUsedFeatureFlags] => 300,
|
|
|
|
# We need to disable the cache for this cop since it creates files under tmp/feature_flags/*.used,
|
|
|
|
# the cache would prevent these files from being created.
|
|
|
|
%w[bundle exec rubocop --only Gitlab/MarkUsedFeatureFlags --cache false] => 600,
|
2021-09-04 01:27:46 +05:30
|
|
|
%w[yarn run lint:eslint:all] => 264,
|
|
|
|
%w[yarn run lint:prettier] => 134,
|
|
|
|
%w[bin/rake gettext:lint] => 81,
|
2020-06-23 00:09:42 +05:30
|
|
|
%w[bundle exec license_finder] => 49,
|
2021-09-04 01:27:46 +05:30
|
|
|
%w[bin/rake lint:static_verification] => 24,
|
|
|
|
%w[bin/rake gitlab:sidekiq:all_queues_yml:check] => 12,
|
|
|
|
(Gitlab.ee? ? %w[bin/rake gitlab:sidekiq:sidekiq_queues_yml:check] : nil) => 11,
|
2020-06-23 00:09:42 +05:30
|
|
|
%w[bin/rake config_lint] => 11,
|
2021-09-04 01:27:46 +05:30
|
|
|
%w[yarn run internal:stylelint] => 8,
|
|
|
|
%w[scripts/lint-conflicts.sh] => 1,
|
|
|
|
%w[yarn run block-dependencies] => 1,
|
|
|
|
%w[scripts/lint-rugged] => 1,
|
|
|
|
%w[scripts/gemfile_lock_changed.sh] => 1,
|
|
|
|
%w[scripts/frontend/check_no_partial_karma_jest.sh] => 1
|
2020-06-23 00:09:42 +05:30
|
|
|
}.reject { |k| k.nil? }.sort_by { |a| -a[1] }.to_h.keys.freeze
|
|
|
|
|
|
|
|
def run_tasks!
|
|
|
|
tasks = tasks_to_run((ENV['CI_NODE_INDEX'] || 1).to_i, (ENV['CI_NODE_TOTAL'] || 1).to_i)
|
|
|
|
|
|
|
|
static_analysis = Gitlab::Popen::Runner.new
|
|
|
|
|
|
|
|
static_analysis.run(tasks) do |cmd, &run|
|
|
|
|
puts
|
|
|
|
puts "$ #{cmd.join(' ')}"
|
|
|
|
|
|
|
|
result = run.call
|
|
|
|
|
|
|
|
puts "==> Finished in #{result.duration} seconds"
|
|
|
|
puts
|
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
puts
|
2020-06-23 00:09:42 +05:30
|
|
|
puts '==================================================='
|
2018-03-17 18:26:18 +05:30
|
|
|
puts
|
|
|
|
puts
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
if static_analysis.all_success_and_clean?
|
|
|
|
puts 'All static analyses passed successfully.'
|
|
|
|
elsif static_analysis.all_success?
|
|
|
|
puts 'All static analyses passed successfully, but we have warnings:'
|
|
|
|
puts
|
2020-01-12 00:16:45 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
emit_warnings(static_analysis)
|
2020-01-12 00:16:45 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
exit 2 if warning_count(static_analysis).nonzero?
|
2019-12-26 22:10:19 +05:30
|
|
|
else
|
2020-06-23 00:09:42 +05:30
|
|
|
puts 'Some static analyses failed:'
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
emit_warnings(static_analysis)
|
|
|
|
emit_errors(static_analysis)
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def emit_warnings(static_analysis)
|
|
|
|
static_analysis.warned_results.each do |result|
|
|
|
|
puts
|
|
|
|
puts "**** #{result.cmd.join(' ')} had the following warning(s):"
|
|
|
|
puts
|
|
|
|
puts result.stderr
|
|
|
|
puts
|
|
|
|
end
|
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def emit_errors(static_analysis)
|
|
|
|
static_analysis.failed_results.each do |result|
|
|
|
|
puts
|
|
|
|
puts "**** #{result.cmd.join(' ')} failed with the following error(s):"
|
|
|
|
puts
|
|
|
|
puts result.stdout
|
|
|
|
puts result.stderr
|
|
|
|
puts
|
|
|
|
end
|
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def warning_count(static_analysis)
|
|
|
|
static_analysis.warned_results
|
|
|
|
.count { |result| !ALLOWED_WARNINGS.include?(result.stderr.strip) }
|
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def tasks_to_run(node_index, node_total)
|
|
|
|
tasks = []
|
|
|
|
TASKS_BY_DURATIONS_SECONDS_DESC.each_with_index do |task, i|
|
|
|
|
tasks << task if i % node_total == (node_index - 1)
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
tasks
|
|
|
|
end
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
if $0 == __FILE__
|
|
|
|
StaticAnalysis.new.run_tasks!
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|