summaryrefslogtreecommitdiff
path: root/qa/qa/resource/group.rb
blob: f53bb531d9af2a412c0538c8f32fd63f46683063 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# frozen_string_literal: true

module QA
  module Resource
    class Group < GroupBase
      attributes :require_two_factor_authentication, :description, :path

      attribute :full_path do
        determine_full_path
      end

      attribute :name do
        @name || @path || Runtime::Namespace.name
      end

      attribute :path do
        @path || @name || Runtime::Namespace.name
      end

      attribute :sandbox do
        if Runtime::Env.personal_access_tokens_disabled?
          Resource::Sandbox.fabricate! do |sandbox|
            sandbox.path = Runtime::Namespace.sandbox_name
          end
        else
          Sandbox.fabricate_via_api! do |sandbox|
            sandbox.api_client = api_client
          end
        end
      end

      def initialize
        @description = "QA test run at #{Runtime::Namespace.time}"
        @require_two_factor_authentication = false
        # Add visibility to enable create private group
        @visibility = 'public'
      end

      def fabricate!
        sandbox.visit!

        Page::Group::Show.perform do |group_show|
          unless group_show.has_subgroup?(path)
            group_show.go_to_new_subgroup

            Page::Group::New.perform do |group_new|
              group_new.set_path(path)
              group_new.set_visibility(@visibility)
              group_new.create_subgroup
            end

            # Ensure that the group was actually created
            group_show.wait_until(sleep_interval: 1) do
              group_show.has_text?(path) &&
                group_show.has_new_project_and_new_subgroup_buttons?
            end
            sandbox.visit!
          end

          group_show.click_subgroup(path)
          @id = group_show.group_id
        end
      end

      def fabricate_via_api!
        resource_web_url(api_get)
      rescue ResourceNotFoundError
        super
      end

      def api_get_path
        "/groups/#{CGI.escape(determine_full_path)}"
      end

      # Parameters included in the query URL
      #
      # @return [Hash]
      def query_parameters
        super.merge({ with_projects: false })
      end

      def api_post_body
        {
          parent_id: sandbox.id,
          path: path,
          name: name,
          visibility: @visibility.downcase,
          require_two_factor_authentication: @require_two_factor_authentication,
          avatar: avatar
        }
      end

      def set_require_two_factor_authentication(value:)
        put_body = { require_two_factor_authentication: value }
        response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body
        return if response.code == HTTP_STATUS_OK

        raise(ResourceUpdateFailedError, <<~ERROR.strip)
          Could not update require_two_factor_authentication to #{value}. Request returned (#{response.code}): `#{response}`.
        ERROR
      end

      def change_repository_storage(new_storage)
        post_body = { destination_storage_name: new_storage }
        response = post Runtime::API::Request.new(api_client, "/groups/#{id}/repository_storage_moves").url, post_body

        unless response.code.between?(200, 300)
          raise(
            ResourceUpdateFailedError,
            "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
          )
        end

        wait_until(sleep_interval: 1) do
          Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage)
        end
      rescue Support::Repeater::RepeaterConditionExceededError
        raise(
          Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError,
          'Timed out while waiting for the group repository storage move to finish'
        )
      end

      private

      # Determine the path up to the root group.
      #
      # This is equivalent to the full_path API attribute. We can't use the full_path attribute
      # because it depends on the group being fabricated first, and we use this method to help
      # _check_ if the group exists.
      #
      # @param [QA::Resource::GroupBase] sandbox the immediate parent group of this group
      # @param [String] path the path name of this group (the leaf, not the full path)
      # @return [String]
      def determine_full_path
        determine_parent_group_paths(sandbox, path)
      end

      # Recursively traverse the parents of this group up to the root group.
      #
      # @param [QA::Resource::GroupBase] parent the immediate parent group
      # @param [String] path the path traversed so far
      # @return [String]
      def determine_parent_group_paths(parent, path)
        return "#{parent.path}/#{path}" unless parent.respond_to?(:sandbox)

        determine_parent_group_paths(parent.sandbox, "#{parent.path}/#{path}")
      end
    end
  end
end