diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json index 65091487c93e8053edaa3a8f67cc6e640de989f9..1274df4b505b40575410d9b6827e25f26cf56d96 100644 --- a/app/assets/javascripts/editor/schema/ci.json +++ b/app/assets/javascripts/editor/schema/ci.json @@ -2084,6 +2084,10 @@ "publish": { "description": "A path to a directory that contains the files to be published with Pages", "type": "string" + }, + "pages_path_prefix": { + "description": "The path prefix identifier for this version of pages. Allows creation of multiple versions of the same site with different path prefixes", + "type": "string" } }, "oneOf": [ diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 73594448192271630dbe21bda375b5004eaa8bfe..107f3c5987a68c1847f645adf6bc24d64786442c 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -391,6 +391,9 @@ def pages_generator? name == 'pages' end + # overridden on EE + def pages_path_prefix; end + def runnable? true end diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 403f645392c237c7b2020c64e3d6cda3768ff0ad..7d25e4cff4d66a42dbcaf4fc6bfbf15fdbae1c40 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -2,6 +2,8 @@ module Projects class UpdatePagesService < BaseService + include Gitlab::Utils::StrongMemoize + # old deployment can be cached by pages daemon # so we need to give pages daemon some time update cache # 10 minutes is enough, but 30 feels safer @@ -18,9 +20,7 @@ def initialize(project, build) def execute register_attempt - # Create status notifying the deployment of pages - @commit_status = build_commit_status - ::Ci::Pipelines::AddJobService.new(@build.pipeline).execute!(@commit_status) do |job| + ::Ci::Pipelines::AddJobService.new(@build.pipeline).execute!(commit_status) do |job| job.enqueue! job.run! end @@ -47,7 +47,7 @@ def execute private def success - @commit_status.success + commit_status.success @project.mark_pages_as_deployed publish_deployed_event super @@ -56,15 +56,14 @@ def success def error(message) register_failure log_error("Projects::UpdatePagesService: #{message}") - @commit_status.allow_failure = !deployment_update.latest? - @commit_status.description = message - @commit_status.drop(:script_failure) + commit_status.allow_failure = !deployment_update.latest? + commit_status.description = message + commit_status.drop(:script_failure) super end - def build_commit_status - stage = create_stage - + # Create status notifying the deployment of pages + def commit_status GenericCommitStatus.new( user: build.user, ci_stage: stage, @@ -73,26 +72,22 @@ def build_commit_status stage_idx: stage.position ) end + strong_memoize_attr :commit_status # rubocop: disable Performance/ActiveRecordSubtransactionMethods - def create_stage + def stage build.pipeline.stages.safe_find_or_create_by(name: 'deploy', pipeline_id: build.pipeline.id) do |stage| stage.position = GenericCommitStatus::EXTERNAL_STAGE_IDX stage.project = build.project end end + strong_memoize_attr :commit_status # rubocop: enable Performance/ActiveRecordSubtransactionMethods def create_pages_deployment(artifacts_path, build) - sha256 = build.job_artifacts_archive.file_sha256 File.open(artifacts_path) do |file| - deployment = project.pages_deployments.create!( - file: file, - file_count: deployment_update.entries_count, - file_sha256: sha256, - ci_build_id: build.id, - root_directory: build.options[:publish] - ) + attributes = pages_deployment_attributes(file, build) + deployment = project.pages_deployments.create!(**attributes) break if deployment.size != file.size || deployment.file.size != file.size @@ -100,6 +95,17 @@ def create_pages_deployment(artifacts_path, build) end end + # overridden on EE + def pages_deployment_attributes(file, build) + { + file: file, + file_count: deployment_update.entries_count, + file_sha256: build.job_artifacts_archive.file_sha256, + ci_build_id: build.id, + root_directory: build.options[:publish] + } + end + def update_project_pages_deployment(deployment) project.update_pages_deployment!(deployment) DestroyPagesDeploymentsWorker.perform_in( @@ -144,3 +150,5 @@ def publish_deployed_event end end end + +::Projects::UpdatePagesService.prepend_mod diff --git a/ee/app/models/ee/ci/build.rb b/ee/app/models/ee/ci/build.rb index b28c303c17d68c3f903307b24397e77fdd578242..be8690467c4854b0daad65dddac0bc7a1aabb5db 100644 --- a/ee/app/models/ee/ci/build.rb +++ b/ee/app/models/ee/ci/build.rb @@ -9,6 +9,7 @@ module Ci module Build extend ActiveSupport::Concern extend ::Gitlab::Utils::Override + include ::Gitlab::Utils::StrongMemoize VALIDATE_SCHEMA_VARIABLE_NAME = 'VALIDATE_SCHEMA' LICENSED_PARSER_FEATURES = { @@ -213,6 +214,16 @@ def resource_parent project end + override :pages_path_prefix + def pages_path_prefix + return unless pages_generator? + return unless options[:pages_path_prefix].present? + return unless ::Gitlab::Pages.multiple_versions_enabled_for?(project) + + ExpandVariables.expand(options[:pages_path_prefix], -> { simple_variables }) + end + strong_memoize_attr :pages_path_prefix + private def variables_hash diff --git a/ee/app/services/ee/projects/update_pages_service.rb b/ee/app/services/ee/projects/update_pages_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..b6119f6b3f1607bdc032813077811b23334da8bf --- /dev/null +++ b/ee/app/services/ee/projects/update_pages_service.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module EE + module Projects + module UpdatePagesService + extend ::Gitlab::Utils::Override + + override :pages_deployment_attributes + def pages_deployment_attributes(file, build) + return super unless ::Gitlab::Pages.multiple_versions_enabled_for?(build.project) + + super.merge(path_prefix: build.pages_path_prefix) + end + end + end +end diff --git a/ee/lib/ee/gitlab/ci/config/entry/job.rb b/ee/lib/ee/gitlab/ci/config/entry/job.rb index 965e9f6ad84334d4613f145f814b7c78d032e075..288e42aa29ed3a2613f1cbe0441a37646fcba269 100644 --- a/ee/lib/ee/gitlab/ci/config/entry/job.rb +++ b/ee/lib/ee/gitlab/ci/config/entry/job.rb @@ -9,8 +9,10 @@ module Job extend ActiveSupport::Concern extend ::Gitlab::Utils::Override + EE_ALLOWED_KEYS = %i[dast_configuration secrets pages_path_prefix].freeze + prepended do - attributes :dast_configuration, :secrets + attributes :dast_configuration, :secrets, :pages_path_prefix entry :dast_configuration, ::Gitlab::Ci::Config::Entry::DastConfiguration, description: 'DAST configuration for this job', @@ -20,13 +22,18 @@ module Job description: 'Configured secrets for this job', inherit: false, metadata: { composable_class: ::Gitlab::Ci::Config::Entry::Secret } - end - - EE_ALLOWED_KEYS = %i[dast_configuration secrets].freeze - override :value - def value - super.merge({ dast_configuration: dast_configuration_value, secrets: secrets_value }.compact) + entry :pages_path_prefix, ::Gitlab::Ci::Config::Entry::PagesPathPrefix, + inherit: false, + description: \ + 'Pages path prefix identifier. ' \ + 'This allows to create multiple versions of the same site with different path prefixes' + + validations do + validates :pages_path_prefix, + absence: { message: "can only be used within a `pages` job" }, + unless: -> { pages_job? } + end end class_methods do @@ -37,6 +44,15 @@ def allowed_keys super + EE_ALLOWED_KEYS end end + + override :value + def value + super.merge({ + dast_configuration: dast_configuration_value, + secrets: secrets_value, + pages_path_prefix: pages_path_prefix + }.compact) + end end end end diff --git a/ee/lib/ee/gitlab/ci/yaml_processor/result.rb b/ee/lib/ee/gitlab/ci/yaml_processor/result.rb index e2daac1e7b6ac266f04dbc4b30288c84b87d97fb..6835c7a4138dca7cc50c76e0fe61a484de3098dd 100644 --- a/ee/lib/ee/gitlab/ci/yaml_processor/result.rb +++ b/ee/lib/ee/gitlab/ci/yaml_processor/result.rb @@ -15,7 +15,10 @@ def build_attributes(name) super.deep_merge( { - options: { dast_configuration: job[:dast_configuration] }.compact, + options: { + dast_configuration: job[:dast_configuration], + pages_path_prefix: job[:pages_path_prefix] + }.compact, secrets: job[:secrets] }.compact ) diff --git a/ee/lib/gitlab/ci/config/entry/pages_path_prefix.rb b/ee/lib/gitlab/ci/config/entry/pages_path_prefix.rb new file mode 100644 index 0000000000000000000000000000000000000000..81bf87efb522eba0fdbebd03d3e5a4bee5b14022 --- /dev/null +++ b/ee/lib/gitlab/ci/config/entry/pages_path_prefix.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + class Config + module Entry + ## + # Entry that represents the pages path prefix + # + class PagesPathPrefix < ::Gitlab::Config::Entry::Node + include ::Gitlab::Config::Entry::Validatable + + validations do + validates :config, type: String + end + end + end + end + end +end diff --git a/ee/spec/lib/gitlab/ci/config/entry/pages_path_prefix_spec.rb b/ee/spec/lib/gitlab/ci/config/entry/pages_path_prefix_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f63e303b199edbe385d04492ddd269fb585e4876 --- /dev/null +++ b/ee/spec/lib/gitlab/ci/config/entry/pages_path_prefix_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Config::Entry::PagesPathPrefix, :aggregate_failures, feature_category: :pages do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when config value is correct' do + let(:config) { 'prefix' } + + describe '#config' do + it 'returns the given value' do + expect(entry.config).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when the value has a wrong type' do + let(:config) { { test: true } } + + it 'reports an error' do + expect(entry.errors).to include 'pages path prefix config should be a string' + end + end + end +end diff --git a/ee/spec/models/ci/build_spec.rb b/ee/spec/models/ci/build_spec.rb index ae68d2175a66398a0a9cc5c062f143aa264380cb..162a7875d29aa30ab62c738c15ccf4566f0fbe3a 100644 --- a/ee/spec/models/ci/build_spec.rb +++ b/ee/spec/models/ci/build_spec.rb @@ -915,6 +915,36 @@ end end + describe '#pages_path_prefix', feature_category: :pages do + where(:result, :option, :pages_generator, :multiple_versions_enabled) do + nil | nil | false | false + nil | nil | false | true + nil | nil | true | false + nil | nil | true | true + nil | '' | true | true + 'foo' | 'foo' | true | true + 'master' | '$CI_COMMIT_BRANCH' | true | true + end + + with_them do + before do + job.options[:pages_path_prefix] = option + + allow(job) + .to receive(:pages_generator?) + .and_return(pages_generator) + + allow(::Gitlab::Pages) + .to receive(:multiple_versions_enabled_for?) + .and_return(multiple_versions_enabled) + end + + subject { job.pages_path_prefix } + + it { is_expected.to eq(result) } + end + end + context 'with loose foreign keys for partitioned tables' do before do create(:security_scan, build: job) diff --git a/ee/spec/services/ee/projects/update_pages_service_spec.rb b/ee/spec/services/ee/projects/update_pages_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..571fe122fd2b75d77887898a6f1c915e1de14ec5 --- /dev/null +++ b/ee/spec/services/ee/projects/update_pages_service_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::UpdatePagesService, feature_category: :pages do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:build) { create_pages_build_and_artifacts(project) } + + subject(:service) { described_class.new(project, build) } + + before do + stub_pages_setting(enabled: true) + end + + context 'when pages_multiple_versions is not enabled for project' do + it 'does not save the given path prefix' do + expect(::Gitlab::Pages) + .to receive(:multiple_versions_enabled_for?) + .with(build.project) + .and_return(false) + + expect do + expect(service.execute[:status]).to eq(:success) + end.to change { project.pages_deployments.count }.by(1) + + deployment = project.pages_deployments.last + + expect(deployment.path_prefix).to be_nil + end + end + + context 'when pages_multiple_versions is enabled for project' do + it 'saves the given path prefix' do + expect(::Gitlab::Pages) + .to receive(:multiple_versions_enabled_for?) + .with(build.project) + .and_return(true) + .twice # it's called from within the build.pages_path_prefix as well + + expect do + expect(service.execute[:status]).to eq(:success) + end.to change { project.pages_deployments.count }.by(1) + + deployment = project.pages_deployments.last + + expect(deployment.path_prefix).to eq('__pages__prefix__') + end + end + + def create_pages_build_and_artifacts(project) + build = create( + :ci_build, + name: 'pages', + pipeline: create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha), + ref: 'HEAD', + options: { pages_path_prefix: '__pages__prefix__' }) + + create( + :ci_job_artifact, + :correct_checksum, + file: fixture_file_upload('spec/fixtures/pages.zip'), + job: build) + + create( + :ci_job_artifact, + file_type: :metadata, + file_format: :gzip, + file: fixture_file_upload('spec/fixtures/pages.zip.meta'), + job: build) + + build.reload + end +end diff --git a/lib/gitlab/pages.rb b/lib/gitlab/pages.rb index 4e0e5102becbcc8ded9f0e9a91436ab2915c6eca..367fe7639da09a73d9d6d8b7af8eb18588cb76bc 100644 --- a/lib/gitlab/pages.rb +++ b/lib/gitlab/pages.rb @@ -23,6 +23,14 @@ def access_control_is_forced? ::Gitlab.config.pages.access_control && ::Gitlab::CurrentSettings.current_application_settings.force_pages_access_control end + + def multiple_versions_enabled_for?(project) + return false if project.blank? + + ::Feature.enabled?(:pages_multiple_versions_setting, project) && + project.licensed_feature_available?(:pages_multiple_versions) && + project.project_setting.pages_multiple_versions_enabled + end end end end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index 4be7c11fab0c69d72163e585140ca3f416779d92..980ea2e2765b27b3b2eda035e525db5d0bcd3f12 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::Entry::Job, feature_category: :pipeline_composition do + using RSpec::Parameterized::TableSyntax + let(:entry) { described_class.new(config, name: :rspec) } it_behaves_like 'with inheritable CI config' do @@ -696,8 +698,6 @@ end context 'with workflow rules' do - using RSpec::Parameterized::TableSyntax - where(:name, :has_workflow_rules?, :only, :rules, :result) do "uses default only" | false | nil | nil | { refs: %w[branches tags] } "uses user only" | false | %w[branches] | nil | { refs: %w[branches] } @@ -739,6 +739,20 @@ end end + describe '#pages_job?', :aggregate_failures, feature_category: :pages do + where(:name, :result) do + :pages | true + :'pages:staging' | false + :'something:pages:else' | false + end + + with_them do + subject { described_class.new({}, name: name).pages_job? } + + it { is_expected.to eq(result) } + end + end + context 'when composed' do before do entry.compose! diff --git a/spec/lib/gitlab/pages_spec.rb b/spec/lib/gitlab/pages_spec.rb index 9f85efd56e6c607faeb150547fa7652642b608d1..20b7821f4d2942260d0adfd0befb39b3c6208924 100644 --- a/spec/lib/gitlab/pages_spec.rb +++ b/spec/lib/gitlab/pages_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Pages do +RSpec.describe Gitlab::Pages, feature_category: :pages do using RSpec::Parameterized::TableSyntax let(:pages_secret) { SecureRandom.random_bytes(Gitlab::Pages::SECRET_LENGTH) } @@ -48,4 +48,42 @@ it { is_expected.to eq(result) } end end + + describe '.multiple_versions_enabled_for?' do + context 'when project is nil' do + it 'returns false' do + expect(described_class.multiple_versions_enabled_for?(nil)).to eq(false) + end + end + + context 'when a project is given' do + let_it_be(:project) { create(:project) } + + where(:setting, :feature_flag, :license, :result) do + false | false | false | false + false | false | true | false + false | true | false | false + false | true | true | false + true | false | false | false + true | false | true | false + true | true | false | false + true | true | true | true + end + + with_them do + let_it_be(:project) { create(:project) } + + subject { described_class.multiple_versions_enabled_for?(project) } + + before do + stub_licensed_features(pages_multiple_versions: license) + stub_feature_flags(pages_multiple_versions_setting: feature_flag) + project.project_setting.update!(pages_multiple_versions_enabled: setting) + end + + # this feature is only available in EE + it { is_expected.to eq(result && Gitlab.ee?) } + end + end + end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index f17cbd821c5ff547a037793403c3cf0eacb3a3ba..b95dec7195ffaca56eb39f31c819eccaf235eb3e 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_default: :keep do + using RSpec::Parameterized::TableSyntax include Ci::TemplateHelpers include AfterNextHelpers @@ -1493,8 +1494,6 @@ end describe 'state transition metrics' do - using RSpec::Parameterized::TableSyntax - subject { build.send(event) } where(:state, :report_count, :trait) do @@ -2129,8 +2128,6 @@ end describe '#ref_slug' do - using RSpec::Parameterized::TableSyntax - where(:ref, :slug) do 'master' | 'master' '1-foo' | '1-foo' @@ -4025,73 +4022,61 @@ def run_job_without_exception end end - describe 'pages deployments' do - let_it_be(:build, reload: true) { create(:ci_build, pipeline: pipeline, user: user) } + describe '#pages_generator?', feature_category: :pages do + where(:name, :enabled, :result) do + 'foo' | false | false + 'pages' | false | false + 'pages:preview' | true | false + 'pages' | true | true + end - context 'when job is "pages"' do + with_them do before do - build.name = 'pages' + stub_pages_setting(enabled: enabled) + build.update!(name: name) end - context 'when pages are enabled' do - before do - allow(Gitlab.config.pages).to receive_messages(enabled: true) - end - - it 'is marked as pages generator' do - expect(build).to be_pages_generator - end - - context 'job succeeds' do - it "calls pages worker" do - expect(PagesWorker).to receive(:perform_async).with(:deploy, build.id) + subject { build.pages_generator? } - build.success! - end - end + it { is_expected.to eq(result) } + end + end - context 'job fails' do - it "does not call pages worker" do - expect(PagesWorker).not_to receive(:perform_async) + describe 'pages deployments', feature_category: :pages do + let_it_be(:build, reload: true) { create(:ci_build, name: 'pages', pipeline: pipeline, user: user) } - build.drop! - end - end + context 'when pages are enabled' do + before do + stub_pages_setting(enabled: true) end - context 'when pages are disabled' do - before do - allow(Gitlab.config.pages).to receive_messages(enabled: false) - end + context 'and job succeeds' do + it "calls pages worker" do + expect(PagesWorker).to receive(:perform_async).with(:deploy, build.id) - it 'is not marked as pages generator' do - expect(build).not_to be_pages_generator + build.success! end + end - context 'job succeeds' do - it "does not call pages worker" do - expect(PagesWorker).not_to receive(:perform_async) + context 'and job fails' do + it "does not call pages worker" do + expect(PagesWorker).not_to receive(:perform_async) - build.success! - end + build.drop! end end end - context 'when job is not "pages"' do + context 'when pages are disabled' do before do - build.name = 'other-job' - end - - it 'is not marked as pages generator' do - expect(build).not_to be_pages_generator + stub_pages_setting(enabled: false) end - context 'job succeeds' do + context 'and job succeeds' do it "does not call pages worker" do expect(PagesWorker).not_to receive(:perform_async) - build.success + build.success! end end end diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index a113f3506e13cc5eb4ccc53396b4321a21eac16f..a250be0c94f6e4377a5c37ea75c248961c140984 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -20,13 +20,45 @@ let(:custom_root_file_metadata) { "spec/fixtures/pages_with_custom_root.zip.meta" } let(:metadata) { fixture_file_upload(metadata_filename) if File.exist?(metadata_filename) } - subject { described_class.new(project, build) } + subject(:service) { described_class.new(project, build) } + + RSpec.shared_examples 'pages size limit is' do |size_limit| + context "when size is below the limit" do + before do + allow(metadata).to receive(:total_size).and_return(size_limit - 1.megabyte) + allow(metadata).to receive(:entries).and_return([]) + end + + it 'updates pages correctly' do + subject.execute + + deploy_status = GenericCommitStatus.last + expect(deploy_status.description).not_to be_present + expect(project.pages_metadatum).to be_deployed + end + end + + context "when size is above the limit" do + before do + allow(metadata).to receive(:total_size).and_return(size_limit + 1.megabyte) + allow(metadata).to receive(:entries).and_return([]) + end + + it 'limits the maximum size of gitlab pages' do + subject.execute + + deploy_status = GenericCommitStatus.last + expect(deploy_status.description).to match(/artifacts for pages are too large/) + expect(deploy_status).to be_script_failure + end + end + end context 'when a deploy stage already exists', :aggregate_failures do let!(:stage) { create(:ci_stage, name: 'deploy', pipeline: pipeline) } it 'assigns the deploy stage' do - expect { subject.execute } + expect { service.execute } .to change(GenericCommitStatus, :count).by(1) .and change(Ci::Stage.where(name: 'deploy'), :count).by(0) @@ -41,7 +73,7 @@ context 'when a deploy stage does not exists' do it 'assigns the deploy stage' do - expect { subject.execute } + expect { service.execute } .to change(GenericCommitStatus, :count).by(1) .and change(Ci::Stage.where(name: 'deploy'), :count).by(1) @@ -64,7 +96,7 @@ end it "doesn't delete artifacts after deploying" do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) expect(project.pages_metadatum).to be_deployed expect(build.artifacts?).to eq(true) @@ -72,7 +104,7 @@ it 'succeeds' do expect(project.pages_deployed?).to be_falsey - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) expect(project.pages_metadatum).to be_deployed expect(project.pages_deployed?).to be_truthy end @@ -84,12 +116,12 @@ root_namespace_id: project.root_namespace.id } - expect { subject.execute }.to publish_event(Pages::PageDeployedEvent).with(expected_data) + expect { service.execute }.to publish_event(Pages::PageDeployedEvent).with(expected_data) end it 'creates pages_deployment and saves it in the metadata' do expect do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) end.to change { project.pages_deployments.count }.by(1) deployment = project.pages_deployments.last @@ -108,7 +140,7 @@ project.reload expect do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) end.to change { project.pages_deployments.count }.by(1) expect(project.pages_metadatum.reload.pages_deployment).to eq(project.pages_deployments.last) @@ -127,12 +159,12 @@ ) ) - execute + service.execute end it 'removes older deployments', :sidekiq_inline do expect do - execute + service.execute end.not_to change { PagesDeployment.count } # it creates one and deletes one expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil @@ -144,7 +176,7 @@ let(:metadata_filename) { empty_metadata_filename } it 'returns an error' do - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") end @@ -158,7 +190,7 @@ let(:options) { { publish: 'foo' } } it 'creates pages_deployment and saves it in the metadata' do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) deployment = project.pages_deployments.last expect(deployment.root_directory).to eq(options[:publish]) @@ -169,7 +201,7 @@ let(:options) { { publish: 'bar' } } it 'returns an error' do - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") end @@ -181,7 +213,7 @@ let(:metadata_filename) { "spec/fixtures/pages.zip.meta" } it 'returns an error' do - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") end @@ -190,13 +222,13 @@ it 'limits pages size' do stub_application_setting(max_pages_size: 1) - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) end it 'limits pages file count' do create(:plan_limits, :default_plan, pages_file_entries: 2) - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) expect(GenericCommitStatus.last.description).to eq("pages site contains 3 file entries, while limit is set to 2") end @@ -209,9 +241,11 @@ end it 'raises an error' do - expect { execute }.to raise_error(SocketError) + expect { service.execute }.to raise_error(SocketError) build.reload + + deploy_status = GenericCommitStatus.last expect(deploy_status).to be_failed expect(project.pages_metadatum).not_to be_deployed end @@ -223,9 +257,11 @@ end it 'does not raise an error as failed job' do - execute + service.execute build.reload + + deploy_status = GenericCommitStatus.last expect(deploy_status).to be_failed expect(project.pages_metadatum).not_to be_deployed end @@ -234,7 +270,7 @@ context 'with background jobs running', :sidekiq_inline do it 'succeeds' do expect(project.pages_deployed?).to be_falsey - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) end end @@ -249,7 +285,7 @@ shared_examples 'successfully deploys' do it 'succeeds' do expect do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) end.to change { project.pages_deployments.count }.by(1) deployment = project.pages_deployments.last @@ -261,7 +297,7 @@ context 'when old deployment present' do before do - old_build = create(:ci_build, pipeline: old_pipeline, ref: 'HEAD') + old_build = create(:ci_build, name: 'pages', pipeline: old_pipeline, ref: 'HEAD') old_deployment = create(:pages_deployment, ci_build: old_build, project: project) project.update_pages_deployment!(old_deployment) end @@ -272,15 +308,16 @@ context 'when newer deployment present' do before do new_pipeline = create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) - new_build = create(:ci_build, pipeline: new_pipeline, ref: 'HEAD') + new_build = create(:ci_build, name: 'pages', pipeline: new_pipeline, ref: 'HEAD') new_deployment = create(:pages_deployment, ci_build: new_build, project: project) project.update_pages_deployment!(new_deployment) end it 'fails with outdated reference message' do - expect(execute).to eq(:error) + expect(service.execute[:status]).to eq(:error) expect(project.reload.pages_metadatum).not_to be_deployed + deploy_status = GenericCommitStatus.last expect(deploy_status).to be_failed expect(deploy_status.description).to eq('build SHA is outdated for this ref') end @@ -294,7 +331,7 @@ .and_return(file.size + 1) end - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) expect(GenericCommitStatus.last.description).to eq('The uploaded artifact size does not match the expected value') project.pages_metadatum.reload @@ -318,18 +355,18 @@ it 'fails with exception raised' do expect do - execute + service.execute end.to raise_error("Validation failed: File sha256 can't be blank") end end it 'fails if no artifacts' do - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) end it 'fails for invalid archive' do create(:ci_job_artifact, :archive, file: invalid_file, job: build) - expect(execute).not_to eq(:success) + expect(service.execute[:status]).not_to eq(:success) end describe 'maximum pages artifacts size' do @@ -383,21 +420,13 @@ end it 'marks older pages:deploy jobs retried' do - expect(execute).to eq(:success) + expect(service.execute[:status]).to eq(:success) expect(older_deploy_job.reload).to be_retried + + deploy_status = GenericCommitStatus.last expect(deploy_status.ci_stage).to eq(stage) expect(deploy_status.stage_idx).to eq(stage.position) end end - - private - - def deploy_status - GenericCommitStatus.where(name: 'pages:deploy').last - end - - def execute - subject.execute[:status] - end end diff --git a/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb b/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb deleted file mode 100644 index d9e906ebb75d8f31efc17cc43bd37315e7362113..0000000000000000000000000000000000000000 --- a/spec/support/shared_examples/services/pages_size_limit_shared_examples.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_examples 'pages size limit is' do |size_limit| - context "when size is below the limit" do - before do - allow(metadata).to receive(:total_size).and_return(size_limit - 1.megabyte) - allow(metadata).to receive(:entries).and_return([]) - end - - it 'updates pages correctly' do - subject.execute - - expect(deploy_status.description).not_to be_present - expect(project.pages_metadatum).to be_deployed - end - end - - context "when size is above the limit" do - before do - allow(metadata).to receive(:total_size).and_return(size_limit + 1.megabyte) - allow(metadata).to receive(:entries).and_return([]) - end - - it 'limits the maximum size of gitlab pages' do - subject.execute - - expect(deploy_status.description) - .to match(/artifacts for pages are too large/) - expect(deploy_status).to be_script_failure - end - end -end