diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 20:02:30 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 20:02:30 +0000 |
commit | 41fe97390ceddf945f3d967b8fdb3de4c66b7dea (patch) | |
tree | 9c8d89a8624828992f06d892cd2f43818ff5dcc8 /qa/qa/resource | |
parent | 0804d2dc31052fb45a1efecedc8e06ce9bc32862 (diff) | |
download | gitlab-ce-41fe97390ceddf945f3d967b8fdb3de4c66b7dea.tar.gz |
Add latest changes from gitlab-org/gitlab@14-9-stable-eev14.9.0-rc42
Diffstat (limited to 'qa/qa/resource')
-rw-r--r-- | qa/qa/resource/api_fabricator.rb | 19 | ||||
-rw-r--r-- | qa/qa/resource/deploy_key.rb | 42 | ||||
-rw-r--r-- | qa/qa/resource/fork.rb | 2 | ||||
-rw-r--r-- | qa/qa/resource/group.rb | 9 | ||||
-rw-r--r-- | qa/qa/resource/group_base.rb | 20 | ||||
-rw-r--r-- | qa/qa/resource/kubernetes_cluster/project_cluster.rb | 3 | ||||
-rw-r--r-- | qa/qa/resource/project.rb | 36 | ||||
-rw-r--r-- | qa/qa/resource/protected_branch.rb | 10 | ||||
-rw-r--r-- | qa/qa/resource/reusable_collection.rb | 4 | ||||
-rw-r--r-- | qa/qa/resource/reusable_group.rb | 2 | ||||
-rw-r--r-- | qa/qa/resource/reusable_project.rb | 2 | ||||
-rw-r--r-- | qa/qa/resource/runner.rb | 5 |
12 files changed, 111 insertions, 43 deletions
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb index 1958884916c..79cb1ebebc9 100644 --- a/qa/qa/resource/api_fabricator.rb +++ b/qa/qa/resource/api_fabricator.rb @@ -54,7 +54,7 @@ module QA body) unless response.code == HTTP_STATUS_OK - raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`." + raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" end process_api_response(parse_body(response)) @@ -91,9 +91,9 @@ module QA response = get(request.url) if response.code == HTTP_STATUS_SERVER_ERROR - raise InternalServerError, "Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`." + raise InternalServerError, "Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" elsif response.code != HTTP_STATUS_OK - raise ResourceNotFoundError, "Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`." + raise ResourceNotFoundError, "Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" end @api_fabrication_http_method = :get # rubocop:disable Gitlab/ModuleWithInstanceVariables @@ -114,6 +114,7 @@ module QA unless graphql_response.code == HTTP_STATUS_OK && (body[:errors].nil? || body[:errors].empty?) raise(ResourceFabricationFailedError, <<~MSG) Fabrication of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`. + #{QA::Support::Loglinking.failure_metadata(graphql_response.headers[:x_request_id])} MSG end @@ -126,7 +127,7 @@ module QA unless response.code == HTTP_STATUS_CREATED raise( ResourceFabricationFailedError, - "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`." + "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" ) end @@ -145,7 +146,7 @@ module QA response = delete(request.url) unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED].include? response.code - raise ResourceNotDeletedError, "Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`." + raise ResourceNotDeletedError, "Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" end response @@ -165,6 +166,14 @@ module QA def transform_api_resource(api_resource) api_resource end + + # Get api request url + # + # @param [String] path + # @return [String] + def request_url(path, **opts) + Runtime::API::Request.new(api_client, path, **opts).url + end end end end diff --git a/qa/qa/resource/deploy_key.rb b/qa/qa/resource/deploy_key.rb index 26355729dab..c06671be77d 100644 --- a/qa/qa/resource/deploy_key.rb +++ b/qa/qa/resource/deploy_key.rb @@ -5,6 +5,8 @@ module QA class DeployKey < Base attr_accessor :title, :key + attribute :id + attribute :md5_fingerprint do Page::Project::Settings::Repository.perform do |setting| setting.expand_deploy_keys do |key| @@ -34,6 +36,46 @@ module QA end end end + + def fabricate_via_api! + resource_web_url(api_get) + rescue ResourceNotFoundError + super + end + + def resource_web_url(resource) + super + rescue ResourceURLMissingError + # this particular resource does not expose a web_url property + end + + def api_get_path + "/projects/#{project.id}/deploy_keys/#{find_id}" + end + + def api_post_path + "/projects/#{project.id}/deploy_keys" + end + + def api_post_body + { + key: key, + title: title + } + end + + private + + def find_id + id + rescue NoValueError + found_key = auto_paginated_response(request_url("/projects/#{project.id}/deploy_keys", per_page: '100')) + .find { |keys| keys[:key].strip == @key.strip } + + return found_key.fetch(:id) if found_key + + raise ResourceNotFoundError + end end end end diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb index d60b90b534f..0e6dd626312 100644 --- a/qa/qa/resource/fork.rb +++ b/qa/qa/resource/fork.rb @@ -95,7 +95,7 @@ module QA def wait_until_forked Runtime::Logger.debug("Waiting for the fork process to complete...") forked = wait_until do - project.import_status == "finished" + project.reload!.import_status == "finished" end raise "Timed out while waiting for the fork process to complete." unless forked diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb index dee63f9699c..c3da9d47de5 100644 --- a/qa/qa/resource/group.rb +++ b/qa/qa/resource/group.rb @@ -10,7 +10,11 @@ module QA end attribute :name do - @name || path + @name || @path || Runtime::Namespace.name + end + + attribute :path do + @path || @name || Runtime::Namespace.name end attribute :sandbox do @@ -20,7 +24,6 @@ module QA end def initialize - @path = Runtime::Namespace.name @description = "QA test run at #{Runtime::Namespace.time}" @require_two_factor_authentication = false end @@ -64,7 +67,7 @@ module QA { parent_id: sandbox.id, path: path, - name: name || path, + name: name, visibility: 'public', require_two_factor_authentication: @require_two_factor_authentication, avatar: avatar diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb index 05b41a4b4f6..889197a0373 100644 --- a/qa/qa/resource/group_base.rb +++ b/qa/qa/resource/group_base.rb @@ -64,6 +64,10 @@ module QA end end + def marked_for_deletion? + reload!.api_response[:marked_for_deletion_on].present? + end + # Get group badges # # @return [Array<QA::Resource::GroupBadge>] @@ -80,22 +84,6 @@ module QA end end - # Get group members - # - # @return [Array<QA::Resource::User>] - def members - parse_body(api_get_from("#{api_get_path}/members")).map do |member| - User.init do |resource| - resource.api_client = api_client - resource.id = member[:id] - resource.name = member[:name] - resource.username = member[:username] - resource.email = member[:email] - resource.access_level = member[:access_level] - end - end - end - # API get path # # @return [String] diff --git a/qa/qa/resource/kubernetes_cluster/project_cluster.rb b/qa/qa/resource/kubernetes_cluster/project_cluster.rb index 0a63ff47694..0443b26064e 100644 --- a/qa/qa/resource/kubernetes_cluster/project_cluster.rb +++ b/qa/qa/resource/kubernetes_cluster/project_cluster.rb @@ -26,9 +26,6 @@ module QA Page::Project::Infrastructure::Kubernetes::Index.perform( &:connect_existing_cluster) - Page::Project::Infrastructure::Kubernetes::Add.perform( - &:add_existing_cluster) - Page::Project::Infrastructure::Kubernetes::AddExisting.perform do |cluster_page| cluster_page.set_cluster_name(@cluster.cluster_name) cluster_page.set_api_url(@cluster.api_url) diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index c5b72eebe03..740a8920cf2 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -262,7 +262,7 @@ module QA reload!.api_response[:default_branch] || Runtime::Env.default_branch end - def import_status + def project_import_status response = get(request_url("/projects/#{id}/import")) unless response.code == HTTP_STATUS_OK @@ -276,7 +276,7 @@ module QA Runtime::Logger.error("Failed relations: #{result[:failed_relations]}") end - result[:import_status] + result end def commits(auto_paginate: false, attempts: 0) @@ -373,6 +373,30 @@ module QA api_post_to(api_wikis_path, title: title, content: content) end + # Uses the API to wait until a pull mirroring update is successful (pull mirroring is treated as an import) + def wait_for_pull_mirroring + mirror_succeeded = Support::Retrier.retry_until(max_duration: 180, raise_on_failure: false, sleep_interval: 1) do + reload! + api_resource[:import_status] == "finished" + end + + unless mirror_succeeded + raise "Mirroring failed with error: #{api_resource[:import_error]}" + end + end + + def remove_via_api! + super + + Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1, message: "Waiting for #{self.class.name} to be removed") do + !exists? + rescue InternalServerError + # Retry on transient errors that are likely to be due to race conditions between concurrent delete operations + # when parts of a resource are stored in multiple tables + false + end + end + protected # Return subset of fields for comparing projects @@ -407,14 +431,6 @@ module QA Git::Location.new(api_resource[:http_url_to_repo]) api_resource end - - # Get api request url - # - # @param [String] path - # @return [String] - def request_url(path, **opts) - Runtime::API::Request.new(api_client, path, **opts).url - end end end end diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb index 062d4e9f3d8..55ad6edb3c1 100644 --- a/qa/qa/resource/protected_branch.rb +++ b/qa/qa/resource/protected_branch.rb @@ -72,6 +72,16 @@ module QA self.remove_via_api!(&block) end + # Remove the branch protection after confirming that it exists + def remove_via_api! + Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1, message: "Waiting for branch #{branch_name} to be protected") do + # We confirm it exists before removal because there's no creation event when the default branch is automatically protected by GitLab itself, and there's a slight delay between creating the repo and protecting the default branch + exists? + end + + super + end + def api_get_path "/projects/#{project.id}/protected_branches/#{branch_name}" end diff --git a/qa/qa/resource/reusable_collection.rb b/qa/qa/resource/reusable_collection.rb index 1168b0091fc..99a55800d1c 100644 --- a/qa/qa/resource/reusable_collection.rb +++ b/qa/qa/resource/reusable_collection.rb @@ -35,6 +35,10 @@ module QA instance.each_resource do |reuse_as, resource| next QA::Runtime::Logger.debug("#{resource.class.name} reused as :#{reuse_as} has already been removed.") unless resource.exists? + if resource.respond_to?(:marked_for_deletion?) && resource.marked_for_deletion? + next QA::Runtime::Logger.debug("#{resource.class.name} reused as :#{reuse_as} is already scheduled to be removed.") + end + resource.method(:remove_via_api!).super_method.call end end diff --git a/qa/qa/resource/reusable_group.rb b/qa/qa/resource/reusable_group.rb index b75cb0517bf..05ff38249f6 100644 --- a/qa/qa/resource/reusable_group.rb +++ b/qa/qa/resource/reusable_group.rb @@ -8,7 +8,7 @@ module QA def initialize super - @name = @path = 'reusable_group' + @name = @path = QA::Runtime::Env.reusable_group_path @description = "QA reusable group" @reuse_as = :default_group end diff --git a/qa/qa/resource/reusable_project.rb b/qa/qa/resource/reusable_project.rb index b9fca314122..8a12c25b6f0 100644 --- a/qa/qa/resource/reusable_project.rb +++ b/qa/qa/resource/reusable_project.rb @@ -15,7 +15,7 @@ module QA super @add_name_uuid = false - @name = @path = 'reusable_project' + @name = @path = QA::Runtime::Env.reusable_project_path @reuse_as = :default_project @initialize_with_readme = true end diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb index e69702a8ffa..9c5c9992442 100644 --- a/qa/qa/resource/runner.rb +++ b/qa/qa/resource/runner.rb @@ -47,9 +47,8 @@ module QA def remove_via_api! runners = project.runners(tag_list: @tags) - unless runners && !runners.empty? - raise "Project #{project.path_with_namespace} has no runners#{" with tags #{@tags}." if @tags&.any?}" - end + + return if runners.blank? this_runner = runners.find { |runner| runner[:description] == name } unless this_runner |