Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-28 18:09:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-28 18:09:17 +0300
commit1bb7f81e238569fd0fe2b0c4385f1015407a2d59 (patch)
tree768c7d44fa3ed641a7e26fdf9db61422902e8294 /qa
parenteb3a23aaaa99ef8ae08c7b440fad676e3c71a1af (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'qa')
-rw-r--r--qa/Gemfile6
-rw-r--r--qa/Gemfile.lock84
-rw-r--r--qa/lib/gitlab/page/group/settings/usage_quotas.rb2
-rw-r--r--qa/qa/resource/issue.rb44
-rw-r--r--qa/qa/resource/merge_request.rb42
-rw-r--r--qa/qa/resource/project.rb7
-rw-r--r--qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb206
-rw-r--r--qa/qa/specs/features/sanity/framework_spec.rb2
8 files changed, 292 insertions, 101 deletions
diff --git a/qa/Gemfile b/qa/Gemfile
index cf939f8e301..53d05b1ce89 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -22,13 +22,15 @@ gem 'timecop', '~> 0.9.1'
gem 'parallel', '~> 1.19'
gem 'rainbow', '~> 3.0.0'
gem 'rspec-parameterized', '~> 0.4.2'
-gem 'octokit', '~> 4.21'
+gem 'octokit', '~> 5.6.1'
+gem "faraday-retry", "~> 2.0"
gem 'webdrivers', '~> 5.0'
gem 'zeitwerk', '~> 2.4'
gem 'influxdb-client', '~> 1.17'
gem 'terminal-table', '~> 3.0.0', require: false
gem 'slack-notifier', '~> 2.4', require: false
-gem 'fog-google', '~> 1.17', require: false
+gem 'fog-google', '~> 1.19', require: false
+gem 'fog-core', '2.1.0', require: false # fog-google generates a ton of warnings with latest core
gem "warning", "~> 1.3"
gem 'confiner', '~> 0.3'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index dd14b675769..0773aae706a 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -67,26 +67,15 @@ GEM
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
equalizer (0.0.11)
- excon (0.88.0)
+ excon (0.92.4)
faker (2.19.0)
i18n (>= 1.6, < 2)
- faraday (1.5.1)
- faraday-em_http (~> 1.0)
- faraday-em_synchrony (~> 1.0)
- faraday-excon (~> 1.1)
- faraday-httpclient (~> 1.0.1)
- faraday-net_http (~> 1.0)
- faraday-net_http_persistent (~> 1.1)
- faraday-patron (~> 1.0)
- multipart-post (>= 1.2, < 3)
+ faraday (2.5.2)
+ faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
- faraday-em_http (1.0.0)
- faraday-em_synchrony (1.0.0)
- faraday-excon (1.1.0)
- faraday-httpclient (1.0.1)
- faraday-net_http (1.0.1)
- faraday-net_http_persistent (1.2.0)
- faraday-patron (1.0.0)
+ faraday-net_http (3.0.0)
+ faraday-retry (2.0.0)
+ faraday (~> 2.0)
ffi (1.15.5)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
@@ -96,8 +85,8 @@ GEM
excon (~> 0.58)
formatador (~> 0.2)
mime-types
- fog-google (1.17.0)
- fog-core (<= 2.1.0)
+ fog-google (1.19.0)
+ fog-core (< 2.3)
fog-json (~> 1.2)
fog-xml (~> 0.1.0)
google-apis-compute_v1 (~> 0.14)
@@ -118,7 +107,7 @@ GEM
gitlab (4.18.0)
httparty (~> 0.18)
terminal-table (>= 1.5.1)
- gitlab-qa (8.4.2)
+ gitlab-qa (8.5.0)
activesupport (~> 6.1)
gitlab (~> 4.18.0)
http (~> 5.0)
@@ -126,9 +115,9 @@ GEM
rainbow (~> 3.0.0)
table_print (= 1.5.7)
zeitwerk (~> 2.4)
- google-apis-compute_v1 (0.21.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-core (0.4.1)
+ google-apis-compute_v1 (0.51.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-core (0.9.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@@ -137,22 +126,22 @@ GEM
retriable (>= 2.0, < 4.a)
rexml
webrick
- google-apis-dns_v1 (0.16.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-iamcredentials_v1 (0.8.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-monitoring_v3 (0.18.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-pubsub_v1 (0.10.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-sqladmin_v1beta4 (0.21.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-storage_v1 (0.9.0)
- google-apis-core (>= 0.4, < 2.a)
+ google-apis-dns_v1 (0.27.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-iamcredentials_v1 (0.14.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-monitoring_v3 (0.33.0)
+ google-apis-core (>= 0.7, < 2.a)
+ google-apis-pubsub_v1 (0.28.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-sqladmin_v1beta4 (0.36.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-storage_v1 (0.18.0)
+ google-apis-core (>= 0.7, < 2.a)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
- googleauth (1.1.0)
- faraday (>= 0.17.3, < 2.0)
+ googleauth (1.2.0)
+ faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
@@ -175,7 +164,7 @@ GEM
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
influxdb-client (1.17.0)
- jwt (2.3.0)
+ jwt (2.5.0)
knapsack (4.0.0)
rake
launchy (2.4.3)
@@ -197,12 +186,11 @@ GEM
minitest (5.16.3)
multi_json (1.15.0)
multi_xml (0.6.0)
- multipart-post (2.1.1)
netrc (0.11.0)
nokogiri (1.13.8)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
- octokit (4.25.1)
+ octokit (5.6.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
oj (3.13.11)
@@ -231,7 +219,7 @@ GEM
rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
- representable (3.1.1)
+ representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
@@ -269,7 +257,7 @@ GEM
rspec-core (>= 2, < 4, != 2.12.0)
ruby-debug-ide (0.7.2)
rake (>= 0.8.1)
- ruby2_keywords (0.0.4)
+ ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sawyer (0.9.2)
addressable (>= 2.3.5)
@@ -278,9 +266,9 @@ GEM
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
- signet (0.16.0)
+ signet (0.17.0)
addressable (~> 2.8)
- faraday (>= 0.17.3, < 2.0)
+ faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
slack-notifier (2.4.0)
@@ -297,7 +285,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
- unicode-display_width (2.2.0)
+ unicode-display_width (2.3.0)
unparser (0.4.7)
abstract_type (~> 0.0.7)
adamantium (~> 0.2.0)
@@ -335,12 +323,14 @@ DEPENDENCIES
confiner (~> 0.3)
deprecation_toolkit (~> 1.5.1)
faker (~> 2.19, >= 2.19.0)
- fog-google (~> 1.17)
+ faraday-retry (~> 2.0)
+ fog-core (= 2.1.0)
+ fog-google (~> 1.19)
gitlab-qa (~> 8)
influxdb-client (~> 1.17)
knapsack (~> 4.0)
nokogiri (~> 1.12)
- octokit (~> 4.21)
+ octokit (~> 5.6.1)
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
diff --git a/qa/lib/gitlab/page/group/settings/usage_quotas.rb b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
index 2b491188595..9f34f48fee0 100644
--- a/qa/lib/gitlab/page/group/settings/usage_quotas.rb
+++ b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
@@ -9,7 +9,7 @@ module Gitlab
link :pipelines_tab
link :storage_tab
link :buy_ci_minutes
- link :buy_storage
+ link :purchase_more_storage
div :plan_ci_minutes
div :additional_ci_minutes
span :purchased_usage_total
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index 1e38de97c1e..40e2e819c99 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -104,6 +104,33 @@ module QA
api_post_to(api_comments_path, body: body, confidential: confidential)
end
+ # Issue label events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def label_events(auto_paginate: false, attempts: 0)
+ events("label", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Issue state events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def state_events(auto_paginate: false, attempts: 0)
+ events("state", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Issue milestone events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def milestone_events(auto_paginate: false, attempts: 0)
+ events("milestone", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
protected
# Return subset of fields for comparing issues
@@ -134,6 +161,23 @@ module QA
:created_at
)
end
+
+ private
+
+ # Issue events
+ #
+ # @param [String] name event name
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def events(name, auto_paginate:, attempts:)
+ return parse_body(api_get_from("#{api_get_path}/resource_#{name}_events")) unless auto_paginate
+
+ auto_paginated_response(
+ Runtime::API::Request.new(api_client, "#{api_get_path}/resource_#{name}_events", per_page: '100').url,
+ attempts: attempts
+ )
+ end
end
end
end
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index 0a92553690f..e4314c4dae7 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -186,6 +186,33 @@ module QA
api_post_to(api_comments_path, body: body)
end
+ # Merge request label events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def label_events(auto_paginate: false, attempts: 0)
+ events("label", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Merge request state events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def state_events(auto_paginate: false, attempts: 0)
+ events("state", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Merge request milestone events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def milestone_events(auto_paginate: false, attempts: 0)
+ events("milestone", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
# Return subset of fields for comparing merge requests
#
# @return [Hash]
@@ -239,6 +266,21 @@ module QA
def create_target?
!(project.initialize_with_readme && target_branch == project.default_branch) && target_new_branch
end
+
+ # Merge request events
+ #
+ # @param [String] name event name
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def events(name, auto_paginate:, attempts:)
+ return parse_body(api_get_from("#{api_get_path}/resource_#{name}_events")) unless auto_paginate
+
+ auto_paginated_response(
+ Runtime::API::Request.new(api_client, "#{api_get_path}/resource_#{name}_events", per_page: '100').url,
+ attempts: attempts
+ )
+ end
end
end
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 13c6f285259..b188e432679 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -324,8 +324,11 @@ module QA
result = parse_body(response)
if result[:import_status] == "failed"
- Runtime::Logger.error("Import failed: #{result[:import_error]}")
- Runtime::Logger.error("Failed relations: #{result[:failed_relations]}")
+ Runtime::Logger.error(<<~ERR)
+ Import of project '#{full_path}' failed!
+ error: '#{result[:import_error]}'
+ failed relations: '#{result[:failed_relations]}'
+ ERR
end
result
diff --git a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
index e6b60a5b090..58820a7e477 100644
--- a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
@@ -1,21 +1,76 @@
# frozen_string_literal: true
+require "etc"
+
# Lifesize project import test executed from https://gitlab.com/gitlab-org/manage/import/import-metrics
# rubocop:disable Rails/Pluck
module QA
RSpec.describe 'Manage', :github, requires_admin: 'creates users', only: { job: 'large-github-import' } do
- describe 'Project import' do
+ describe 'Project import' do # rubocop:disable RSpec/MultipleMemoizedHelpers
+ let(:github_repo) { ENV['QA_LARGE_IMPORT_REPO'] || 'rspec/rspec-core' }
+ let(:import_max_duration) { ENV['QA_LARGE_IMPORT_DURATION']&.to_i || 7200 }
let(:logger) { Runtime::Logger.logger }
let(:differ) { RSpec::Support::Differ.new(color: true) }
let(:gitlab_address) { QA::Runtime::Scenario.gitlab_address }
let(:dummy_url) { "https://example.com" }
+ let(:api_request_params) { { auto_paginate: true, attempts: 2 } }
let(:created_by_pattern) { /\*Created by: \S+\*\n\n/ }
let(:suggestion_pattern) { /suggestion:-\d+\+\d+/ }
let(:gh_link_pattern) { %r{https://github.com/#{github_repo}/(issues|pull)} }
let(:gl_link_pattern) { %r{#{gitlab_address}/#{imported_project.path_with_namespace}/-/(issues|merge_requests)} }
- let(:event_pattern) { %r{(un)?assigned( to)? @\S+|mentioned in (issue|merge request) [!#]\d+|changed title from \*\*.*\*\* to \*\*.*\*\*} } # rubocop:disable Layout/LineLength
+ # rubocop:disable Lint/MixedRegexpCaptureTypes
+ let(:event_pattern) do
+ Regexp.union(
+ [
+ /(?<event>(un)?assigned)( to)? @\S+/,
+ /(?<event>mentioned) in (issue|merge request) [!#]\d+/,
+ /(?<event>changed title) from \*\*.*\*\* to \*\*.*\*\*/,
+ /(?<event>requested review) from @\w+/,
+ /\*(?<event>Merged) by:/,
+ /\*\*(Review):\*\*/
+ ]
+ )
+ end
+ # rubocop:enable Lint/MixedRegexpCaptureTypes
+
+ # mapping from gitlab to github names
+ let(:event_mapping) do
+ {
+ "label_add" => "labeled",
+ "label_remove" => "unlabeled",
+ "milestone_add" => "milestoned",
+ "milestone_remove" => "demilestoned",
+ "assigned" => "assigned",
+ "unassigned" => "unassigned",
+ "changed title" => "renamed",
+ "requested review" => "review_requested",
+ "Merged" => "merged"
+ }
+ end
+
+ # github events that are not migrated or are not correctly mapable in gitlab
+ let(:unsupported_events) do
+ [
+ "head_ref_deleted",
+ "head_ref_force_pushed",
+ "head_ref_restored",
+ "auto_squash_enabled",
+ "auto_merge_disabled",
+ "comment_deleted",
+ "convert_to_draft",
+ "ready_for_review",
+ "subscribed",
+ "unsubscribed",
+ "transferred",
+ # mentions are supported but they can be reported differently on gitlab's side
+ # for example mention of issue creation in pr will be reported in the issue on gitlab side
+ # or referenced in github will still create a 'mentioned in' comment in gitlab
+ "referenced",
+ "mentioned"
+ ]
+ end
let(:api_client) { Runtime::API::Client.as_admin }
@@ -25,79 +80,105 @@ module QA
end
end
- let(:github_repo) { ENV['QA_LARGE_IMPORT_REPO'] || 'rspec/rspec-core' }
- let(:import_max_duration) { ENV['QA_LARGE_IMPORT_DURATION'] ? ENV['QA_LARGE_IMPORT_DURATION'].to_i : 7200 }
let(:github_client) do
Octokit::Client.new(
access_token: ENV['QA_LARGE_IMPORT_GH_TOKEN'] || Runtime::Env.github_access_token,
- auto_paginate: true
+ auto_paginate: true,
+ middleware: Faraday::RackBuilder.new do |builder|
+ builder.use(Faraday::Retry::Middleware, exceptions: [Octokit::InternalServerError, Octokit::ServerError])
+ end
)
end
let(:gh_repo) { github_client.repository(github_repo) }
let(:gh_branches) do
- logger.debug("= Fetching branches =")
+ logger.info("= Fetching branches =")
github_client.branches(github_repo).map(&:name)
end
let(:gh_commits) do
- logger.debug("= Fetching commits =")
+ logger.info("= Fetching commits =")
github_client.commits(github_repo).map(&:sha)
end
let(:gh_labels) do
- logger.debug("= Fetching labels =")
+ logger.info("= Fetching labels =")
github_client.labels(github_repo).map { |label| { name: label.name, color: "##{label.color}" } }
end
let(:gh_milestones) do
- logger.debug("= Fetching milestones =")
+ logger.info("= Fetching milestones =")
github_client
.list_milestones(github_repo, state: 'all')
.map { |ms| { title: ms.title, description: ms.description } }
end
- let(:gh_all_issues) do
- logger.debug("= Fetching issues and prs =")
- github_client.list_issues(github_repo, state: 'all')
- end
-
let(:gh_prs) do
gh_all_issues.select(&:pull_request).each_with_object({}) do |pr, hash|
- hash[pr.number] = {
+ id = pr.number
+ hash[id] = {
url: pr.html_url,
title: pr.title,
body: pr.body || '',
- comments: [*gh_pr_comments[pr.html_url], *gh_issue_comments[pr.html_url]].compact
+ comments: [*gh_pr_comments[id], *gh_issue_comments[id]].compact,
+ events: gh_pr_events[id].reject { |event| unsupported_events.include?(event) }
}
end
end
let(:gh_issues) do
gh_all_issues.reject(&:pull_request).each_with_object({}) do |issue, hash|
- hash[issue.number] = {
+ id = issue.number
+ hash[id] = {
url: issue.html_url,
title: issue.title,
body: issue.body || '',
- comments: gh_issue_comments[issue.html_url]
+ comments: gh_issue_comments[id],
+ events: gh_issue_events[id].reject { |event| unsupported_events.include?(event) }
}
end
end
+ let(:gh_all_issues) do
+ logger.info("= Fetching issues and prs =")
+ github_client.list_issues(github_repo, state: 'all')
+ end
+
+ let(:gh_all_events) do
+ logger.info("- Fetching issue and pr events -")
+ github_client.repository_issue_events(github_repo).map do |event|
+ { name: event[:event], **(event[:issue] || {}) } # some events don't have issue object at all
+ end
+ end
+
+ let(:gh_issue_events) do
+ gh_all_events.each_with_object(Hash.new { |h, k| h[k] = [] }) do |event, hash|
+ next if event[:pull_request] || !event[:number]
+
+ hash[event[:number]] << event[:name]
+ end
+ end
+
+ let(:gh_pr_events) do
+ gh_all_events.each_with_object(Hash.new { |h, k| h[k] = [] }) do |event, hash|
+ next unless event[:pull_request]
+
+ hash[event[:number]] << event[:name]
+ end
+ end
+
let(:gh_issue_comments) do
- logger.debug("= Fetching issue comments =")
+ logger.info("- Fetching issue comments -")
github_client.issues_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
- # use base html url as key
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body&.gsub(gh_link_pattern, dummy_url)
+ hash[id_from_url(c.html_url)] << c.body&.gsub(gh_link_pattern, dummy_url)
end
end
let(:gh_pr_comments) do
- logger.debug("= Fetching pr comments =")
+ logger.info("- Fetching pr comments -")
github_client.pull_requests_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
- # use base html url as key
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body
+ hash[id_from_url(c.html_url)] << c.body
# some suggestions can contain extra whitespaces which gitlab will remove
&.gsub(/suggestion\s+\r/, "suggestion\r")
&.gsub(gh_link_pattern, dummy_url)
@@ -115,7 +196,6 @@ module QA
end
end
- # rubocop:disable RSpec/InstanceVariable
after do |example|
next unless defined?(@import_time)
@@ -164,7 +244,6 @@ module QA
}
)
end
- # rubocop:enable RSpec/InstanceVariable
it(
'imports large Github repo via api',
@@ -172,17 +251,18 @@ module QA
) do
start = Time.now
- # import the project and log gitlab path
- logger.info("== Importing project '#{github_repo}' in to '#{imported_project.reload!.full_path}' ==")
# fetch all objects right after import has started
fetch_github_objects
+ # import the project and log gitlab path
+ logger.info("== Importing project '#{github_repo}' in to '#{imported_project.reload!.full_path}' ==")
+
import_status = lambda do
imported_project.project_import_status.yield_self do |status|
@stats = status.dig(:stats, :imported)
# fail fast if import explicitly failed
- raise "Import of '#{imported_project.name}' failed!" if status[:import_status] == 'failed'
+ raise "Import of '#{imported_project.full_path}' failed!" if status[:import_status] == 'failed'
status[:import_status]
end
@@ -294,7 +374,7 @@ module QA
actual.each_with_object([]) do |(key, actual_item), missing_comments|
expected_item = expected[key]
title = actual_item[:title]
- msg = "expected #{type} with title '#{title}' to have"
+ msg = "expected #{type} with iid '#{key}' to have"
# Print title in the error message to see which object is missing
#
@@ -320,6 +400,14 @@ module QA
expect(expected_comments.length).to eq(actual_comments.length), comment_count_msg
expect(expected_comments).to match_array(actual_comments)
+ expected_events = expected_item[:events]
+ actual_events = actual_item[:events]
+ event_count_msg = <<~MSG
+ #{msg} same amount of events. Gitlab: #{expected_events.length}, Github: #{actual_events.length}
+ MSG
+ expect(expected_events.length).to eq(actual_events.length), event_count_msg
+ expect(expected_events).to match_array(actual_events)
+
# Save missing comments
#
comment_diff = actual_comments - expected_comments
@@ -380,26 +468,27 @@ module QA
def mrs
@mrs ||= begin
logger.debug("= Fetching merge requests =")
- imported_mrs = imported_project.merge_requests(auto_paginate: true, attempts: 2)
+ imported_mrs = imported_project.merge_requests(**api_request_params)
logger.debug("= Fetching merge request comments =")
- Parallel.map(imported_mrs, in_threads: 4) do |mr|
+ Parallel.map(imported_mrs, in_threads: Etc.nprocessors) do |mr|
resource = Resource::MergeRequest.init do |resource|
resource.project = imported_project
resource.iid = mr[:iid]
resource.api_client = api_client
end
- logger.debug("Fetching comments for mr '#{mr[:title]}'")
- comments = resource
- .comments(auto_paginate: true, attempts: 2)
- .reject { |c| c[:system] || c[:body].match?(/^(\*\*Review:\*\*)|(\*Merged by:).*/) }
+ logger.debug("Fetching events and comments for mr '!#{mr[:iid]}'")
+ comments = resource.comments(**api_request_params)
+ label_events = resource.label_events(**api_request_params)
+ state_events = resource.state_events(**api_request_params)
+ milestone_events = resource.milestone_events(**api_request_params)
[mr[:iid], {
url: mr[:web_url],
title: mr[:title],
body: sanitize_description(mr[:description]) || '',
- events: events(comments),
+ events: events(comments, label_events, state_events, milestone_events),
comments: non_event_comments(comments)
}]
end.to_h
@@ -412,48 +501,59 @@ module QA
def gl_issues
@gl_issues ||= begin
logger.debug("= Fetching issues =")
- imported_issues = imported_project.issues(auto_paginate: true, attempts: 2)
+ imported_issues = imported_project.issues(**api_request_params)
logger.debug("= Fetching issue comments =")
- Parallel.map(imported_issues, in_threads: 4) do |issue|
+ Parallel.map(imported_issues, in_threads: Etc.nprocessors) do |issue|
resource = Resource::Issue.init do |issue_resource|
issue_resource.project = imported_project
issue_resource.iid = issue[:iid]
issue_resource.api_client = api_client
end
- logger.debug("Fetching comments for issue '#{issue[:title]}'")
- comments = resource.comments(auto_paginate: true, attempts: 2)
+ logger.debug("Fetching events and comments for issue '!#{issue[:iid]}'")
+ comments = resource.comments(**api_request_params)
+ label_events = resource.label_events(**api_request_params)
+ state_events = resource.state_events(**api_request_params)
+ milestone_events = resource.milestone_events(**api_request_params)
[issue[:iid], {
url: issue[:web_url],
title: issue[:title],
body: sanitize_description(issue[:description]) || '',
- events: events(comments),
+ events: events(comments, label_events, state_events, milestone_events),
comments: non_event_comments(comments)
}]
end.to_h
end
end
- # Fetch comments without events
+ # Filter out event comments
#
# @param [Array] comments
# @return [Array]
def non_event_comments(comments)
comments
- .reject { |c| c[:body].match?(event_pattern) }
+ .reject { |c| c[:system] || c[:body].match?(event_pattern) }
.map { |c| sanitize_comment(c[:body]) }
end
# Events
#
# @param [Array] comments
+ # @param [Array] label_events
+ # @param [Array] state_events
+ # @param [Array] milestone_events
# @return [Array]
- def events(comments)
- comments
- .select { |c| c[:body].match?(event_pattern) }
- .map { |c| c[:body] }
+ def events(comments, label_events, state_events, milestone_events)
+ mapped_label_events = label_events.map { |event| event_mapping["label_#{event[:action]}"] }
+ mapped_milestone_events = milestone_events.map { |event| event_mapping["milestone_#{event[:action]}"] }
+ mapped_state_event = state_events.map { |event| event[:state] }
+ mapped_comment_events = comments.map do |c|
+ event_mapping[c[:body].match(event_pattern)&.named_captures&.fetch("event", nil)]
+ end
+
+ [*mapped_label_events, *mapped_milestone_events, *mapped_state_event, *mapped_comment_events].compact
end
# Normalize comments and make them directly comparable
@@ -489,6 +589,16 @@ module QA
def save_json(name, json)
File.open("tmp/#{name}.json", "w") { |file| file.write(JSON.pretty_generate(json)) }
end
+
+ # Extract id number from web url of issue or pull request
+ #
+ # Some endpoints don't return object id as separate parameter so web url can be used as a workaround
+ #
+ # @param [String] url
+ # @return [Integer]
+ def id_from_url(url)
+ url.match(%r{(?<type>issues|pull)/(?<id>\d+)})&.named_captures&.fetch(:id, nil).to_i
+ end
end
end
end
diff --git a/qa/qa/specs/features/sanity/framework_spec.rb b/qa/qa/specs/features/sanity/framework_spec.rb
index feec56478c0..fa34f525a85 100644
--- a/qa/qa/specs/features/sanity/framework_spec.rb
+++ b/qa/qa/specs/features/sanity/framework_spec.rb
@@ -6,7 +6,7 @@ module QA
it 'succeeds' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- expect(page).to have_text('A complete DevOps platform')
+ expect(page).to have_text('GitLab')
end
end