diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-20 23:50:22 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-20 23:50:22 +0000 |
commit | 9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch) | |
tree | 70467ae3692a0e35e5ea56bcb803eb512a10bedb /qa/qa/specs | |
parent | 4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff) | |
download | gitlab-ce-9dc93a4519d9d5d7be48ff274127136236a3adb3.tar.gz |
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'qa/qa/specs')
50 files changed, 1149 insertions, 163 deletions
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 new file mode 100644 index 00000000000..6024c8658d5 --- /dev/null +++ b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Project access token' do + before(:all) do + @project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api! + @user_api_client = Runtime::API::Client.new(:gitlab, personal_access_token: @project_access_token.token) + end + + context 'for the same project' do + it 'can be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1734' do + expect do + Resource::File.fabricate_via_api! do |file| + file.api_client = @user_api_client + file.project = @project_access_token.project + file.branch = 'new_branch' + file.commit_message = 'Add new file' + file.name = "text-#{SecureRandom.hex(8)}.txt" + file.content = 'New file' + end + end.not_to raise_error + end + + it 'can be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1735' do + expect do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.api_client = @user_api_client + commit.project = @project_access_token.project + commit.branch = 'new_branch' + 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' } + ]) + end + end.not_to raise_error + end + end + + context 'for a different project' do + before(:all) do + @different_project = Resource::Project.fabricate! + end + + it 'cannot be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1736' do + expect do + Resource::File.fabricate_via_api! do |file| + file.api_client = @user_api_client + file.project = @different_project + file.branch = 'new_branch' + file.commit_message = 'Add new file' + file.name = "text-#{SecureRandom.hex(8)}.txt" + file.content = 'New file' + end + end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden/) + end + + it 'cannot be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1737' do + expect do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.api_client = @user_api_client + commit.project = @different_project + commit.branch = 'new_branch' + 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' } + ]) + end + end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/) + end + + after(:all) do + @different_project.remove_via_api! + end + end + + after(:all) do + @project_access_token.remove_via_api! + @project_access_token.project.remove_via_api! + end + end + end +end 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 b7f71ad5bcd..a069b94f4da 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 @@ -12,7 +12,9 @@ module QA @user_api_client = Runtime::API::Client.new(:gitlab, user: @user) - @group = Resource::Group.fabricate_via_api! + @group = QA::Resource::Group.fabricate_via_api! do |group| + group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}" + end @group.sandbox.add_member(@user) @@ -73,11 +75,7 @@ module QA after(:all) do @user.remove_via_api! @project.remove_via_api! - begin - @group.remove_via_api! - rescue Resource::ApiFabricator::ResourceNotDeletedError - # It is ok if the group is already marked for deletion by another test - end + @group.remove_via_api! end end end diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb index 631056ed52e..176f1139a7a 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb @@ -9,7 +9,7 @@ module QA it 'confirms a `finished` status after moving project repository storage' do expect(project).to have_file('README.md') expect { project.change_repository_storage(destination_storage[:name]) }.not_to raise_error - expect { praefect_manager.verify_storage_move(source_storage, destination_storage) }.not_to raise_error + expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :project) }.not_to raise_error Resource::Repository::ProjectPush.fabricate! do |push| push.project = project @@ -45,7 +45,7 @@ module QA # Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect # scenario with other tests that aren't considered orchestrated. # It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage - context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do + context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1755', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } } let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } } let(:project) do diff --git a/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb b/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb new file mode 100644 index 00000000000..c06e3b9f162 --- /dev/null +++ b/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'PostReceive idempotent' do + # Tests that a push does not result in multiple changes from repeated PostReceive executions. + # One of the consequences would be duplicate push events + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'push-postreceive-idempotent' + project.initialize_with_readme = true + end + end + + after do + project&.remove_via_api! + end + + it 'pushes and creates a single push event three times', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1744' do + verify_single_event_per_push(repeat: 3) + end + + it 'repeatedly pushes and creates a single push event several times', :transient, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1744' do + verify_single_event_per_push(repeat: Runtime::Env.transient_trials) do |i| + QA::Runtime::Logger.info("Transient bug test action - Trial #{i}") + end + end + + def verify_single_event_per_push(repeat:) + repeat.times do |i| + yield i if block_given? + + commit_message = "test post-receive idempotency #{SecureRandom.hex(8)}" + + Resource::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.new_branch = false + push.commit_message = commit_message + end + + events = project.push_events(commit_message) + + aggregate_failures do + expect(events.size).to eq(1), "An unexpected number of push events was created" + expect(events.first.dig(:push_data, :commit_title)).to eq(commit_message) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb index 4872acd1004..7b82a872fc0 100644 --- a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb +++ b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb @@ -24,7 +24,7 @@ module QA it 'moves snippet repository from one Gitaly storage to another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1700' do expect(snippet).to have_file('original_file') expect { snippet.change_repository_storage(destination_storage[:name]) }.not_to raise_error - expect { praefect_manager.verify_storage_move(source_storage, destination_storage) }.not_to raise_error + expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :snippet) }.not_to raise_error # verifies you can push commits to the moved snippet Resource::Repository::Push.fabricate! do |push| diff --git a/qa/qa/specs/features/api/4_verify/.gitkeep b/qa/qa/specs/features/api/4_verify/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 --- a/qa/qa/specs/features/api/4_verify/.gitkeep +++ /dev/null diff --git a/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb b/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb new file mode 100644 index 00000000000..ecca0f94604 --- /dev/null +++ b/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Verify', :requires_admin do + describe 'When user is blocked' do + let!(:admin_api_client) { Runtime::API::Client.as_admin } + let!(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) } + + let(:user) do + Resource::User.fabricate_via_api! do |resource| + resource.api_client = admin_api_client + end + end + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-for-canceled-schedule' + end + end + + before do + project.add_member(user, Resource::Members::AccessLevel::MAINTAINER) + + Resource::PipelineSchedules.fabricate_via_api! do |schedule| + schedule.api_client = user_api_client + schedule.project = project + end + + Support::Waiter.wait_until { !pipeline_schedule[:id].nil? && pipeline_schedule[:active] == true } + end + + after do + user.remove_via_api! + project.remove_via_api! + end + + it 'pipeline schedule is canceled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1730' do + user.block! + + expect(pipeline_schedule[:active]).not_to be_truthy, "Expected schedule active state to be false - active state #{pipeline_schedule[:active]}" + end + + private + + def pipeline_schedule + project.pipeline_schedules.first + end + end + end +end diff --git a/qa/qa/specs/features/api/5_package/.gitkeep b/qa/qa/specs/features/api/5_package/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 --- a/qa/qa/specs/features/api/5_package/.gitkeep +++ /dev/null diff --git a/qa/qa/specs/features/api/5_package/container_registry_spec.rb b/qa/qa/specs/features/api/5_package/container_registry_spec.rb new file mode 100644 index 00000000000..57b059ffc02 --- /dev/null +++ b/qa/qa/specs/features/api/5_package/container_registry_spec.rb @@ -0,0 +1,119 @@ +# frozen_string_literal: true + +require 'airborne' + +module QA + RSpec.describe 'Package', only: { subdomain: :staging } do + include Support::Api + + describe 'Container Registry' do + let(:api_client) { Runtime::API::Client.new(:gitlab) } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-registry-api' + project.template_name = 'express' + end + end + + let(:registry) do + Resource::RegistryRepository.new.tap do |repository| + repository.name = "#{project.path_with_namespace}" + repository.project = project + repository.tag_name = 'master' + end + end + + let(:gitlab_ci_yaml) do + <<~YAML + stages: + - build + - test + + build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG + - docker pull $IMAGE_TAG + + test: + image: dwdraju/alpine-curl-jq:latest + stage: test + variables: + MEDIA_TYPE: 'application/vnd.docker.distribution.manifest.v2+json' + before_script: + - token=$(curl -u "$CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD" "https://$CI_SERVER_HOST/jwt/auth?service=container_registry&scope=repository:$CI_PROJECT_PATH:pull,push,delete" | jq -r '.token') + script: + - 'digest=$(curl -L -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/master" | jq -r ".layers[0].digest")' + - 'curl -L -X DELETE -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/blobs/$digest"' + - 'curl -L --head -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/blobs/$digest"' + - 'digest=$(curl -L -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/master" | jq -r ".config.digest")' + - 'curl -L -X DELETE -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/$digest"' + - 'curl -L --head -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/$digest"' + + YAML + end + + after do + registry&.remove_via_api! + end + + it 'pushes, pulls image to the registry and deletes image blob, manifest and tag', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1738' do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: gitlab_ci_yaml + }]) + end + + Support::Waiter.wait_until(max_duration: 10) { pipeline_is_triggered? } + + Support::Retrier.retry_until(max_duration: 260, sleep_interval: 5) do + latest_pipeline_succeed? + end + + expect(job_log).to have_content '404 Not Found' + + expect(registry).to have_tag('master') + + registry.delete_tag + + expect(registry).not_to have_tag('master') + end + + private + + def pipeline_is_triggered? + !project.pipelines.empty? + end + + def latest_pipeline_succeed? + latest_pipeline = project.pipelines.first + latest_pipeline[:status] == 'success' + end + + def job_log + pipeline = project.pipelines.first + pipeline_id = pipeline[:id] + + jobs = get Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipelines/#{pipeline_id}/jobs").url + test_job = parse_body(jobs).first + test_job_id = test_job[:id] + + log = get Runtime::API::Request.new(api_client, "/projects/#{project.id}/jobs/#{test_job_id}/trace").url + QA::Runtime::Logger.debug(" \n\n ------- Test job log: ------- \n\n #{log} \n -------") + + log + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb new file mode 100644 index 00000000000..d6bcd134a03 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Subgroup transfer' do + let(:source_group) do + Resource::Group.fabricate_via_api! do |group| + group.path = "source-group-for-transfer_#{SecureRandom.hex(8)}" + end + end + + let!(:target_group) do + Resource::Group.fabricate_via_api! do |group| + group.path = "target-group-for-transfer_#{SecureRandom.hex(8)}" + end + end + + let(:sub_group_for_transfer) do + Resource::Group.fabricate_via_api! do |group| + group.path = "subgroup-for-transfer_#{SecureRandom.hex(8)}" + group.sandbox = source_group + end + end + + before do + Flow::Login.sign_in + sub_group_for_transfer.visit! + end + + it 'transfers a subgroup to another group', + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do + Page::Group::Menu.perform(&:click_group_general_settings_item) + Page::Group::Settings::General.perform do |general| + general.transfer_group(target_group.path) + end + + expect(page).to have_text("Group '#{sub_group_for_transfer.path}' was successfully transferred.") + expect(page.driver.current_url).to include("#{target_group.path}/#{sub_group_for_transfer.path}") + end + + after do + source_group&.remove_via_api! + target_group&.remove_via_api! + sub_group_for_transfer&.remove_via_api! + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb index 4141060b6cb..5fbcd69817b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb @@ -71,7 +71,7 @@ module QA Flow::Login.sign_in(as: user, skip_page_validation: true) - expect(page).to have_text("Invalid Login or password") + expect(page).to have_text("Invalid login or password") @recreated_user = Resource::User.fabricate_via_browser_ui! do |resource| resource.name = user.name diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index c8c483fc2aa..5072b6d48bf 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -29,7 +29,7 @@ module QA user.remove_via_api! end - it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do + it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1762' do Flow::Login.sign_in(as: user) imported_project # import the project diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb new file mode 100644 index 00000000000..00d1b829150 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Project access tokens' do + let(:project_access_token) {QA::Resource::ProjectAccessToken.fabricate_via_browser_ui!} + + it 'can be created and revoked via the UI' do + expect(project_access_token.token).not_to be_nil + + project_access_token.revoke_via_ui! + expect(page).to have_text("Revoked project access token #{project_access_token.name}!") + end + + after do + project_access_token.project.remove_via_api! + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb index 7ec217cb47d..2a91c674a22 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb @@ -12,7 +12,9 @@ module QA end let!(:group) do - group = Resource::Group.fabricate_via_api! + group = QA::Resource::Group.fabricate_via_api! do |group| + group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}" + end group.sandbox.add_member(user) group end @@ -53,11 +55,7 @@ module QA after do user.remove_via_api! project.remove_via_api! - begin - group.remove_via_api! - rescue Resource::ApiFabricator::ResourceNotDeletedError - # It is ok if the group is already marked for deletion by another test - end + group.remove_via_api! end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb index de6b24e8477..b2b37fcd424 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -48,7 +48,7 @@ module QA Resource::Issue.fabricate_via_api!.visit! end - it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/393' do + it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1742' do Page::Project::Issue::Show.perform do |show| show.comment('See attached banana for scale', attachment: file_to_attach) diff --git a/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb new file mode 100644 index 00000000000..f2e4a320e04 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Plan', :transient do + describe 'Discussion comments transient bugs' do + let(:user1) do + Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) + end + + let(:my_first_reply) { 'This is my first reply' } + let(:my_second_reply) { "@#{Runtime::Env.gitlab_qa_username_1}" } + let(:my_third_reply) { "@#{Runtime::Env.gitlab_qa_username_1} This is my third reply" } + let(:my_fourth_reply) { '/close' } + + before do + Flow::Login.sign_in + end + + it 'comments with mention on a discussion in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1753' do + Runtime::Env.transient_trials.times do |i| + QA::Runtime::Logger.info("Transient bug test action - Trial #{i}") + + Resource::Issue.fabricate_via_api!.visit! + + Page::Project::Issue::Show.perform do |issue_page| + issue_page.select_all_activities_filter + issue_page.start_discussion('My first discussion') + issue_page.reply_to_discussion(1, my_first_reply) + + expect(issue_page).to have_comment(my_first_reply) + + issue_page.reply_to_discussion(1, "#{my_second_reply}\n") + + expect(issue_page).to have_comment(my_second_reply) + + issue_page.reply_to_discussion(1, my_third_reply) + + expect(issue_page).to have_comment(my_third_reply) + + issue_page.reply_to_discussion(1, my_fourth_reply) + + expect(issue_page).to have_system_note('closed') + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb index 43cf701acdd..6afc7549c59 100644 --- a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb @@ -23,7 +23,7 @@ module QA Flow::Login.sign_in end - it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/274' do + it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1761' do third_design.issue.visit! Page::Project::Issue::Show.perform do |issue| diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb index 9fbb0d69de1..dfdc9b7c9b4 100644 --- a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb @@ -13,7 +13,7 @@ module QA Flow::Login.sign_in end - it 'user adds a design and modifies it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/273' do + it 'user adds a design and modifies it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1760' do design.issue.visit! Page::Project::Issue::Show.perform do |issue| diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb new file mode 100644 index 00000000000..16afa3be62a --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Cherry picking from a merge request' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project' + project.initialize_with_readme = true + end + end + + let(:feature_mr) do + Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project + merge_request.target_branch = 'development' + merge_request.target_new_branch = true + end + end + + before do + Flow::Login.sign_in + end + + it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1616' do + feature_mr.visit! + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.merge! + merge_request.cherry_pick! + end + + Page::MergeRequest::New.perform(&:create_merge_request) + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + expect(merge_request).to have_file(feature_mr.file_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb new file mode 100644 index 00000000000..41746e84862 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Cherry picking a commit' do + let(:file_name) { "secret_file.md" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project' + project.initialize_with_readme = true + end + end + + let(:commit) do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.branch = "development" + commit.start_branch = project.default_branch + commit.commit_message = 'Add new file' + commit.add_files([ + { file_path: file_name, content: 'pssst!' } + ]) + end + end + + before do + Flow::Login.sign_in + commit.visit! + end + + it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1752' do + Page::Project::Commit::Show.perform(&:cherry_pick_commit) + Page::MergeRequest::New.perform(&:create_merge_request) + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + expect(merge_request).to have_file(file_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb index 8d12042bd85..c2e148e19bd 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -3,13 +3,11 @@ module QA RSpec.describe 'Create' do describe 'Merge request creation from fork', :smoke do - let!(:merge_request) do - Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request| + it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do + merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request| merge_request.fork_branch = 'feature-branch' end - end - it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do Flow::Login.while_signed_in do merge_request.visit! diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb index 2ddc59acd5c..2b1ac75b9f5 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb @@ -3,82 +3,97 @@ module QA RSpec.describe 'Create', :runner do describe 'Merge requests' do - let(:project) do - Resource::Project.fabricate_via_api! do |project| - project.name = 'merge-when-pipeline-succeeds' - project.initialize_with_readme = true + shared_examples 'merge when pipeline succeeds' do |repeat: 1| + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'merge-when-pipeline-succeeds' + project.initialize_with_readme = true + end end - end - let!(:runner) do - Resource::Runner.fabricate! do |runner| - runner.project = project - runner.name = "runner-for-#{project.name}" - runner.tags = ["runner-for-#{project.name}"] + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = "runner-for-#{project.name}" + runner.tags = ["runner-for-#{project.name}"] + end end - end - before do - Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project - commit.commit_message = 'Add .gitlab-ci.yml' - commit.add_files( - [ - { - file_path: '.gitlab-ci.yml', - content: <<~EOF - test: - tags: ["runner-for-#{project.name}"] - script: sleep 5 - only: - - merge_requests - EOF - } - ] - ) + before do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files( + [ + { + file_path: '.gitlab-ci.yml', + content: <<~EOF + test: + tags: ["runner-for-#{project.name}"] + script: sleep 10 + only: + - merge_requests + EOF + } + ] + ) + end + + Flow::Login.sign_in end - Flow::Login.sign_in - end + after do + runner&.remove_via_api! + project&.remove_via_api! + end - after do - runner&.remove_via_api! - project&.remove_via_api! - end + it 'merges after pipeline succeeds' do + repeat.times do |i| + QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if repeat > 1 - it 'merges when pipeline succeeds', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do - branch_name = "merge-request-test-#{SecureRandom.hex(8)}" + branch_name = "mr-test-#{SecureRandom.hex(6)}-#{i}" - # Create a branch that will be merged into the default branch - Resource::Repository::ProjectPush.fabricate! do |project_push| - project_push.project = project - project_push.new_branch = true - project_push.branch_name = branch_name - project_push.file_name = "file-#{SecureRandom.hex(8)}.txt" - end + # Create a branch that will be merged into the default branch + Resource::Repository::ProjectPush.fabricate! do |project_push| + project_push.project = project + project_push.new_branch = true + project_push.branch_name = branch_name + project_push.file_name = "#{branch_name}.txt" + end - # Create a merge request to merge the branch we just created - merge_request = Resource::MergeRequest.fabricate_via_api! do |merge_request| - merge_request.project = project - merge_request.source_branch = branch_name - merge_request.no_preparation = true - end + # Create a merge request to merge the branch we just created + merge_request = Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project + merge_request.source_branch = branch_name + merge_request.no_preparation = true + end - merge_request.visit! + merge_request.visit! - Page::MergeRequest::Show.perform do |mr| - mr.merge_when_pipeline_succeeds! + Page::MergeRequest::Show.perform do |mr| + mr.merge_when_pipeline_succeeds! - expect(mr.merge_request_status).to match(/to be merged automatically when the pipeline succeeds/) + Support::Waiter.wait_until(sleep_interval: 5) do + merge_request = merge_request.reload! + merge_request.state == 'merged' + end - Support::Waiter.wait_until(sleep_interval: 5) do - merge_request = merge_request.reload! - merge_request.state == 'merged' + aggregate_failures do + expect(merge_request.merge_when_pipeline_succeeds).to be_truthy + expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear." + end + end end - - expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear." end end + + context 'when merging once', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do + it_behaves_like 'merge when pipeline succeeds' + end + + context 'when merging several times', :transient, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do + it_behaves_like 'merge when pipeline succeeds', repeat: Runtime::Env.transient_trials + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb new file mode 100644 index 00000000000..3574cdbe4ac --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Merged merge request' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'revert' + end + end + + let(:revertable_merge_request) do + Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project + end + end + + before do + Flow::Login.sign_in + end + + it 'can be reverted', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1745' do + revertable_merge_request.visit! + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.merge! + merge_request.revert_change! + end + + Page::MergeRequest::New.perform(&:create_merge_request) + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + expect(merge_request).to have_file(revertable_merge_request.file_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb index eab2729af83..05e274de820 100644 --- a/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb @@ -2,25 +2,23 @@ module QA RSpec.describe 'Create' do - context 'Transient tests', :transient do + context 'Add batch suggestions to a Merge Request', :transient do let(:project) do Resource::Project.fabricate_via_api! do |project| - project.name = 'project-for-transient-test' + project.name = 'suggestions_project' end end - let(:code_for_merge) do - Pathname - .new(__dir__) - .join('../../../../../fixtures/metrics_dashboards/templating.yml') - end - let(:merge_request) do Resource::MergeRequest.fabricate_via_api! do |merge_request| merge_request.project = project - merge_request.title = 'Transient MR' - merge_request.description = 'detecting transient bugs' - merge_request.file_content = File.read(code_for_merge) + merge_request.title = 'Needs some suggestions' + merge_request.description = '... so please add them.' + merge_request.file_content = File.read( + Pathname + .new(__dir__) + .join('../../../../../../fixtures/metrics_dashboards/templating.yml') + ) end end @@ -30,6 +28,7 @@ module QA before do project.add_member(dev_user) + Flow::Login.sign_in(as: dev_user, skip_page_validation: true) merge_request.visit! @@ -38,7 +37,7 @@ module QA [4, 6, 10, 13].each do |line_number| Page::MergeRequest::Show.perform do |merge_request| - merge_request.add_suggestion_to_diff("This is the #{line_number} suggestion!", line_number) + merge_request.add_suggestion_to_diff("This is the suggestion for line number #{line_number}!", line_number) end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb new file mode 100644 index 00000000000..ad12a3ec334 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + context 'Add suggestions to a Merge Request' do + let(:commit_message) { 'Applying suggested change for testing purposes.' } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'suggestions_project' + end + end + + let(:merge_request) do + Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project + merge_request.title = 'Needs some suggestions' + merge_request.description = '... so please add them.' + merge_request.file_content = File.read( + Pathname + .new(__dir__) + .join('../../../../../../fixtures/metrics_dashboards/templating.yml') + ) + end + end + + let(:dev_user) do + Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) + end + + before do + project.add_member(dev_user) + + Flow::Login.sign_in(as: dev_user, skip_page_validation: true) + merge_request.visit! + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + merge_request.add_suggestion_to_diff('This is the suggestion for line number 4!', 4) + end + + Flow::Login.sign_in + merge_request.visit! + end + + it 'applies a single suggestion with a custom message' do + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + merge_request.apply_suggestion_with_message(commit_message) + + expect(merge_request).to have_css('.badge-success', text: 'Applied') + + merge_request.click_commits_tab + + expect(merge_request).to have_content(commit_message) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb index 38c9216005f..ef3d45724db 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb @@ -27,7 +27,7 @@ module QA Page::Main::Menu.perform(&:sign_out_if_signed_in) end - it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/386' do + it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1763' do project = Resource::Project.fabricate_via_api! do |project| project.name = 'git-protocol-project' end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb index d44f5bc9e2e..70880011985 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb @@ -39,7 +39,7 @@ module QA ssh_key.remove_via_api! end - it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/826' do + it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1748' do push = Resource::Repository::Push.fabricate! do |push| push.repository_http_uri = repository_uri_http push.file_name = new_file @@ -70,7 +70,7 @@ module QA snippet.remove_via_api! end - it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do + it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1747' do push = Resource::Repository::Push.fabricate! do |push| push.repository_ssh_uri = repository_uri_ssh push.ssh_key = ssh_key diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb index ddbc98c4a1a..4f241325437 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', :smoke do + RSpec.describe 'Create' do # convert back to a smoke test once proved to be stable describe 'Personal snippet creation' do it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1704' do Flow::Login.sign_in diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb index 6044c87d24e..70959dd0200 100644 --- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb @@ -27,7 +27,7 @@ module QA edit.set_message commit_message end - Page::Project::Wiki::Edit.perform(&:click_create_page) + Page::Project::Wiki::Edit.perform(&:click_submit) Page::Project::Wiki::Show.perform do |wiki| expect(wiki).to have_title new_wiki_title @@ -46,7 +46,7 @@ module QA edit.set_message commit_message end - Page::Project::Wiki::Edit.perform(&:click_create_page) + Page::Project::Wiki::Edit.perform(&:click_submit) Page::Project::Wiki::Show.perform do |wiki| expect(wiki).to have_title new_wiki_title diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb index 30a91c2e254..9a6d7d08e7b 100644 --- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb @@ -25,7 +25,7 @@ module QA edit.set_message commit_message end - Page::Project::Wiki::Edit.perform(&:click_save_changes) + Page::Project::Wiki::Edit.perform(&:click_submit) Page::Project::Wiki::Show.perform do |wiki| expect(wiki).to have_title new_wiki_title diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb index 4f1d9ac1696..1a46322d283 100644 --- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb @@ -20,7 +20,7 @@ module QA edit.set_message('changing the path of the home page') end - Page::Project::Wiki::Edit.perform(&:click_save_changes) + Page::Project::Wiki::Edit.perform(&:click_submit) Page::Project::Wiki::Show.perform do |wiki| expect(wiki).to have_directory('a') diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb index fcd8cb02870..39cbd0028c0 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb @@ -16,7 +16,7 @@ module QA add_ci_variable end - it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/395' do + it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1759' do Page::Project::Settings::CiVariables.perform do |ci_variable| expect(ci_variable).to have_text('VARIABLE_KEY') expect(ci_variable).not_to have_text('some_CI_variable') @@ -27,7 +27,7 @@ module QA end end - it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/394' do + it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1758' do Page::Project::Settings::CiVariables.perform do |ci_variable| ci_variable.click_edit_ci_variable ci_variable.click_ci_variable_delete_button diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb new file mode 100644 index 00000000000..5083b7b0859 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Verify', :requires_admin do + describe 'Include local config file paths with wildcard' do + let(:feature_flag) { :ci_wildcard_file_paths } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline' + end + end + + before do + Runtime::Feature.enable(feature_flag) + Flow::Login.sign_in + add_files_to_project + project.visit! + Flow::Pipeline.visit_latest_pipeline + end + + after do + Runtime::Feature.disable(feature_flag) + project.remove_via_api! + end + + it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1757' do + Page::Project::Pipeline::Show.perform do |pipeline| + aggregate_failures 'pipeline has all expected jobs' do + expect(pipeline).to have_job('build') + expect(pipeline).to have_job('test') + expect(pipeline).not_to have_job('deploy') + end + end + end + + private + + def add_files_to_project + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add CI and local files' + commit.add_files([build_config_file, test_config_file, non_detectable_file, main_ci_file]) + end + end + + def main_ci_file + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + include: 'configs/*.yml' + YAML + } + end + + def build_config_file + { + file_path: 'configs/builds.yml', + content: <<~YAML + build: + stage: build + script: echo build + YAML + } + end + + def test_config_file + { + file_path: 'configs/tests.yml', + content: <<~YAML + test: + stage: test + script: echo test + YAML + } + end + + def non_detectable_file + { + file_path: 'configs/not_included.yaml', # we only include `*.yml` not `*.yaml` + content: <<~YAML + deploy: + stage: deploy + script: echo deploy + YAML + } + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb index c5d73d2fd7d..01aada2d6dd 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb @@ -39,6 +39,7 @@ module QA needs: [test_blocked_pipeline] script: echo do not click me when: manual + allow_failure: false dummy_job: stage: deploy @@ -71,8 +72,9 @@ module QA it 'can still merge MR successfully', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/971' do Page::MergeRequest::Show.perform do |show| - show.wait_until(reload: false) { show.has_pipeline_status?('running') } - show.merge_immediately! + # waiting for manual action status shows status badge 'blocked' on pipelines page + show.wait_until(reload: false) { show.has_pipeline_status?('waiting for manual action') } + show.merge! expect(show).to be_merged end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb new file mode 100644 index 00000000000..d87fa0f5127 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +require 'faker' + +module QA + RSpec.describe 'Verify', :runner do + describe 'Trigger matrix' do + let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = [executor] + end + end + + before do + Flow::Login.sign_in + add_ci_files + project.visit! + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded') + end + + after do + runner.remove_via_api! + project.remove_via_api! + end + + it 'creates 2 trigger jobs and passes corresponding matrix variables', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1732' do + Page::Project::Pipeline::Show.perform do |parent_pipeline| + trigger_title1 = 'deploy: [ovh, monitoring]' + trigger_title2 = 'deploy: [ovh, app]' + + aggregate_failures 'Creates two child pipelines' do + expect(parent_pipeline).to have_child_pipeline(title: trigger_title1) + expect(parent_pipeline).to have_child_pipeline(title: trigger_title2) + end + + # Only check output of one of the child pipelines, should be sufficient + parent_pipeline.expand_child_pipeline(title: trigger_title1) + parent_pipeline.click_job('test_vars') + end + + Page::Project::Job::Show.perform do |show| + Support::Waiter.wait_until { show.successful? } + + aggregate_failures 'Job output has the correct variables' do + expect(show.output).to have_content('ovh') + expect(show.output).to have_content('monitoring') + end + end + end + + private + + def add_ci_files + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add parent and child pipelines CI files.' + commit.add_files( + [ + child_ci_file, + parent_ci_file + ] + ) + end + end + + def parent_ci_file + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + test: + stage: test + script: echo test + tags: [#{executor}] + + deploy: + stage: deploy + trigger: + include: child.yml + parallel: + matrix: + - PROVIDER: ovh + STACK: [monitoring, app] + + YAML + } + end + + def child_ci_file + { + file_path: 'child.yml', + content: <<~YAML + test_vars: + script: + - echo $PROVIDER + - echo $STACK + tags: [#{executor}] + YAML + } + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb index 9ce87f353d0..916b809ebc1 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb @@ -15,7 +15,7 @@ module QA runner.remove_via_api! end - it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/392' do + it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1764' do Flow::Login.sign_in runner.project.visit! diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb index 5bfc88e45f2..d6d8729114d 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb @@ -33,7 +33,7 @@ module QA runner.remove_via_api! end - it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/807' do + it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1740' do runner.project.visit! configure_code_coverage(simplecov) merge_request.visit! @@ -42,7 +42,7 @@ module QA Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 5) do mr_widget.has_pipeline_status?(/Pipeline #\d+ passed/) end - expect(mr_widget).to have_content('Coverage 66.67%') + expect(mr_widget).to have_content('Test coverage 66.67%') end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb index 6c1a0cea209..2489545782a 100644 --- a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb @@ -1,18 +1,25 @@ # frozen_string_literal: true +require 'securerandom' + module QA RSpec.describe 'Package', :orchestrated, :packages do describe 'Composer Repository' do include Runtime::Fixtures - let(:package_name) { 'my_package' } - let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'composer-package-project' end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = "my_package-#{SecureRandom.hex(4)}" + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" @@ -30,7 +37,7 @@ module QA let(:composer_json_file) do <<~EOF { - "name": "#{project.path_with_namespace}/#{package_name}", + "name": "#{project.path_with_namespace}/#{package.name}", "description": "Library XY", "type": "library", "license": "GPL-3.0-only", @@ -94,14 +101,15 @@ module QA after do runner.remove_via_api! + package.remove_via_api! end it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1088' do Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) - index.click_package(package_name) + expect(index).to have_package(package.name) + index.click_package(package.name) end Page::Project::Packages::Show.perform(&:click_delete) @@ -109,7 +117,7 @@ module QA Page::Project::Packages::Index.perform do |index| aggregate_failures 'package deletion' do expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + expect(index).not_to have_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb index 7effefc4d73..a1e2eb1046c 100644 --- a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb @@ -5,14 +5,19 @@ module QA describe 'Conan Repository' do include Runtime::Fixtures - let(:package_name) { 'conantest' } - let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'conan-package-project' end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = 'conantest' + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" @@ -29,6 +34,7 @@ module QA after do runner.remove_via_api! + package.remove_via_api! end it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do @@ -47,10 +53,10 @@ module QA stage: deploy script: - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan" - - "conan new #{package_name}/0.1 -t" + - "conan new #{package.name}/0.1 -t" - "conan create . mycompany/stable" - - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab" - - "conan install conantest/0.1@mycompany/stable --remote=gitlab" + - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab" + - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab" tags: - "runner-for-#{project.name}" YAML @@ -71,15 +77,15 @@ module QA Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) - index.click_package(package_name) + expect(index).to have_package(package.name) + index.click_package(package.name) end Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + expect(index).not_to have_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb index 3e3addf9eeb..bbf8ea8c05e 100644 --- a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb @@ -3,14 +3,19 @@ module QA RSpec.describe 'Package', :orchestrated, :packages do describe 'Generic Repository' do - let(:package_name) { 'my_package' } - let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'generic-package-project' end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = "my_package" + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" @@ -90,14 +95,15 @@ module QA after do runner.remove_via_api! + package.remove_via_api! end it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1108' do Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) - index.click_package(package_name) + expect(index).to have_package(package.name) + index.click_package(package.name) end Page::Project::Packages::Show.perform(&:click_delete) @@ -105,7 +111,7 @@ module QA Page::Project::Packages::Index.perform do |index| aggregate_failures 'package deletion' do expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).to have_no_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb index b5b050a5dfe..4d4f981f021 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb @@ -23,6 +23,13 @@ module QA end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = package_name + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" @@ -39,6 +46,7 @@ module QA after do runner.remove_via_api! + package.remove_via_api! end it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb index 2f508d00790..7234edb46d3 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb @@ -31,6 +31,13 @@ module QA end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = package_name + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb index 97df8fedf87..49b42bd1ff6 100644 --- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb @@ -5,8 +5,7 @@ module QA describe 'npm registry' do include Runtime::Fixtures - let(:registry_scope) { project.group.sandbox.path } - let(:package_name) { "@#{registry_scope}/#{project.name}" } + let!(:registry_scope) { project.group.sandbox.path } let(:auth_token) do unless Page::Main::Menu.perform(&:signed_in?) Flow::Login.sign_in @@ -15,12 +14,23 @@ module QA Resource::PersonalAccessToken.fabricate!.token end - let(:project) do + let!(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'npm-registry-project' end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = "@#{registry_scope}/#{project.name}" + package.project = project + end + end + + after do + package.remove_via_api! + end + it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944' do uri = URI.parse(Runtime::Scenario.gitlab_address) gitlab_host_with_port = "#{uri.host}:#{uri.port}" @@ -29,7 +39,7 @@ module QA file_path: 'package.json', content: <<~JSON { - "name": "#{package_name}", + "name": "#{package.name}", "version": "1.0.0", "description": "Example package for GitLab npm registry", "publishConfig": { @@ -56,20 +66,20 @@ module QA Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) + expect(index).to have_package(package.name) - index.click_package(package_name) + index.click_package(package.name) end Page::Project::Packages::Show.perform do |show| - expect(show).to have_package_info(package_name, "1.0.0") + expect(show).to have_package_info(package.name, "1.0.0") show.click_delete end Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + expect(index).not_to have_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb index f143bc52095..c0d84d82e51 100644 --- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb @@ -6,8 +6,6 @@ module QA RSpec.describe 'Package', :orchestrated, :packages do describe 'NuGet Repository' do include Runtime::Fixtures - - let(:package_name) { "dotnetcore-#{SecureRandom.hex(8)}" } let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'nuget-package-project' @@ -15,6 +13,13 @@ module QA end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = "dotnetcore-#{SecureRandom.hex(8)}" + package.project = project + end + end + let(:another_project) do Resource::Project.fabricate_via_api! do |project| project.name = 'nuget-package-install-project' @@ -43,6 +48,7 @@ module QA after do runner.remove_via_api! another_runner.remove_via_api! + package.remove_via_api! end it 'publishes a nuget package at the project level, installs and deletes it at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do @@ -66,7 +72,7 @@ module QA script: - dotnet restore -p:Configuration=Release - dotnet build -c Release - - dotnet pack -c Release -p:PackageID=#{package_name} + - dotnet pack -c Release -p:PackageID=#{package.name} - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text - dotnet nuget push "bin/Release/*.nupkg" --source gitlab only: @@ -127,7 +133,7 @@ module QA script: - dotnet nuget locals all --clear - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text - - "dotnet add otherdotnet.csproj package #{package_name} --version 1.0.0" + - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0" only: - "#{another_project.default_branch}" tags: @@ -153,15 +159,15 @@ module QA Page::Group::Menu.perform(&:go_to_group_packages) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) - index.click_package(package_name) + expect(index).to have_package(package.name) + index.click_package(package.name) end Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + expect(index).not_to have_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb index 396863b33c4..fb29af43da6 100644 --- a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb @@ -4,15 +4,19 @@ module QA RSpec.describe 'Package', :orchestrated, :packages do describe 'PyPI Repository' do include Runtime::Fixtures - - let(:package_name) { 'mypypipackage' } - let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'pypi-package-project' end end + let(:package) do + Resource::Package.new.tap do |package| + package.name = 'mypypipackage' + package.project = project + end + end + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" @@ -87,6 +91,7 @@ module QA after do runner.remove_via_api! + package.remove_via_api! project&.remove_via_api! end @@ -94,8 +99,8 @@ module QA Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - expect(index).to have_package(package_name) - index.click_package(package_name) + expect(index).to have_package(package.name) + index.click_package(package.name) end Page::Project::Packages::Show.perform(&:click_delete) @@ -103,13 +108,13 @@ module QA Page::Project::Packages::Index.perform do |index| aggregate_failures do expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + expect(index).not_to have_package(package.name) end end end context 'Geo', :orchestrated, :geo do - it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1120' do + it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1120', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325556', type: :investigating } do QA::Runtime::Logger.debug('Visiting the secondary Geo site') QA::Flow::Login.while_signed_in(address: :geo_secondary) do @@ -127,8 +132,8 @@ module QA Page::Project::Menu.perform(&:click_packages_link) Page::Project::Packages::Index.perform do |index| - index.wait_for_package_replication(package_name) - expect(index).to have_package(package_name) + index.wait_for_package_replication(package.name) + expect(index).to have_package(package.name) end end end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb index 87bd2b76560..713b32de217 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Release' do describe 'Deploy key creation' do - it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/390' do + it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1765' do Flow::Login.sign_in key = Runtime::Key::RSA.new diff --git a/qa/qa/specs/helpers/context_selector.rb b/qa/qa/specs/helpers/context_selector.rb new file mode 100644 index 00000000000..4313f7c34dd --- /dev/null +++ b/qa/qa/specs/helpers/context_selector.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'rspec/core' + +module QA + module Specs + module Helpers + module ContextSelector + extend self + + def configure_rspec + ::RSpec.configure do |config| + config.before do |example| + if example.metadata.key?(:only) + skip('Test is not compatible with this environment or pipeline') unless ContextSelector.context_matches?(example.metadata[:only]) + elsif example.metadata.key?(:exclude) + skip('Test is excluded in this job') if ContextSelector.exclude?(example.metadata[:exclude]) + end + end + end + end + + def exclude?(*options) + return false unless Runtime::Env.ci_job_name.present? + + context_matches?(*options) + end + + def context_matches?(*options) + return false unless Runtime::Scenario.attributes[:gitlab_address] + + opts = {} + opts[:domain] = '.+' + opts[:tld] = '.com' + + uri = URI(Runtime::Scenario.gitlab_address) + + options.each do |option| + opts[:domain] = 'gitlab' if option == :production + + next unless option.is_a?(Hash) + + if option[:pipeline].present? && Runtime::Env.ci_project_name.present? + return pipeline_matches?(option[:pipeline]) + + elsif option[:job].present? + return job_matches?(option[:job]) + + elsif option[:subdomain].present? + opts.merge!(option) + + opts[:subdomain] = case option[:subdomain] + when Array + "(#{option[:subdomain].join("|")})." + when Regexp + option[:subdomain] + else + "(#{option[:subdomain]})." + end + end + end + + uri.host.match?(/^#{opts[:subdomain]}#{opts[:domain]}#{opts[:tld]}$/) + end + + alias_method :dot_com?, :context_matches? + + def job_matches?(job_patterns) + Array(job_patterns).any? do |job| + pattern = job.is_a?(Regexp) ? job : Regexp.new(job) + pattern = Regexp.new(pattern.source, pattern.options | Regexp::IGNORECASE) + pattern =~ Runtime::Env.ci_job_name + end + end + + def pipeline_matches?(pipeline_to_run_in) + Array(pipeline_to_run_in).any? { |pipeline| pipeline.to_s.casecmp?(pipeline_from_project_name(Runtime::Env.ci_project_name)) } + end + + def pipeline_from_project_name(project_name) + project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : project_name + end + end + end + end +end diff --git a/qa/qa/specs/helpers/quarantine.rb b/qa/qa/specs/helpers/quarantine.rb index d365819057e..15b4ed8336b 100644 --- a/qa/qa/specs/helpers/quarantine.rb +++ b/qa/qa/specs/helpers/quarantine.rb @@ -6,22 +6,18 @@ module QA module Specs module Helpers module Quarantine - include RSpec::Core::Pending + include ::RSpec::Core::Pending extend self def configure_rspec - RSpec.configure do |config| + ::RSpec.configure do |config| config.before(:context, :quarantine) do Quarantine.skip_or_run_quarantined_contexts(config.inclusion_filter.rules, self.class) end config.before do |example| Quarantine.skip_or_run_quarantined_tests_or_contexts(config.inclusion_filter.rules, example) - - if example.metadata.key?(:only) - skip('Test is not compatible with this environment or pipeline') unless Runtime::Env.context_matches?(example.metadata[:only]) - end end end end @@ -52,10 +48,10 @@ module QA if example.metadata.key?(:quarantine) quarantine_tag = example.metadata[:quarantine] - if quarantine_tag&.is_a?(Hash) && quarantine_tag&.key?(:only) + if quarantine_tag.is_a?(Hash) && quarantine_tag&.key?(:only) # If the :quarantine hash contains :only, we respect that. # For instance `quarantine: { only: { subdomain: :staging } }` will only quarantine the test when it runs against staging. - return unless Runtime::Env.context_matches?(quarantine_tag[:only]) + return unless ContextSelector.context_matches?(quarantine_tag[:only]) end skip(quarantine_message(quarantine_tag)) diff --git a/qa/qa/specs/helpers/rspec.rb b/qa/qa/specs/helpers/rspec.rb new file mode 100644 index 00000000000..f49e556b0d9 --- /dev/null +++ b/qa/qa/specs/helpers/rspec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'rspec/core' + +module QA + module Specs + module Helpers + module RSpec + # We need a reporter for internal tests that's different from the reporter for + # external tests otherwise the results will be mixed up. We don't care about + # most reporting, but we do want to know if a test fails + class RaiseOnFailuresReporter < ::RSpec::Core::NullReporter + def self.example_failed(example) + raise example.exception + end + end + + # We use an example group wrapper to prevent the state of internal tests + # expanding into the global state + # See: https://github.com/rspec/rspec-core/issues/2603 + def describe_successfully(*args, &describe_body) + example_group = RSpec.describe(*args, &describe_body) + ran_successfully = example_group.run RaiseOnFailuresReporter + expect(ran_successfully).to eq true + example_group + end + end + end + end +end diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb index 04eaa02bda5..ff690962db8 100644 --- a/qa/qa/specs/runner.rb +++ b/qa/qa/specs/runner.rb @@ -44,7 +44,7 @@ module QA tags_for_rspec.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled? - tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Runtime::Env.dot_com? + tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Specs::Helpers::ContextSelector.dot_com? QA::Runtime::Env.supported_features.each_key do |key| tags_for_rspec.push(%W[--tag ~requires_#{key}]) unless QA::Runtime::Env.can_test? key |