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
|
# frozen_string_literal: true
module QA
module Resource
class Group < GroupBase
attributes :require_two_factor_authentication, :description
attribute :full_path do
determine_full_path
end
attribute :sandbox do
Sandbox.fabricate_via_api! do |sandbox|
sandbox.api_client = api_client
end
end
def initialize
@path = Runtime::Namespace.name
@description = "QA test run at #{Runtime::Namespace.time}"
@require_two_factor_authentication = false
end
def fabricate!
sandbox.visit!
Page::Group::Show.perform do |group_show|
if group_show.has_subgroup?(path)
group_show.click_subgroup(path)
else
group_show.go_to_new_subgroup
Page::Group::New.perform do |group_new|
group_new.click_create_group
group_new.set_path(path)
group_new.set_visibility('Public')
group_new.create
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
end
end
end
def fabricate_via_api!
resource_web_url(api_get)
rescue ResourceNotFoundError
super
Support::Retrier.retry_on_exception(sleep_interval: 5) do
resource = resource_web_url(api_get)
populate(:runners_token)
resource
end
end
def api_get_path
"/groups/#{CGI.escape(determine_full_path)}"
end
def api_post_body
{
parent_id: sandbox.id,
path: path,
name: path,
visibility: 'public',
require_two_factor_authentication: @require_two_factor_authentication
}
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
|