diff --git a/qa/qa/ee.rb b/qa/qa/ee.rb index e6d0c1040a786b256e0f76de86bc5c23036c4e26..94b73753902c3c7a0b100502838558c7994f6077 100644 --- a/qa/qa/ee.rb +++ b/qa/qa/ee.rb @@ -153,6 +153,7 @@ module Metrics module Pipeline autoload :Show, 'qa/ee/page/project/pipeline/show' + autoload :Index, 'qa/ee/page/project/pipeline/index' end module Secure @@ -174,6 +175,10 @@ module Packages module Snippet autoload :Index, 'qa/ee/page/project/snippet/index' end + + module Job + autoload :Show, 'qa/ee/page/project/job/show' + end end module MergeRequest diff --git a/qa/qa/ee/page/project/job/show.rb b/qa/qa/ee/page/project/job/show.rb new file mode 100644 index 0000000000000000000000000000000000000000..0613dbe2ceb8dfed423b1e4d40e881a70a2eaa8b --- /dev/null +++ b/qa/qa/ee/page/project/job/show.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module QA + module EE + module Page + module Project + module Job + module Show + extend QA::Page::PageConcern + + # These wait times cover both the time for pipeline job to complete and time for log and artifact to Geo replicate, so the max duration has been doubled + def wait_for_job_log_replication + QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_job_log_replication]) + wait_until(max_duration: 2 * Runtime::Geo.max_file_replication_time) do + has_job_log? + end + end + + def wait_for_job_artifact_replication + QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_job_artifact_replication]) + wait_until(max_duration: 2 * Runtime::Geo.max_file_replication_time) do + has_browse_button? + end + end + end + end + end + end + end +end diff --git a/qa/qa/ee/page/project/pipeline/index.rb b/qa/qa/ee/page/project/pipeline/index.rb new file mode 100644 index 0000000000000000000000000000000000000000..3c488900f1d98c3d18a8218ec699a40496383c55 --- /dev/null +++ b/qa/qa/ee/page/project/pipeline/index.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module QA + module EE + module Page + module Project + module Pipeline + module Index + extend QA::Page::PageConcern + + def wait_for_latest_pipeline_replication + QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_latest_pipeline_replication]) + wait_until(max_duration: Runtime::Geo.max_file_replication_time) do + within_element_by_index(:pipeline_commit_status, 0) { has_text?('passed') || has_text?('failed') } + end + end + end + end + end + end + end +end diff --git a/qa/qa/ee/page/project/pipeline/show.rb b/qa/qa/ee/page/project/pipeline/show.rb index 09c4ce50b674f9538bda42803bbda9336029145e..b75c2a7c8b732285f4de526527f8d57cc1f27aa1 100644 --- a/qa/qa/ee/page/project/pipeline/show.rb +++ b/qa/qa/ee/page/project/pipeline/show.rb @@ -34,6 +34,13 @@ def click_on_licenses def has_license_count_of?(count) find_element(:licenses_counter).has_content?(count) end + + def wait_for_pipeline_job_replication(name) + QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_pipeline_job_replication]) + wait_until(max_duration: Runtime::Geo.max_file_replication_time) do + has_job?(name) + end + end end end end diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb index 6a657b4ab390682ea82de945f4bd8ccf43a753e5..2ecb27e05b2ccf93860b45601817a5445745777e 100644 --- a/qa/qa/page/project/job/show.rb +++ b/qa/qa/page/project/job/show.rb @@ -58,6 +58,10 @@ def retry! click_element :retry_button end + def has_job_log? + has_element? :job_log_content + end + private def loaded?(wait: 60) @@ -70,3 +74,5 @@ def loaded?(wait: 60) end end end + +QA::Page::Project::Job::Show.prepend_if_ee('QA::EE::Page::Project::Job::Show') diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb index b2ecbb2e98812ef2707d159678ea22615658584f..aff2378330ab57c6af81b48c5649b959843efe12 100644 --- a/qa/qa/page/project/pipeline/index.rb +++ b/qa/qa/page/project/pipeline/index.rb @@ -57,3 +57,5 @@ def click_run_pipeline_button end end end + +QA::Page::Project::Pipeline::Index.prepend_if_ee('QA::EE::Page::Project::Pipeline::Index') diff --git a/qa/qa/specs/features/ee/browser_ui/geo/geo_replication_ci_job_log_artifacts_spec.rb b/qa/qa/specs/features/ee/browser_ui/geo/geo_replication_ci_job_log_artifacts_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c8931ea6aa3d6c2cd70db38346bde6c0fb1a593a --- /dev/null +++ b/qa/qa/specs/features/ee/browser_ui/geo/geo_replication_ci_job_log_artifacts_spec.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Geo', :orchestrated, :runner, :requires_admin, :geo do + describe 'CI job' do + before(:all) do + @file_name = 'geo_artifact.txt' + @directory_name = 'geo_artifacts' + @pipeline_job_name = 'test-artifacts' + executor = "qa-runner-#{Time.now.to_i}" + + @project = Resource::Project.fabricate_via_api! do |project| + project.name = 'geo-project-with-artifacts' + end + + @runner = Resource::Runner.fabricate! do |runner| + runner.project = @project + runner.name = executor + runner.tags = [executor] + end + + 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: <<~YAML + test-artifacts: + tags: + - '#{executor}' + artifacts: + paths: + - '#{@directory_name}' + expire_in: 1000 seconds + script: + - | + mkdir #{@directory_name} + echo "CONTENTS" > #{@directory_name}/#{@file_name} + YAML + } + ] + ) + end + end + + after(:all) do + @runner.remove_via_api! + end + + # Test code is based on qa/specs/features/ee/browser_ui/4_verify/locked_artifacts_spec.rb + it 'replicates the job log to the secondary Geo site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/908' do + Runtime::Logger.debug('Visiting the secondary Geo site') + + Flow::Login.while_signed_in(address: :geo_secondary) do + EE::Page::Main::Banner.perform do |banner| + expect(banner).to have_secondary_read_only_banner + end + + Page::Main::Menu.perform(&:go_to_projects) + + Page::Dashboard::Projects.perform do |dashboard| + dashboard.wait_for_project_replication(@project.name) + dashboard.go_to_project(@project.name) + end + + Page::Project::Menu.perform(&:click_ci_cd_pipelines) + Page::Project::Pipeline::Index.perform do |index| + index.wait_for_latest_pipeline_replication + index.click_on_latest_pipeline + end + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.wait_for_pipeline_job_replication(@pipeline_job_name) + pipeline.click_job(@pipeline_job_name) + end + + Page::Project::Job::Show.perform do |pipeline_job| + pipeline_job.wait_for_job_log_replication + expect(pipeline_job).to have_job_log + end + end + end + + it 'replicates the job artifact to the secondary Geo site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/186' do + Runtime::Logger.debug('Visiting the secondary Geo site') + + Flow::Login.while_signed_in(address: :geo_secondary) do + EE::Page::Main::Banner.perform do |banner| + expect(banner).to have_secondary_read_only_banner + end + + Page::Main::Menu.perform(&:go_to_projects) + + Page::Dashboard::Projects.perform do |dashboard| + dashboard.wait_for_project_replication(@project.name) + dashboard.go_to_project(@project.name) + end + + Page::Project::Menu.perform(&:click_ci_cd_pipelines) + Page::Project::Pipeline::Index.perform do |index| + index.wait_for_latest_pipeline_replication + index.click_on_latest_pipeline + end + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.wait_for_pipeline_job_replication(@pipeline_job_name) + pipeline.click_job(@pipeline_job_name) + end + + Page::Project::Job::Show.perform do |pipeline_job| + pipeline_job.wait_for_job_artifact_replication + pipeline_job.click_browse_button + end + + EE::Page::Project::Artifact::Show.perform do |artifact| + artifact.go_to_directory(@directory_name) + expect(artifact).to have_content(@file_name) + end + end + end + end + end +end