summaryrefslogtreecommitdiff
path: root/app/graphql/resolvers/ci/config_resolver.rb
blob: d6e7c206691e3bae54c157743a1465d02f6fa57e (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
# frozen_string_literal: true

module Resolvers
  module Ci
    class ConfigResolver < BaseResolver
      type Types::Ci::Config::ConfigType, null: true

      argument :content, GraphQL::STRING_TYPE,
               required: true,
               description: 'Contents of .gitlab-ci.yml'

      def resolve(content:)
        result = ::Gitlab::Ci::YamlProcessor.new(content).execute

        response = if result.errors.empty?
                     {
                       status: :valid,
                       errors: [],
                       stages: make_stages(result.jobs)
                     }
                   else
                     {
                       status: :invalid,
                       errors: result.errors
                     }
                   end

        response.merge(merged_yaml: result.merged_yaml)
      end

      private

      def make_jobs(config_jobs)
        config_jobs.map do |job_name, job|
          {
            name: job_name,
            stage: job[:stage],
            group_name: CommitStatus.new(name: job_name).group_name,
            needs: job.dig(:needs, :job) || []
          }
        end
      end

      def make_groups(job_data)
        jobs = make_jobs(job_data)

        jobs_by_group = jobs.group_by { |job| job[:group_name] }
        jobs_by_group.map do |name, jobs|
          { jobs: jobs, name: name, stage: jobs.first[:stage], size: jobs.size }
        end
      end

      def make_stages(jobs)
        make_groups(jobs)
          .group_by { |group| group[:stage] }
          .map { |name, groups| { name: name, groups: groups } }
      end
    end
  end
end