Welcome to mirror list, hosted at ThFree Co, Russian Federation.

lint_templates_bash.rb « scripts - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: cd36bb629ab196c1e882807765698400cdbf8c8c (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
#!/usr/bin/env ruby
# frozen_string_literal: true

require_relative '../config/environment'
require 'open3'

module LintTemplatesBash
  module_function

  EXCLUDED_RULES = [
    "SC2046", "SC2086", # will be fixed later: https://gitlab.com/gitlab-org/gitlab/-/issues/352973
    "SC1090", "SC1091", # we do not have access to sourced files for analysis.
    "SC2154", # Referencing undefined variables is common and adding per-line exceptions for them is unintuitive for end-users
    "SC2164" # CI/CD automatically fails if attempting to change to a directory which does not exist.
  ].join(",").freeze

  EXCLUDED_TEMPLATES = [
    "dotNET.gitlab-ci.yml" # Powershell
  ].freeze

  def run
    failed_templates = Gitlab::Template::GitlabCiYmlTemplate.all.filter_map do |template|
      next if EXCLUDED_TEMPLATES.include?(template.full_name)

      success = check_template(template)

      template.full_name unless success
    end

    if failed_templates.any?
      puts "The following templates have shellcheck violations:"
      puts failed_templates.join("\n")
      exit 1
    end
  end

  def process_content(content)
    Gitlab::Ci::YamlProcessor.new(content).execute
  end

  def job_script(job)
    parts = [:before_script, :script, :after_script].map do |key|
      job[key]&.join("\n")
    end.compact

    parts.prepend("#!/bin/bash\n").join("\n")
  end

  def shellcheck(script_content)
    combined_streams, status = Open3.capture2e("shellcheck --exclude='#{EXCLUDED_RULES}' -", stdin_data: script_content)

    [combined_streams, status.success?]
  end

  def check_job(job)
    shellcheck(job_script(job))
  end

  def check_template(template)
    parsed = process_content(template.content)

    unless parsed.valid?
      warn "#{template.full_name} is invalid: #{parsed.errors.inspect}"
      return true
    end

    results = parsed.jobs.map do |name, job|
      out, success = check_job(job)

      unless success
        puts "The '#{name}' job in #{template.full_name} has shellcheck failures:"
        puts out
      end

      success
    end

    results.all?
  end
end

LintTemplatesBash.run