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
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/specs/features/api/1_manage')
-rw-r--r--qa/qa/specs/features/api/1_manage/group_access_token_spec.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb (renamed from qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb)26
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb (renamed from qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb)253
-rw-r--r--qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb130
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb8
-rw-r--r--qa/qa/specs/features/api/1_manage/rate_limits_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb10
-rw-r--r--qa/qa/specs/features/api/1_manage/users_spec.rb2
18 files changed, 362 insertions, 99 deletions
diff --git a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
index 7d3916641aa..bf95a215c8e 100644
--- a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
@@ -40,9 +40,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.not_to raise_error
end
diff --git a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
index df34bf32421..c3e41e9298b 100644
--- a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
@@ -3,7 +3,7 @@
module QA
# Spec uses real github.com, which means outage of github.com can actually block deployment
# Keep spec in reliable bucket but don't run in blocking pipelines
- RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin do
+ RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin, product_group: :import do
describe 'Project import', issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/353583' do
let!(:api_client) { Runtime::API::Client.as_admin }
let!(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } }
@@ -20,7 +20,9 @@ module QA
project.group = group
project.github_personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = 'gitlab-qa-github/import-test'
- project.api_client = api_client
+ project.api_client = Runtime::API::Client.new(user: user)
+ project.issue_events_import = true
+ project.full_notes_import = true
end
end
@@ -41,6 +43,7 @@ module QA
aggregate_failures do
verify_status_data
verify_repository_import
+ verify_protected_branches_import
verify_commits_import
verify_labels_import
verify_issues_import
@@ -53,7 +56,7 @@ module QA
def verify_status_data
stats = imported_project.project_import_status.dig(:stats, :imported)
expect(stats).to include(
- # issue: 2,
+ issue: 1,
label: 9,
milestone: 1,
note: 3,
@@ -69,6 +72,21 @@ module QA
expect(imported_project.api_response[:import_error]).to be_nil
end
+ def verify_protected_branches_import
+ branches = imported_project.protected_branches.map do |branch|
+ branch.slice(:name, :allow_force_push, :code_owner_approval_required)
+ end
+ expect(branches.first).to include(
+ {
+ name: 'main'
+ # TODO: Add validation once https://gitlab.com/groups/gitlab-org/-/epics/8585 is closed
+ # At the moment both options are always set to false regardless of state in github
+ # allow_force_push: true,
+ # code_owner_approval_required: true
+ }
+ )
+ end
+
def verify_commits_import
expect(imported_project.commits.length).to eq(2)
end
@@ -122,7 +140,7 @@ module QA
mr.iid = merge_requests.first[:iid]
mr.api_client = api_client
end.reload!
- mr_comments = merge_request.comments.map { |comment| comment[:body] } # rubocop:disable Rails/Pluck
+ mr_comments = merge_request.comments.map { |comment| comment[:body] }
expect(merge_requests.length).to eq(1)
expect(merge_request.api_resource).to include(
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/import_large_github_repo_spec.rb
index e6b60a5b090..5acf15dd2b4 100644
--- a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
@@ -1,21 +1,82 @@
# 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', product_group: :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(:gitlab_address) { QA::Runtime::Scenario.gitlab_address.chomp("/") }
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",
+ "base_ref_force_pushed",
+ "base_ref_changed",
+ "review_request_removed",
+ "review_dismissed",
+ "auto_squash_enabled",
+ "auto_merge_disabled",
+ "comment_deleted",
+ "convert_to_draft",
+ "ready_for_review",
+ "subscribed",
+ "unsubscribed",
+ "transferred",
+ "locked",
+ "unlocked",
+ # 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 +86,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)
@@ -111,11 +198,12 @@ module QA
project.github_personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = github_repo
project.personal_namespace = user.username
- project.api_client = api_client
+ project.api_client = Runtime::API::Client.new(user: user)
+ project.issue_events_import = true
+ project.full_notes_import = true
end
end
- # rubocop:disable RSpec/InstanceVariable
after do |example|
next unless defined?(@import_time)
@@ -138,8 +226,10 @@ module QA
milestones: gh_milestones.length,
mrs: gh_prs.length,
mr_comments: gh_prs.sum { |_k, v| v[:comments].length },
+ mr_events: gh_prs.sum { |_k, v| v[:events].length },
issues: gh_issues.length,
- issue_comments: gh_issues.sum { |_k, v| v[:comments].length }
+ issue_comments: gh_issues.sum { |_k, v| v[:comments].length },
+ issue_events: gh_issues.sum { |_k, v| v[:events].length }
}
},
target: {
@@ -153,8 +243,10 @@ module QA
milestones: gl_milestones.length,
mrs: mrs.length,
mr_comments: mrs.sum { |_k, v| v[:comments].length },
+ mr_events: mrs.sum { |_k, v| v[:events].length },
issues: gl_issues.length,
- issue_comments: gl_issues.sum { |_k, v| v[:comments].length }
+ issue_comments: gl_issues.sum { |_k, v| v[:comments].length },
+ issue_events: gl_issues.sum { |_k, v| v[:events].length }
}
},
not_imported: {
@@ -164,7 +256,6 @@ module QA
}
)
end
- # rubocop:enable RSpec/InstanceVariable
it(
'imports large Github repo via api',
@@ -172,8 +263,9 @@ 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}' ==")
+ # trigger import and log project paths
+ logger.info("== Triggering import of project '#{github_repo}' in to '#{imported_project.reload!.full_path}' ==")
+
# fetch all objects right after import has started
fetch_github_objects
@@ -182,7 +274,7 @@ module QA
@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
@@ -276,25 +368,26 @@ module QA
count_msg = "Expected to contain same amount of #{type}s. Gitlab: #{expected.length}, Github: #{actual.length}"
expect(expected.length).to eq(actual.length), count_msg
- missing_comments = verify_comments(type, actual, expected)
+ missing_objects = (actual.keys - expected.keys).map { |it| actual[it].slice(:title, :url) }
+ missing_content = verify_comments_and_events(type, actual, expected)
{
- "#{type}s": (actual.keys - expected.keys).map { |it| actual[it].slice(:title, :url) },
- "#{type}_comments": missing_comments
- }
+ "#{type}s": missing_objects.empty? ? nil : missing_objects,
+ "#{type}_content": missing_content.empty? ? nil : missing_content
+ }.compact
end
- # Verify imported comments
+ # Verify imported comments and events
#
# @param [String] type verification object, 'mrs' or 'issues'
# @param [Hash] actual
# @param [Hash] expected
# @return [Hash]
- def verify_comments(type, actual, expected)
- actual.each_with_object([]) do |(key, actual_item), missing_comments|
+ def verify_comments_and_events(type, actual, expected)
+ actual.each_with_object([]) do |(key, actual_item), missing_content|
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,17 +413,27 @@ module QA
expect(expected_comments.length).to eq(actual_comments.length), comment_count_msg
expect(expected_comments).to match_array(actual_comments)
- # Save missing 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 and events
#
comment_diff = actual_comments - expected_comments
- next if comment_diff.empty?
+ event_diff = actual_events - expected_events
+ next if comment_diff.empty? && event_diff.empty?
- missing_comments << {
+ missing_content << {
title: title,
github_url: actual_item[:url],
gitlab_url: expected_item[:url],
- missing_comments: comment_diff
- }
+ missing_comments: comment_diff.empty? ? nil : comment_diff,
+ missing_events: event_diff.empty? ? nil : event_diff
+ }.compact
end
end
@@ -380,26 +483,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 +516,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 +604,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/api/1_manage/integrations/webhook_events_spec.rb b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
new file mode 100644
index 00000000000..a2d66ffe8d3
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'WebHooks integration', :requires_admin, :integrations, :orchestrated, product_group: :integrations do
+ before(:context) do
+ toggle_local_requests(true)
+ end
+
+ after(:context) do
+ Vendor::Smocker::SmockerApi.teardown!
+ end
+
+ let(:session) { SecureRandom.hex(5) }
+
+ it 'sends a push event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348945' do
+ setup_webhook(push: true) do |webhook, smocker|
+ Resource::Repository::ProjectPush.fabricate! do |project_push|
+ project_push.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].push?).to be(true), "Not push event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a merge request event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349720' do
+ setup_webhook(merge_requests: true) do |webhook, smocker|
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].mr?).to be(true), "Not MR event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a wiki page event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349722' do
+ setup_webhook(wiki_page: true) do |webhook, smocker|
+ Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
+ page.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].wiki?).to be(true), "Not wiki event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends an issues and note event',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
+ setup_webhook(issues: true, note: true) do |webhook, smocker|
+ issue = Resource::Issue.fabricate_via_api! do |issue_init|
+ issue_init.project = webhook.project
+ end
+
+ Resource::ProjectIssueNote.fabricate_via_api! do |note|
+ note.project = issue.project
+ note.issue = issue
+ end
+
+ wait_until do
+ smocker.history(session).size > 1
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ issue_event = events.find(&:issue?)
+ note_event = events.find(&:note?)
+
+ expect(events.size).to be(2), "Should have 2 events: \n#{events.map(&:raw).join("\n")}"
+ expect(issue_event).not_to be(nil), "Not issue event: \n#{events[0].raw}"
+ expect(note_event).not_to be(nil), "Not note event: \n#{events[1].raw}"
+ end
+ end
+ end
+
+ private
+
+ def setup_webhook(**event_args)
+ Vendor::Smocker::SmockerApi.init(wait: 10) do |smocker|
+ smocker.register(session: session)
+
+ webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
+ hook.url = smocker.url
+
+ event_args.each do |event, bool|
+ hook.send("#{event}_events=", bool)
+ end
+ end
+
+ yield(webhook, smocker)
+
+ smocker.reset
+ end
+ end
+
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
+ end
+
+ def wait_until(timeout = 120, &block)
+ Support::Waiter.wait_until(max_duration: timeout, reload_page: false, raise_on_failure: false, &block)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
index f721b3326a0..e17e12cdaf3 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :reliable, :requires_admin do
+ RSpec.describe 'Manage', :reliable, :requires_admin, product_group: :import do
describe 'Gitlab migration' do
let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
let(:admin_api_client) { Runtime::API::Client.as_admin }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
index 74a00e1c74c..c1f11b15068 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
let!(:source_issue) do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
index 83cc44f9958..5689fa169ce 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
@@ -5,7 +5,7 @@
# rubocop:disable Rails/Pluck, Layout/LineLength, RSpec/MultipleMemoizedHelpers
module QA
RSpec.describe "Manage", requires_admin: 'creates users', only: { job: 'large-gitlab-import' } do
- describe "Gitlab migration" do
+ describe "Gitlab migration", product_group: :import do
let(:logger) { Runtime::Logger.logger }
let(:differ) { RSpec::Support::Differ.new(color: true) }
let(:gitlab_group) { ENV['QA_LARGE_IMPORT_GROUP'] || 'gitlab-migration' }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
index 704325d9235..aa4d3becbe7 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
let(:member) do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
index d656ea4dea5..92cba005832 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with merge request' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
index 484c32956e3..3db4ff4351e 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with ci pipeline' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
index 421dbe56a99..3e0df3d1e13 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with uninitialized project' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
index 6910b6a7fa2..91dcfe6a1a3 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with release' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
index 3581ad3d207..9c80c088917 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
@@ -1,9 +1,11 @@
# frozen_string_literal: true
module QA
- # Disable on live envs until bulk_import_projects toggle is on by default
- # Otherwise tests running in parallel can disable feature in the middle of other test
RSpec.shared_context 'with gitlab project migration', requires_admin: 'creates a user via API',
+ quarantine: {
+ type: :flaky,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/364839'
+ },
feature_flag: {
name: 'bulk_import_projects',
scope: :global
diff --git a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
index 539da92f471..c4be90d3759 100644
--- a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
@@ -33,9 +33,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @project_access_token.project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.not_to raise_error
end
@@ -67,9 +65,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @different_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
end
diff --git a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
index 874626e01f1..24088057abc 100644
--- a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
- describe 'rate limits', :reliable do
+ describe 'rate limits', :reliable, product_group: :integrations do
let(:rate_limited_user) { Resource::User.fabricate_via_api! }
let(:api_client) { Runtime::API::Client.new(:gitlab, user: rate_limited_user) }
let!(:request) { Runtime::API::Request.new(api_client, '/users') }
diff --git a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
index e518bbfc6f7..28c20344b29 100644
--- a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
@@ -69,9 +69,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
end
diff --git a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
index 9f0e2664213..16d4fd35b69 100644
--- a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'User', :requires_admin do
+ describe 'User', :requires_admin, product_group: :workspace do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:sub_group) do
@@ -85,9 +85,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = sub_group_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.not_to raise_error
end
@@ -167,9 +165,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = parent_group_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError,
/403 Forbidden - You are not allowed to push into this branch/)
diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb
index 531419e8d0f..ff036c18671 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/users_spec.rb
@@ -4,7 +4,7 @@ require 'airborne'
module QA
RSpec.describe 'Manage' do
- describe 'Users API', :reliable do
+ describe 'Users API', :reliable, product_group: :workspace do
let(:api_client) { Runtime::API::Client.new(:gitlab) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }