Commit d4db3cf9 authored by Sanad Liaquat's avatar Sanad Liaquat

Merge branch 'acunskis-refactor-mr-api' into 'master'

E2E: Refactor merge request resource to api-only fabrication

See merge request gitlab-org/gitlab!77223
parents ccf33f48 015ab3aa
...@@ -6,11 +6,13 @@ module QA ...@@ -6,11 +6,13 @@ module QA
attr_accessor :approval_rules, attr_accessor :approval_rules,
:source_branch, :source_branch,
:target_new_branch, :target_new_branch,
:update_existing_file,
:assignee, :assignee,
:milestone, :milestone,
:labels, :labels,
:file_name, :file_name,
:file_content :file_content
attr_writer :no_preparation, attr_writer :no_preparation,
:wait_for_merge, :wait_for_merge,
:template :template
...@@ -25,6 +27,8 @@ module QA ...@@ -25,6 +27,8 @@ module QA
attribute :project do attribute :project do
Project.fabricate_via_api! do |resource| Project.fabricate_via_api! do |resource|
resource.name = 'project-with-merge-request' resource.name = 'project-with-merge-request'
resource.initialize_with_readme = true
resource.api_client = api_client
end end
end end
...@@ -33,22 +37,27 @@ module QA ...@@ -33,22 +37,27 @@ module QA
end end
attribute :target do attribute :target do
Repository::ProjectPush.fabricate! do |resource| Repository::Commit.fabricate_via_api! do |resource|
resource.project = project resource.project = project
resource.branch_name = target_branch resource.api_client = api_client
resource.new_branch = target_new_branch resource.commit_message = 'This is a test commit'
resource.remote_branch = target_branch resource.add_files([{ 'file_path': "file-#{SecureRandom.hex(8)}.txt", 'content': 'MR init' }])
resource.branch = target_branch
resource.start_branch = project.default_branch if target_branch != project.default_branch
end end
end end
attribute :source do attribute :source do
Repository::ProjectPush.fabricate! do |resource| Repository::Commit.fabricate_via_api! do |resource|
resource.project = project resource.project = project
resource.branch_name = target_branch resource.api_client = api_client
resource.remote_branch = source_branch resource.commit_message = 'This is a test commit'
resource.new_branch = false resource.branch = source_branch
resource.file_name = file_name resource.start_branch = target_branch
resource.file_content = file_content
files = [{ 'file_path': file_name, 'content': file_content }]
update_existing_file ? resource.update_files(files) : resource.add_files(files)
end end
end end
...@@ -63,6 +72,7 @@ module QA ...@@ -63,6 +72,7 @@ module QA
@file_name = "added_file-#{SecureRandom.hex(8)}.txt" @file_name = "added_file-#{SecureRandom.hex(8)}.txt"
@file_content = "File Added" @file_content = "File Added"
@target_new_branch = true @target_new_branch = true
@update_existing_file = false
@no_preparation = false @no_preparation = false
@wait_for_merge = true @wait_for_merge = true
end end
...@@ -204,8 +214,24 @@ module QA ...@@ -204,8 +214,24 @@ module QA
super(api_resource) super(api_resource)
end end
# Create source and target and commits if necessary
#
# @return [void]
def populate_target_and_source_if_required def populate_target_and_source_if_required
populate(:target, :source) unless @no_preparation return if @no_preparation
populate(:target) if create_target?
populate(:source)
end
# Check if target needs to be created
#
# Return false if project was already initialized and mr target is default branch
# Return false if target_new_branch is explicitly set to false
#
# @return [Boolean]
def create_target?
!(project.initialize_with_readme && target_branch == project.default_branch) && target_new_branch
end end
end end
end end
......
...@@ -107,32 +107,6 @@ module QA ...@@ -107,32 +107,6 @@ module QA
super super
end end
def has_file?(file_path)
response = repository_tree
raise ResourceNotFoundError, (response[:message]).to_s if response.is_a?(Hash) && response.has_key?(:message)
response.any? { |file| file[:path] == file_path }
end
def has_branch?(branch)
has_branches?(Array(branch))
end
def has_branches?(branches)
branches.all? do |branch|
response = get(request_url("#{api_repository_branches_path}/#{branch}"))
response.code == HTTP_STATUS_OK
end
end
def has_tags?(tags)
tags.all? do |tag|
response = get(request_url("#{api_repository_tags_path}/#{tag}"))
response.code == HTTP_STATUS_OK
end
end
def api_get_path def api_get_path
"/projects/#{CGI.escape(path_with_namespace)}" "/projects/#{CGI.escape(path_with_namespace)}"
end end
...@@ -237,6 +211,32 @@ module QA ...@@ -237,6 +211,32 @@ module QA
post_body post_body
end end
def has_file?(file_path)
response = repository_tree
raise ResourceNotFoundError, (response[:message]).to_s if response.is_a?(Hash) && response.has_key?(:message)
response.any? { |file| file[:path] == file_path }
end
def has_branch?(branch)
has_branches?(Array(branch))
end
def has_branches?(branches)
branches.all? do |branch|
response = get(request_url("#{api_repository_branches_path}/#{branch}"))
response.code == HTTP_STATUS_OK
end
end
def has_tags?(tags)
tags.all? do |tag|
response = get(request_url("#{api_repository_tags_path}/#{tag}"))
response.code == HTTP_STATUS_OK
end
end
def change_repository_storage(new_storage) def change_repository_storage(new_storage)
response = put(request_url(api_put_path), repository_storage: new_storage) response = put(request_url(api_put_path), repository_storage: new_storage)
......
...@@ -22,42 +22,7 @@ module QA ...@@ -22,42 +22,7 @@ module QA
def initialize def initialize
@commit_message = 'QA Test - Commit message' @commit_message = 'QA Test - Commit message'
end @actions = []
def add_files(files)
validate_files!(files)
@add_files = files
end
def add_directory(dir)
raise "Must set directory as a Pathname" unless dir.is_a?(Pathname)
files_to_add = []
dir.each_child do |child|
case child.ftype?
when "file"
files_to_add.append({
file_path: child.to_s,
content: child.read
})
when "directory"
add_directory(child)
else
continue
end
end
validate_files!(files_to_add)
@add_files.merge(files_to_add)
end
def update_files(files)
validate_files!(files)
@update_files = files
end end
# If `actions` are specified, it performs the actions to create, # If `actions` are specified, it performs the actions to create,
...@@ -72,32 +37,74 @@ module QA ...@@ -72,32 +37,74 @@ module QA
end end
def api_get_path def api_get_path
api_post_path "/projects/#{CGI.escape(project.path_with_namespace)}/repository/commits"
end end
def api_post_path def api_post_path
"/projects/#{CGI.escape(project.path_with_namespace)}/repository/commits" api_get_path
end end
def api_post_body def api_post_body
{ {
branch: @branch || project.default_branch, branch: branch || project.default_branch,
author_email: @author_email || Runtime::User.default_email, author_email: author_email || api_client.user&.email || Runtime::User.default_email,
author_name: @author_name || Runtime::User.username, author_name: author_name || api_client.user&.name || Runtime::User.username,
commit_message: commit_message, commit_message: commit_message,
actions: actions actions: actions
}.merge(new_branch) }.merge(new_branch)
end end
def actions # Add files
pending_actions = [] # Pass in array of new files like, example:
pending_actions << @add_files.map { |file| file.merge({ action: "create" }) } if @add_files # [{ "file_path": "foo/bar", "content": "some content" }]
pending_actions << @update_files.map { |file| file.merge({ action: "update" }) } if @update_files #
pending_actions.flatten # @param [Array<Hash>] files
# @return [void]
def add_files(files)
validate_files!(files)
actions.push(*files.map { |file| file.merge({ action: "create" }) })
end
# Update files
# Pass in array of files and it's contents, example:
# [{ "file_path": "foo/bar", "content": "some content" }]
#
# @param [Array<Hash>] files
# @return [void]
def update_files(files)
validate_files!(files)
actions.push(*files.map { |file| file.merge({ action: "update" }) })
end
# Add all files from directory
#
# @param [Pathname] dir
# @return [void]
def add_directory(dir)
raise "Must set directory as a Pathname" unless dir.is_a?(Pathname)
files_to_add = []
dir.each_child do |child|
case child.ftype
when "directory"
add_directory(child)
when "file"
files_to_add.push({ file_path: child.basename, content: child.read })
else
continue
end
end
add_files(files_to_add)
end end
private private
attr_reader :actions
def validate_files!(files) def validate_files!(files)
if !files.is_a?(Array) || if !files.is_a?(Array) ||
files.empty? || files.empty? ||
......
...@@ -198,6 +198,8 @@ module QA ...@@ -198,6 +198,8 @@ module QA
end end
context 'with merge request' do context 'with merge request' do
let(:source_project_with_readme) { true }
let(:other_user) do let(:other_user) do
Resource::User.fabricate_via_api! do |usr| Resource::User.fabricate_via_api! do |usr|
usr.api_client = admin_api_client usr.api_client = admin_api_client
......
...@@ -19,7 +19,7 @@ module QA ...@@ -19,7 +19,7 @@ module QA
group = QA::Resource::Group.fabricate_via_api! do |group| group = QA::Resource::Group.fabricate_via_api! do |group|
group.path = "group_for_follow_user_activity_#{SecureRandom.hex(8)}" group.path = "group_for_follow_user_activity_#{SecureRandom.hex(8)}"
end end
group.add_member(user) group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
group group
end end
......
...@@ -13,7 +13,7 @@ module QA ...@@ -13,7 +13,7 @@ module QA
Resource::Runner.fabricate_via_api! do |runner| Resource::Runner.fabricate_via_api! do |runner|
runner.project = project runner.project = project
runner.name = project.name runner.name = project.name
runner.tags = ["#{project.name}"] runner.tags = [project.name]
end end
end end
......
...@@ -5,7 +5,7 @@ module QA ...@@ -5,7 +5,7 @@ module QA
describe 'License merge request widget' do describe 'License merge request widget' do
let(:approved_license_name) { "MIT License" } let(:approved_license_name) { "MIT License" }
let(:denied_license_name) { "zlib License" } let(:denied_license_name) { "zlib License" }
let(:executor) {"qa-runner-#{Time.now.to_i}"} let(:executor) { "qa-runner-#{Time.now.to_i}" }
after do after do
@runner.remove_via_api! @runner.remove_via_api!
...@@ -25,12 +25,12 @@ module QA ...@@ -25,12 +25,12 @@ module QA
runner.tags = ['secure_license'] runner.tags = ['secure_license']
end end
Resource::Repository::ProjectPush.fabricate! do |project_push| Resource::Repository::Commit.fabricate_via_api! do |resource|
project_push.project = @project resource.project = @project
project_push.directory = Pathname resource.commit_message = 'Create license file'
resource.add_directory(Pathname
.new(__dir__) .new(__dir__)
.join('../../../../../ee/fixtures/secure_license_files') .join('../../../../../ee/fixtures/secure_license_files'))
project_push.commit_message = 'Create license file'
end end
@project.visit! @project.visit!
...@@ -40,7 +40,6 @@ module QA ...@@ -40,7 +40,6 @@ module QA
mr.project = @project mr.project = @project
mr.source_branch = 'license-management-mr' mr.source_branch = 'license-management-mr'
mr.target_branch = @project.default_branch mr.target_branch = @project.default_branch
mr.target = @project.default_branch
mr.file_name = 'gl-license-scanning-report.json' mr.file_name = 'gl-license-scanning-report.json'
mr.file_content = mr.file_content =
<<~FILE_UPDATE <<~FILE_UPDATE
...@@ -89,6 +88,7 @@ module QA ...@@ -89,6 +88,7 @@ module QA
} }
FILE_UPDATE FILE_UPDATE
mr.target_new_branch = false mr.target_new_branch = false
mr.update_existing_file = true
end end
@project.visit! @project.visit!
...@@ -102,8 +102,7 @@ module QA ...@@ -102,8 +102,7 @@ module QA
# Give time for the runner to complete pipeline # Give time for the runner to complete pipeline
show.has_pipeline_status?('passed') show.has_pipeline_status?('passed')
# TODO: Remove the reload_page: once https://gitlab.com/gitlab-org/gitlab/-/issues/335227 is fixed Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 5) do
Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 5, reload_page: show) do
show.wait_for_license_compliance_report show.wait_for_license_compliance_report
end end
......
...@@ -70,6 +70,7 @@ module QA ...@@ -70,6 +70,7 @@ module QA
merge_request.project = @project merge_request.project = @project
merge_request.description = Faker::Lorem.sentence merge_request.description = Faker::Lorem.sentence
merge_request.target_new_branch = false merge_request.target_new_branch = false
merge_request.update_existing_file = true
merge_request.file_name = @file_name merge_request.file_name = @file_name
merge_request.file_content = Faker::Lorem.sentence merge_request.file_content = Faker::Lorem.sentence
end end
...@@ -115,7 +116,7 @@ module QA ...@@ -115,7 +116,7 @@ module QA
Page::Dashboard::Todos.perform do |todos| Page::Dashboard::Todos.perform do |todos|
todos.wait_until(reload: true, sleep_interval: 1) { todos.has_todo_list? } todos.wait_until(reload: true, sleep_interval: 1) { todos.has_todo_list? }
expect(todos).to have_latest_todo_item_with_content("Removed from Merge Train:", "#{mr_title}") expect(todos).to have_latest_todo_item_with_content("Removed from Merge Train:", @mr_title)
end end
end end
end end
......
...@@ -3,7 +3,13 @@ ...@@ -3,7 +3,13 @@
module QA module QA
RSpec.describe 'Verify', :runner, :reliable do RSpec.describe 'Verify', :runner, :reliable do
describe 'Pipelines for merged results and merge trains' do describe 'Pipelines for merged results and merge trains' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } let!(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'pipelines-for-merge-trains'
end
end
let!(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate_via_api! do |runner| Resource::Runner.fabricate_via_api! do |runner|
...@@ -13,12 +19,6 @@ module QA ...@@ -13,12 +19,6 @@ module QA
end end
end end
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'pipelines-for-merge-trains'
end
end
let!(:ci_file) do let!(:ci_file) do
Resource::Repository::Commit.fabricate_via_api! do |commit| Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project commit.project = project
...@@ -60,7 +60,10 @@ module QA ...@@ -60,7 +60,10 @@ module QA
runner.remove_via_api! if runner runner.remove_via_api! if runner
end end
it 'creates a pipeline with merged results', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348034' do it(
'creates a pipeline with merged results',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348034'
) do
merge_request.visit! merge_request.visit!
Page::MergeRequest::Show.perform do |show| Page::MergeRequest::Show.perform do |show|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment