config.rb 2.61 KB
Newer Older
1 2
# frozen_string_literal: true

3 4
module Gitlab
  module Ci
5
    #
6 7
    # Base GitLab CI Configuration facade
    #
8
    class Config
9
      ConfigError = Class.new(StandardError)
10 11
      TIMEOUT_SECONDS = 30.seconds
      TIMEOUT_MESSAGE = 'Resolving config took longer than expected'
12

13 14 15 16 17 18
      RESCUE_ERRORS = [
        Gitlab::Config::Loader::FormatError,
        Extendable::ExtensionError,
        External::Processor::IncludeError
      ].freeze

19 20
      attr_reader :root

21 22 23
      def initialize(config, project: nil, sha: nil, user: nil, parent_pipeline: nil)
        @context = build_context(project: project, sha: sha, user: user, parent_pipeline: parent_pipeline)
        @context.set_deadline(TIMEOUT_SECONDS)
24 25

        @config = expand_config(config)
26

27 28
        @root = Entry::Root.new(@config)
        @root.compose!
29

30
      rescue *rescue_errors => e
31
        raise Config::ConfigError, e.message
32 33
      end

34
      def valid?
35
        @root.valid?
36 37 38
      end

      def errors
39
        @root.errors
40 41
      end

42 43 44
      def to_hash
        @config
      end
45 46 47 48 49

      ##
      # Temporary method that should be removed after refactoring
      #
      def variables
50
        root.variables_value
51 52 53
      end

      def stages
54
        root.stages_value
55 56 57
      end

      def jobs
58
        root.jobs_value
59
      end
60

61 62
      private

63 64 65 66
      def expand_config(config)
        build_config(config)

      rescue Gitlab::Config::Loader::Yaml::DataTooLargeError => e
67
        track_and_raise_for_dev_exception(e)
68 69 70
        raise Config::ConfigError, e.message

      rescue Gitlab::Ci::Config::External::Context::TimeoutError => e
71
        track_and_raise_for_dev_exception(e)
72 73 74 75
        raise Config::ConfigError, TIMEOUT_MESSAGE
      end

      def build_config(config)
76
        initial_config = Gitlab::Config::Loader::Yaml.new(config).load!
77
        initial_config = Config::External::Processor.new(initial_config, @context).perform
78
        initial_config = Config::Extendable.new(initial_config).to_hash
79
        initial_config = Config::EdgeStagesInjector.new(initial_config).to_hash
80 81

        initial_config
82
      end
83

84
      def build_context(project:, sha:, user:, parent_pipeline:)
85
        Config::External::Context.new(
86
          project: project,
87
          sha: sha || project&.repository&.root_ref_sha,
88 89
          user: user,
          parent_pipeline: parent_pipeline)
90 91
      end

92
      def track_and_raise_for_dev_exception(error)
93
        Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, @context.sentry_payload)
94
      end
95 96 97 98 99

      # Overriden in EE
      def rescue_errors
        RESCUE_ERRORS
      end
100 101 102
    end
  end
end
103

104
Gitlab::Ci::Config.prepend_if_ee('EE::Gitlab::Ci::ConfigEE')