File: group_ownership.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (92 lines) | stat: -rwxr-xr-x 3,055 bytes parent folder | download
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
90
91
92
# frozen_string_literal: true

# Helpers related to Stage/Section/Group ownership
module InternalEventsCli
  module Helpers
    module GroupOwnership
      STAGES_YML = 'https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml'

      def prompt_for_group_ownership(message, defaults = {})
        if available_groups.any?
          prompt_for_ownership_from_ssot(message, defaults)
        else
          prompt_for_ownership_manually(message, defaults)
        end
      end

      def find_stage(group)
        available_groups[group]&.fetch(:stage)
      end

      def find_section(group)
        available_groups[group]&.fetch(:section)
      end

      private

      def prompt_for_ownership_from_ssot(prompt, defaults)
        sorted_defaults = defaults.values_at(:section, :stage, :product_group)
        group = sorted_defaults.last
        default = sorted_defaults.compact.join(':') # compact because not all groups have a section

        cli.select(prompt, group_choices, **select_opts, **filter_opts) do |menu|
          if group
            if available_groups[group]
              # We have a complete group selection -> set as default in menu
              menu.default(default)
            else
              cli.error format_error(">>> Failed to find group matching #{group}. Select another.\n")
            end
          elsif default
            # We have a section and/or stage in common
            menu.instance_variable_set(:@filter, default.split(''))
          end
        end
      end

      def prompt_for_ownership_manually(message, defaults)
        prompt_for_text(message, defaults[:product_group])
      end

      # @return Array[<Hash - matches #prompt_for_ownership_manually output format>]
      def group_choices
        available_groups.map do |group, ownership|
          {
            name: ownership.values_at(:section, :stage, :group).compact.join(':'),
            value: group
          }
        end
      end

      # Output looks like:
      #   {
      #     "import_and_integrate" => { stage: "manage", section: "dev", group: "import_and_integrate" },
      #     ...
      #   }
      def available_groups
        # rubocop:disable Gitlab/ModuleWithInstanceVariables -- memoization is acceptable use
        # https://docs.gitlab.com/ee/development/module_with_instance_variables.html#acceptable-use
        return @available_groups if @available_groups

        response = Timeout.timeout(5) { Net::HTTP.get(URI(STAGES_YML)) }
        data = YAML.safe_load(response)

        @available_groups = data['stages'].flat_map do |stage_name, stage_data|
          stage_data['groups'].map do |group_name, _|
            [
              group_name,
              {
                group: group_name,
                stage: stage_name,
                section: stage_data['section']
              }
            ]
          end
        end.to_h
      rescue StandardError
        @available_groups = {}
        # rubocop:enable Gitlab/ModuleWithInstanceVariables
      end
    end
  end
end