summaryrefslogtreecommitdiff
path: root/rubocop/check_graceful_task.rb
blob: 724f7fa69633cf611b19012cb0c97a24da4aff05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# frozen_string_literal: true

require_relative 'formatter/graceful_formatter'
require_relative '../lib/gitlab/popen'

module RuboCop
  class CheckGracefulTask
    def initialize(output)
      @output = output
    end

    def run(args)
      options = %w[
        --parallel
        --format RuboCop::Formatter::GracefulFormatter
      ]

      available_cops = RuboCop::Cop::Registry.global.to_h

      cop_names, paths = args.partition { available_cops.key?(_1) }

      if cop_names.any?
        list = cop_names.sort.join(',')
        options.concat ['--only', list]
      end

      options.concat(paths)

      puts <<~MSG
        Running RuboCop in graceful mode:
          rubocop #{options.join(' ')}

        This might take a while...
      MSG

      status_orig = RuboCop::CLI.new.run(options)
      status = RuboCop::Formatter::GracefulFormatter.adjusted_exit_status(status_orig)

      # We had to adjust the status which means we have silenced offenses. Notify Slack!
      notify_slack unless status_orig == status

      status
    end

    private

    def env_values(*keys)
      env = ENV.slice(*keys)

      missing_keys = keys - env.keys

      if missing_keys.any?
        puts "Missing ENV keys: #{missing_keys.join(', ')}"
        return
      end

      env.values
    end

    def notify_slack
      job_name, job_url, _ = env_values('CI_JOB_NAME', 'CI_JOB_URL', 'CI_SLACK_WEBHOOK_URL')

      unless job_name
        puts 'Skipping Slack notification.'
        return
      end

      channel = 'f_rubocop'
      message = format(
        ':warning: `%{job_name}` passed :green: but contained <%{job_url}|silenced offenses>. ' \
        'See <%{docs_link}|docs>.',
        docs_link: 'https://docs.gitlab.com/ee/development/contributing/style_guides.html#silenced-offenses',
        job_name: job_name,
        job_url: job_url)

      emoji = 'rubocop'
      user_name = 'GitLab Bot'

      puts "Notifying Slack ##{channel}."

      _output, result = Gitlab::Popen.popen(['scripts/slack', channel, message, emoji, user_name])
      puts "Failed to notify Slack channel ##{channel}." if result.nonzero?
    end

    def puts(...)
      @output.puts(...)
    end
  end
end